/* ========================================================================
   LAYER 00 · TOKENS — design custom properties (single :root block, verbatim)
   ======================================================================== */

/* --- source lines 5-39 --- */
/* ===== Custom Properties ===== */
:root {
  /* Palette — warm cream */
  --bg:        #F4F3EE;
  --bg-2:      #EDE8DE;
  --surface:   #E8E2D8;
  --border:    rgba(0,0,0,0.10);
  --text:      #1A1A18;
  --text-2:    #5A5650;
  --text-3:    #9A9590;

  /* Card outer colours (text on pill) */
  --apps-out:  #0d0d0d;
  --web-out:   #0d0d0d;
  --brand-out: #0d0d0d;
  --ai-out:    #ffffff;

  /* Card inner colours (pill background = exact card colour) */
  --apps-in:   #3676FF;
  --web-in:    #FFD146;
  --brand-in:  #ffffff;
  --ai-in:     #0E4C4B;

  /* Nav */
  --pill-bg:   #111;

  --r-card: clamp(14px, 2.8vw, 32px); /* scales with viewport so corners stay proportional as cards shrink */
  --r-frame: 4px;

  --nav-h: 56px;

  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
}

/* ========================================================================
   LAYER 01 · RESET & BASE — box model, html/body, links, images, selection, focus
   ======================================================================== */

/* --- source lines 40-74 --- */
/* ===== Reset ===== */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  /* Belt-and-braces horizontal-scroll fix for iOS Safari, which historically
     ignored `overflow-x: clip` on body. `hidden` on <html> doesn't break
     position:fixed (that's a body-level pitfall), and clamps the document
     width to the viewport. */
  overflow-x: hidden;
  width: 100%;
}

body {
  background-color: var(--bg);
  background-image: radial-gradient(circle, rgba(0,0,0,0.18) 1px, transparent 1px);
  background-size: 28px 28px;
  transition: background-color 0.15s ease;
  color: var(--text);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip; /* clip (not hidden) — prevents horizontal bleed without making body a scroll container, which would break position:fixed children */
  width: 100%;
  max-width: 100vw;
  padding-bottom: 0;
}

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

::selection { background: rgba(245,196,64,0.35); }
:focus-visible { outline: 2px solid #3676FF; outline-offset: 3px; border-radius: 3px; }

/* ========================================================================
   LAYER 02 · GLOBAL TYPE & MOTION PRIMITIVES — fixed wordmark, hero type, scroll-reveal split-text
   ======================================================================== */

/* --- source lines 75-110 --- */
/* ======================================================
   LOGO
   ====================================================== */
.logo {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(1.3rem, 2vw, 1.8rem);
  font-weight: 400;
  letter-spacing: -0.02em;
  color: var(--text-2);
  display: block;
  position: fixed;
  top: 40px;
  /* Push the logo 15 vw outward (toward the viewport's left edge) from
     the calculated --logo-left anchor — gives the lockup more
     breathing room while keeping a sensible min inset on small
     viewports. */
  left: clamp(16px, 2vw, 36px);
  z-index: 9100;
  margin-bottom: 0;
  transform-origin: top left;
  transition: transform 0.35s var(--ease-out);
}
.logo--scrolled {
  transform: scale(0.6);
}
/* Mobile: shrink by 30% on scroll (less aggressive than the desktop 0.6).
   Keeps the wordmark legible in the corner while still settling out of the
   way as the user scrolls. */
@media (max-width: 699px) {
  .logo--scrolled { transform: scale(0.7); }
}
/* Canvas open — logo is moved into the overlay by JS so it renders above canvas art. */
body[data-card] .logo {
  z-index: 9100;
}

/* --- source lines 111-180 --- */
/* ======================================================
   HERO
   ====================================================== */
.hero {
  /* Fill the viewport so the content block sits vertically centred */
  height: 100dvh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  box-sizing: border-box;
  /* Top padding clears the fixed logo; bottom gives breathing room */
  padding: 96px 28px 80px;
}

.hero-text {
  margin-bottom: 36px;
}

/* Hero scroll-in entrance */
.hero-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}
.hero-word.is-in {
  opacity: 1;
  transform: translateY(0);
}

h1 {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 400;
  font-size: clamp(2rem, 5vw, 3.8rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--text);
  margin-bottom: 20px;
}

/* Magnetic text — perspective so rotationY looks 3-D */
.magnetic-text {
  perspective: 700px;
  transform-style: preserve-3d;
}
.magnetic-text .char {
  display: inline-block;
  will-change: transform;
  cursor: default;
}

.hero-sub {
  font-size: 1.32rem;
  color: var(--text-2);
  font-weight: 400;
  line-height: 1.65;
  max-width: 75%;
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.hero-sub.is-in {
  opacity: 1;
  transform: translateY(0);
}
@media (max-width: 768px) {
  .hero-sub { font-size: 0.99rem; }
}

/* --- source lines 181-193 --- */
/* ===== Generic scroll-reveal for section headings =====
   JS splits text into .sr-word spans, groups by line, and wobbles each line in.
   CSS just provides the initial hidden state; transitions are handled by WAAPI. */
.scroll-reveal {
  opacity: 0;
}

/* Word spans inserted by scroll-reveal JS */
.sr-word {
  display: inline-block;
  white-space: nowrap;
}

/* ========================================================================
   LAYER 03 · DISCIPLINE CARD SYSTEM — .cards-frame / .cards-row (hero card deck + resize handles)
   ======================================================================== */

/* --- source lines 194-258 --- */
/* ===== Cards Frame ===== */
.cards-frame {
  position: relative;
  border: 1px solid rgba(0,0,0,0.15);
  border-radius: var(--r-frame);
  padding: 20px 16px 16px;
  transition: border-color 0.25s var(--ease-out);
}
/* Cards have been removed from this frame — hide the empty container
   on the home page so the border/handles don't render. */
.hero #cards-frame { display: none !important; }

/* Hide frame border when hovering or a card is active */
.cards-frame:has(.card:hover),
.cards-frame:has(.card.active) {
  border-color: transparent;
}

/* Corner handles — shared styles */
.handle {
  position: absolute;
  width: 9px;
  height: 9px;
  background: #B8B2A8;
  border-radius: 1px;
  opacity: 0;
  transition: opacity 0.25s var(--ease-out);
  pointer-events: none;
  z-index: 6;
}
.h-tl { top: -5px;  left: -5px; }
.h-tr { top: -5px;  right: -5px; }
.h-bl { bottom: -5px; left: -5px; }
.h-br { bottom: -5px; right: -5px; }

/* Frame handles: visible by default, interactive for column-drag */
.cards-frame > .handle {
  opacity: 1;
  pointer-events: all;
  cursor: ew-resize;
}
/* Expanded invisible hit area so they're easy to grab */
.cards-frame > .handle::before {
  content: '';
  position: absolute;
  inset: -10px;
}
.cards-frame:has(.card:hover) > .handle,
.cards-frame:has(.card.active) > .handle { opacity: 0; }

/* Card handles: show on hover or active */
.card:hover .handle,
.card.active .handle { opacity: 1; }

/* Card selection border: show only on active (selected) */
.card.active::before {
  content: '';
  position: absolute;
  inset: -1px;
  border: 1px solid rgba(0,0,0,0.22);
  border-radius: calc(var(--r-card) + 1px);
  pointer-events: none;
  z-index: 5;
}

/* --- source lines 259-426 --- */
/* ===== Cards Row ===== */
.cards-row {
  display: flex;
  gap: 10px;
  justify-content: stretch;
}

/* Single card */
.card {
  flex: 1;
  min-width: 126px; /* cards don't shrink below their natural desktop width */
  border-radius: var(--r-card);
  display: flex;
  flex-direction: column;
  cursor: pointer;
  position: relative;
  container-type: inline-size; /* enables cqi units → label font scales with card width */
  transition: transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out);
  user-select: none;
}

.card:nth-child(1) { transform: rotate(-6deg) translateY(4px);  animation: card-in-1 0.75s cubic-bezier(0.34,1.56,0.64,1) both; animation-delay: 0.05s; }
.card:nth-child(2) { transform: rotate(5deg)  translateY(-6px); animation: card-in-2 0.75s cubic-bezier(0.34,1.56,0.64,1) both; animation-delay: 0.15s; }
.card:nth-child(3) { transform: rotate(-4deg) translateY(4px);  animation: card-in-3 0.75s cubic-bezier(0.34,1.56,0.64,1) both; animation-delay: 0.25s; }
.card:nth-child(4) { transform: rotate(6deg)  translateY(-2px); animation: card-in-4 0.75s cubic-bezier(0.34,1.56,0.64,1) both; animation-delay: 0.35s; }

@keyframes card-in-1 {
  from { transform: rotate(-6deg) translateY(140px); opacity: 0; }
  to   { transform: rotate(-6deg) translateY(4px);   opacity: 1; }
}
@keyframes card-in-2 {
  from { transform: rotate(5deg)  translateY(140px); opacity: 0; }
  to   { transform: rotate(5deg)  translateY(-6px);  opacity: 1; }
}
@keyframes card-in-3 {
  from { transform: rotate(-4deg) translateY(140px); opacity: 0; }
  to   { transform: rotate(-4deg) translateY(4px);   opacity: 1; }
}
@keyframes card-in-4 {
  from { transform: rotate(6deg)  translateY(140px); opacity: 0; }
  to   { transform: rotate(6deg)  translateY(-2px);  opacity: 1; }
}

/* Hero-mode hover only — body:not([data-card]) ensures JS fan transforms
   are never overridden by !important when a canvas is open */
body:not([data-card]) .card:hover {
  transform: rotate(0deg) translateY(-6px) scale(1.02) !important;
  z-index: 5;
}

.card.active {
  transform: rotate(0deg) translateY(-4px) !important;
  z-index: 4;
}

/* Card inner area — aspect-ratio keeps cards proportional at any width */
.card-inner {
  border-radius: calc(var(--r-card) - 10px);
  margin: 20px;
  aspect-ratio: 4/3;
  overflow: hidden;
}

/* Card image — fills inner stage */
.card-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Lottie inner — keeps card's background tint, centres the player */
.card-inner--lottie {
  display: flex;
  align-items: center;
  justify-content: center;
}
.card-inner--lottie dotlottie-player {
  width: 100%;
  height: 100%;
}

/* Video inner — img visible by default, video fades in on card hover */
.card-inner--video {
  position: relative;
  padding: 0;
}
.card-inner--video .card-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: opacity 0.35s ease;
}
/* Hide the poster image while the card is hovered so any video letter-
   boxing or alpha edge can't reveal the still beneath it. */
.card:hover .card-inner--video .card-img { opacity: 0; }
.card-video {
  position: absolute;
  /* Slight overflow + scale so the video fully covers the rounded card
     stage edge — kills the thin background-coloured hairline that can
     appear at the inner corners on certain aspect mismatches. */
  inset: -2px;
  width: calc(100% + 4px);
  height: calc(100% + 4px);
  object-fit: cover;
  display: block;
  opacity: 0;
  transform: scale(1.02);
  transform-origin: center;
  transition: opacity 0.35s ease;
}
.card:hover .card-video {
  opacity: 1;
}

/* Card label — font scales with card width so all 4 labels stay on one line together */
.card-label {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: min(13cqi, 2.565rem); /* 13% of card width; equal-width cards = all same size */
  font-weight: 400;
  letter-spacing: 0.01em;
  padding: 4px 20% 16px 20px; /* 20% right keeps longest label clear of edge */
  display: block;
}

/* Bottom-right arrow badge — same style as canvas thumb hover hint */
.card-hint {
  position: absolute;
  bottom: 14px;
  right: 14px;
  width: 32px;
  height: 32px;
  background: #fff;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: scale(0.5);
  transition: opacity 0.18s var(--ease-out), transform 0.22s var(--ease-spring);
  pointer-events: none;
  color: var(--text);
  z-index: 5;
}
.card--brand .card-hint { background: #e8e8e8; }
.card:hover .card-hint {
  opacity: 1;
  transform: scale(1);
}

/* Card colour overrides */
.card--apps             { background: #3676FF; }
.card--apps .card-inner { background: #3676FF; }
.card--apps .card-label { color: #fff; }

.card--websites             { background: #FFD146; }
.card--websites .card-inner { background: #FFD146; }
.card--websites .card-label { color: #000; }

.card--brand             { background: #fff; }
.card--brand .card-inner { background: #fff; }
.card--brand .card-label { color: #000; }

.card--ai             { background: #0E4C4B; }
.card--ai .card-inner { background: #0E4C4B; }
.card--ai .card-label { color: #fff; }

/* ========================================================================
   LAYER 04 · WORK PANEL — sticky title column + folio grid, filters, rows/tiles view toggle
   ======================================================================== */

/* --- source lines 427-535 --- */
/* ======================================================
   WORK PANEL — sticky title left, scrolling grid right
   ====================================================== */

.work-panel {
  display: flex;
  align-items: flex-start;
  padding: 80px 28px 120px;
  gap: 60px;
  transition: gap 0.4s var(--ease-out);
}

/* Tile mode: header stacks above full-width grid */
.work-panel--tiles {
  flex-direction: column;
  gap: 32px;
}

/* Left column: sticky title — pins to vertical centre of viewport */
.work-panel__left {
  position: sticky;
  top: 50vh;
  transform: translateY(-50%);
  flex: 0 0 auto;
  width: clamp(220px, 26vw, 320px);
  transition: width 0.4s var(--ease-out), max-width 0.4s var(--ease-out);
}

.work-panel__left .about-title {
  margin-bottom: 24px;
}

/* Tile mode: left col becomes full-width header strip */
.work-panel--tiles .work-panel__left {
  position: static;
  transform: none;
  top: auto;
  width: 100%;
}

.work-panel--tiles .about-title {
  max-width: 800px;
  margin-bottom: 28px;
}

/* Controls wrapper: holds filters + view toggle */
.work-panel__controls {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* Tile mode: filters + toggle collapse into one row */
.work-panel--tiles .work-panel__controls {
  flex-direction: row;
  align-items: center;
  gap: 14px;
  margin-bottom: 8px;
}

.work-panel--tiles .work-view-toggle {
  margin-top: 0;
}

/* Filter buttons */
.work-filters {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 4px;
}

.work-panel--tiles .work-filters {
  flex-wrap: nowrap;
  margin-top: 0;
}

/* Hollow active filter in tile mode */
.work-panel--tiles .work-filter--active {
  background: transparent;
  border-color: var(--text-1);
  color: var(--text-1);
  font-weight: 400;
}

.work-filter {
  background: transparent;
  border: 1.5px solid rgba(26,26,24,0.3);
  border-radius: 999px;
  color: var(--text-1);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  padding: 7px 18px;
  cursor: pointer;
  transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease;
}

.work-filter:hover {
  border-color: rgba(26,26,24,0.7);
}

.work-filter--active {
  background: var(--text-1);
  border-color: var(--text-1);
  color: var(--bg-page);
}

/* --- source lines 536-610 --- */
/* ===== Industry sub-filters — hollow pills =====
   A second tier of filters under .work-filters. Stays hollow even
   when active (border thickens + colour darkens) so they read as
   secondary to the main category filters above. Final pill in the
   row (.industry-filter--reset, label "Show all") clears the
   industry filter and surfaces every project again. */
.industry-filters {
  display: flex !important;
  flex-wrap: wrap;
  gap: 10px;
  /* Sits directly under the .process-hed-row H2 (e.g. "Product
     design, system, architecture…") and inherits its column —
     nudge top spacing so the row doesn't crowd the title. */
  margin: 24px 0 0 0;
  max-width: 90%;
  position: relative;
  z-index: 750;
}
@media (max-width: 699px) {
  .industry-filters { margin: 14px 16px 0; gap: 6px; }
}
/* Industry filter pill — mirrors `.faq-more-btn` exactly so the
   pill row reads as part of the same visual family as the
   "Show more questions" button. Inter sans-serif (not monospace),
   transparent fill, 1.5 px hairline border, 100 px radius. */
.industry-filter {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: 1.5px solid var(--border);
  border-radius: 100px;
  padding: 10px 22px;
  font-family: 'Inter', sans-serif;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--text-2);
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.industry-filter:hover {
  border-color: var(--text);
  color: var(--text);
}
.industry-filter--active {
  border-color: var(--text);
  color: var(--text);
}

/* Hide the industry-filters row entirely unless the "Product
   design" intro-chip (data-intro-filter="apps") is active —
   industries only apply to the apps discipline. The :has() check
   on the document means the row reveals as soon as the user
   clicks the Product Design chip and hides again on any other
   discipline. */
.industry-filters { display: none !important; }
:root:has(.intro-chip[data-intro-filter="apps"].is-active) .industry-filters,
body:has(.intro-chip[data-intro-filter="apps"].is-active) .industry-filters {
  display: flex !important;
}
/* Show-all pill — sits inline beside the industry pills (no
   auto-margin push to the right). Slightly dimmer text so it
   still reads as a reset action. */
.industry-filter--reset {
  color: rgba(26,26,24,0.6);
}
.industry-filter--reset:hover {
  color: var(--text-1);
}
/* Hidden by the industry filter — kept separate from the
   category filter's `.work-thumb--hidden` so both filters can be
   layered, and so the cap counter can skip industry-filtered
   thumbs when computing what counts toward the 11-thumb limit. */
.work-thumb--industry-hidden { display: none !important; }

/* --- source lines 611-664 --- */
/* ===== Work view toggle (rows / tiles) ===== */
.work-view-toggle {
  display: flex;
  gap: 6px;
  margin-top: 16px;
}

.work-view-btn {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 1.5px solid rgba(26,26,24,0.18);
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: rgba(26,26,24,0.4);
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.work-view-btn:hover {
  border-color: rgba(26,26,24,0.5);
  color: rgba(26,26,24,0.8);
}

.work-view-btn--active {
  background: rgba(26,26,24,0.08);
  border-color: rgba(26,26,24,0.3);
  color: rgba(26,26,24,0.85);
}


/* Hidden filtered thumbnails */
.work-thumb.work-thumb--hidden {
  display: none;
}

/* Right column: single-column grid */
.work-panel__right {
  flex: 1 1 auto;
  min-width: 0;
}

.work-panel__grid {
  display: grid;
  grid-template-columns: min(700px, 100%);
  gap: 40px;
  /* Left-align with the Trusted-By heading column (15vw) so the
     "Recent completed projects" title and the cards share an edge. */
  margin-left: 15vw;
  transition: gap 0.4s var(--ease-out);
}

/* --- source lines 665-893 --- */
/* ===== Tile view override ===== */
.work-panel--tiles .work-panel__right {
  width: 100%;
}

.work-panel__grid--tiles {
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin: 0;
  width: 100%;
}

.work-panel__grid--tiles .work-thumb {
  border-radius: 10px;
}

.work-panel__grid--tiles .work-thumb--tall {
  grid-row: span 2;
}

.work-panel__grid--tiles .work-thumb--tall img {
  height: 100%;
  object-fit: cover;
}

/* Desktop-only tall variant — applies the same span-2 treatment but only
   above the mobile breakpoint, so a portrait-cropped tile (e.g. Supapix)
   stays a normal single-row tile on small screens. */
@media (min-width: 700px) {
  .work-panel__grid--tiles .work-thumb--tall-desktop {
    grid-row: span 2;
  }
  .work-panel__grid--tiles .work-thumb--tall-desktop img {
    height: 100%;
    object-fit: cover;
  }
  .work-panel__grid--tiles .work-thumb--tall-desktop video.work-thumb__video {
    height: 100%;
    object-fit: cover;
  }
}

/* Tile-in animation */
@keyframes tile-in {
  from { opacity: 0; transform: scale(0.94) translateY(10px); }
  to   { opacity: 1; transform: none; }
}

.work-panel__grid--tiles .work-thumb:not(.work-thumb--hidden) {
  animation: tile-in 0.35s var(--ease-out) both;
}
.work-panel__grid--tiles .work-thumb:nth-child(2)  { animation-delay:  35ms; }
.work-panel__grid--tiles .work-thumb:nth-child(3)  { animation-delay:  70ms; }
.work-panel__grid--tiles .work-thumb:nth-child(4)  { animation-delay: 105ms; }
.work-panel__grid--tiles .work-thumb:nth-child(5)  { animation-delay: 140ms; }
.work-panel__grid--tiles .work-thumb:nth-child(6)  { animation-delay: 175ms; }
.work-panel__grid--tiles .work-thumb:nth-child(7)  { animation-delay: 210ms; }
.work-panel__grid--tiles .work-thumb:nth-child(8)  { animation-delay: 245ms; }
.work-panel__grid--tiles .work-thumb:nth-child(9)  { animation-delay: 280ms; }
.work-panel__grid--tiles .work-thumb:nth-child(10) { animation-delay: 315ms; }
.work-panel__grid--tiles .work-thumb:nth-child(11) { animation-delay: 350ms; }
.work-panel__grid--tiles .work-thumb:nth-child(12) { animation-delay: 385ms; }
.work-panel__grid--tiles .work-thumb:nth-child(13) { animation-delay: 420ms; }

/* Individual thumbnails */
.work-thumb {
  display: block;
  position: relative;
  border-radius: 14px;
  overflow: hidden;
  text-decoration: none;
  background: var(--surface);
  transition: transform 0.25s var(--ease-out);
  /* iOS Safari: stop the browser hesitating between "is this a tap?" and
     "is this a scroll?" — `manipulation` removes the 300ms double-tap-zoom
     delay AND keeps native vertical scrolling responsive when a touch
     starts on a thumb. Fixes the "scroll gets stuck over the folio" bug. */
  touch-action: manipulation;
}

.work-thumb:hover {
  transform: translateY(-4px);
}

/* Top-right expand arrow removed. */

.work-thumb img {
  display: block;
  width: 100%;
  aspect-ratio: 900 / 630;
  object-fit: contain;
}

.work-thumb__cat { display: none; }

.work-thumb__label {
  position: absolute;
  bottom: 12px;
  left: 12px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: #fff;
  background: rgba(0,0,0,0.48);
  backdrop-filter: blur(6px);
  padding: 4px 10px;
  border-radius: 20px;
  pointer-events: none;
  z-index: 4; /* above video(1), reveal canvas(2) */
}

/* Autoplay video overlay — sits above static img, below label */
.work-thumb__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.4s ease;
}
.work-thumb__video.is-playing {
  opacity: 1;
}

/* Pixel-reveal canvas overlay disabled — glass effect removed */
.work-thumb__reveal {
  display: none !important;
}

/* Work-section title banner — appears above the folio when a user
   clicks an intro chip on the homepage. Hidden by default. Sits
   directly above the work-zoom with breathing room. */
.work-title-banner {
  display: none;
  /* Left margin matches the Trusted-By heading column (15vw + 100 px). */
  margin: 260px 28px 28px calc(15vw + 100px);
  padding: 0;
  max-width: 70vw;
}
.work-title-banner.is-shown { display: block; }
/* When banner is shown, reduce the work-zoom's top padding so the
   banner doesn't double up with the section's own top spacing. */
body.has-work-title .work-zoom[data-view="rows"] {
  padding-top: 40px !important;
}
.work-title-banner__text {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(0.79rem, 3.1vw, 3.06rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.02;
  color: var(--text);
  text-align: left;
  margin: 0;
}
@media (max-width: 699px) {
  /* Banner sits 40 px above the first work card. Banner has no
     bottom margin; zoom strips its padding-top; the sticky rail
     above the grid is collapsed; the grid itself carries a 40 px
     padding-top so the gap lands at exactly 40 px (not 24 + 25 +
     padding stacking that the earlier rules produced ≈ 69 px). */
  .work-title-banner {
    margin: 0 16px 0 !important;
  }
  body.has-work-title .work-zoom[data-view="rows"] {
    padding-top: 0 !important;
  }
}
/* Banner-to-first-thumb gap (40 px) is enforced inside the
   `@media (max-width: 699px)` block further down, after the
   `.work-zoom__grid-host { padding: 0 }` reset — source order
   matters here since specificity ties. */

/* Plain Trusted-By headline — matches the home h1 (.intro-giant--multiline)
   in size, weight, leading and left-alignment. */
.trusted-hed--plain {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(0.79rem, 3.1vw, 3.06rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.02;
  color: var(--text);
  text-align: left;
  /* Shifted 100 px further right so every section H2 aligns with
     the indented work-thumb column. */
  margin: 0 28px 60px calc(15vw + 100px);
  padding: 0;
  max-width: min(100%, calc(85vw - 128px));
}
.trusted-hed--plain .hero-word { display: inline-block; margin-right: 0.25em; }

/* When the Trusted-By plain heading sits inside the .hero section
   (the "Read more about process." instance), compensate for the
   hero's left padding (17.5vw on desktop / 28px on mobile) so the
   text aligns at the same 10 vw column as the trusted heading. */
.hero .trusted-hed--plain {
  margin-left: 0;
}
@media (min-width: 900px) {
  .hero .trusted-hed--plain {
    margin-left: calc(15vw - 17.5vw + 100px);
  }
}
@media (max-width: 699px) {
  .trusted-hed--plain {
    font-size: clamp(0.72rem, 3.96vw, 1.62rem);
    margin: 0 16px 32px;
  }
}

/* (Ask-AI top-right override moved to the bottom of the file so it
   wins against the original .ask-ai-btn rule defined later in this
   stylesheet — same specificity, last-rule wins.) */

/* Mobile: stack vertically */
@media (max-width: 699px) {
  .work-panel {
    flex-direction: column;
    gap: 32px;
    padding: 80px 20px 80px;  /* match other section top padding */
  }
  .work-panel__left {
    position: static;
    width: 100%;
  }
}

/* ========================================================================
   LAYER 05 · CONTENT SECTIONS — part 1: .work (about), .about-block / process, trusted-by marquee
   ======================================================================== */

/* --- source lines 894-1084 --- */
/* ======================================================
   WORK SECTION
   ====================================================== */
.work {
  /* Left padding matches the 15vw + 100 px column. */
  padding: 80px 28px 4vh calc(15vw + 100px);
}
/* Also strip any centering on the about-block inside .work so its
   content starts at the section's left padding (= 10vw). */
.work .about-block {
  margin-left: 0 !important;
  margin-right: 0 !important;
  max-width: none !important;
}

.work.revealed {
  animation: work-reveal 0.6s var(--ease-out) both;
}

@keyframes work-reveal {
  from { opacity: 0; transform: translateY(32px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Connector from hero → work intro */
.connector-wrap--intro {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 0;
  margin-bottom: 20px;
}

.connector-svg {
  width: 200px;
  height: 120px;
  flex-shrink: 0;
  overflow: visible;
}

.work-intro {
  font-family: 'IBM Plex Mono', monospace;
  font-size: clamp(1.4rem, 3.5vw, 2rem);
  font-weight: 400;
  line-height: 1.3;
  color: var(--text-2);
  max-width: 380px;
  padding-top: 60px;
  align-self: center;
}

/* Work list */
.work-list {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* Between-project curves */
.between-curve {
  width: 100%;
  height: 100px;
  overflow: visible;
}
.between-curve svg {
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* Project item */
.project {
  display: grid;
  grid-template-columns: 1fr 48px 1fr;
  align-items: center;
  gap: 8px;
  padding: 12px 0;
}

.project--alt .project-info  { order: 1; }
.project--alt .project-connector { order: 2; }
.project--alt .project-visual { order: 3; }

/* On mobile, stack vertically */
@media (max-width: 640px) {
  .project {
    grid-template-columns: 1fr;
  }
  .project-connector { display: none; }
  .project--alt .project-info  { order: 1; }
  .project--alt .project-visual { order: 2; }
}

/* Project connector (vertical line) */
.project-connector {
  display: flex;
  justify-content: center;
  height: 100%;
  min-height: 200px;
}
.project-connector svg {
  width: 48px;
  height: 100%;
  overflow: visible;
}

/* Project visual frame */
.mockup-frame {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 28px 24px;
  min-height: 240px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ── Phone duo mockup ── */
.phones-duo {
  position: relative;
  width: 180px;
  height: 180px;
}

.phone {
  position: absolute;
  width: 80px;
  height: 148px;
  border: 1.5px solid rgba(0,0,0,0.12);
  border-radius: 14px;
  overflow: hidden;
  background: #1a2340;
}
.phone--back  { top: 20px; left: 4px;  transform: rotate(-7deg); z-index: 1; }
.phone--front { top: 8px;  right: 4px; transform: rotate(5deg);  z-index: 2; }
.phone-screen { width: 100%; height: 100%; padding: 8px 6px; }

.ps-bar       { height: 5px; border-radius: 3px; background: rgba(255,255,255,0.2); margin-bottom: 5px; }
.ps-bar--short { width: 55%; }
.ps-gap       { height: 10px; }
.ps-card      { border-radius: 6px; background: rgba(255,255,255,0.08); height: 48px; margin-bottom: 6px; }
.ps-card--sm  { height: 28px; }

/* ── Desktop mockup ── */
.desktop-mock { width: 240px; }
.desktop-screen {
  width: 100%;
  height: 148px;
  border: 1.5px solid rgba(0,0,0,0.12);
  border-radius: 8px;
  overflow: hidden;
}
.ds-nav { height: 16px; background: rgba(255,255,255,0.08); border-bottom: 1px solid rgba(255,255,255,0.05); }
.ds-hero { margin: 8px 10px 6px; height: 44px; border-radius: 5px; background: rgba(255,255,255,0.08); }
.ds-grid { display: flex; gap: 5px; padding: 0 10px; }
.ds-item { flex: 1; height: 48px; border-radius: 5px; background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.05); }

/* ── Brand mockup ── */
.brand-mock {
  width: 220px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 20px;
}
.bm-mark { width: 52px; height: 52px; border-radius: 10px; background: linear-gradient(135deg, #2B6FD4, #F5C440); margin-bottom: 16px; }
.bm-palette { display: flex; gap: 7px; margin-bottom: 14px; }
.bm-palette span { width: 28px; height: 28px; border-radius: 6px; border: 1px solid rgba(0,0,0,0.08); display: block; }
.bm-lines { display: flex; flex-direction: column; gap: 6px; }
.bm-line { height: 5px; border-radius: 3px; background: rgba(0,0,0,0.10); width: 80%; }
.bm-line--h { height: 8px; background: rgba(0,0,0,0.14); width: 100%; }
.bm-line--sm { width: 50%; }

/* Project info */
.project-info {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 8px 0;
}

.project-desc {
  font-family: 'IBM Plex Mono', monospace;
  font-size: clamp(1.1rem, 2.2vw, 1.4rem);
  font-weight: 400;
  line-height: 1.45;
  color: var(--text-2);
  max-width: 340px;
}

/* --- source lines 1085-1805 --- */
/* ======================================================
   ABOUT BLOCK — scrollable bio / history section
   ====================================================== */
.about-block {
  max-width: 660px;
  margin: 0 auto;
  padding: 72px 0 24px;
  position: relative; /* anchor for the curve SVG */
  overflow: visible;
}

/* ── "For the love of design" curved text ── */
.about-curve-svg {
  position: fixed;    /* pinned to viewport — guarantees path entry is always at screen bottom */
  bottom: 0;
  left: 0;
  width: 100%;
  height: 700px;
  overflow: visible;
  pointer-events: none;
  z-index: 6;
  opacity: 0;         /* JS controls visibility */
}

.about-curve-text {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 155px;
  font-weight: 400;
  fill: var(--text);
  letter-spacing: -3px;
}

.about-chip {
  display: inline-flex;
  align-items: center;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 1.05rem;
  padding: 5px 16px;
  border-radius: 20px;
  background: var(--surface);
  color: var(--text-2);
  margin-bottom: 32px;
  /* The .about-block is a flex column, which would otherwise stretch the
     chip to full width. Pin it to its natural content width and left-align. */
  align-self: flex-start;
  width: fit-content;
}

.about-title {
  font-family: 'Inter', sans-serif;
  font-size: clamp(2rem, 5vw, 3.8rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.08;
  color: var(--text);
  margin-bottom: 36px;
}

/* Heading + back-arrow row. The row's left edge sits at the 10 vw
   viewport column (matches body copy below). The toggle hangs to the
   LEFT of that column so the heading text itself starts at 10 vw,
   exactly above the loaded body copy. */
.process-hed-row {
  position: relative;
  /* Extra breathing room above so the process section sits clearly
     separated from the work-zoom rail / cards above it. */
  margin: 160px 0 0;
}
@media (min-width: 900px) {
  .process-hed-row { margin-left: calc(15vw - 17.5vw + 100px); margin-top: 200px; }
}
.process-hed-row .process-hed {
  margin-left: 0 !important;
}
.process-hed { display: block; }
.process-hed .process-hed__text { display: inline; }
.hero .process-toggle {
  display: none;
  position: absolute;
  top: 6px;                          /* optically centre on first heading line */
  right: 100%;                       /* sit immediately left of the row */
  margin-right: 14px;
  flex-shrink: 0;
}
/* On mobile the absolute toggle would go off-screen — stack it above
   the heading instead. */
@media (max-width: 899px) {
  .hero .process-toggle {
    position: static;
    margin: 0 0 14px;
  }
}

/* Chip picker below the process heading — displays a cloned copy of
   the 5 intro chips so the user can pick a discipline from the hero
   too. Hidden once a filter is active. */
.process-chips {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  margin: 28px 0 24px;
  max-width: 70vw;
}
.hero .process-chips { margin-left: 0; }
@media (min-width: 900px) {
  /* Align the discipline picker pills with the "More about process."
     heading column (15vw + 100 px from the viewport edge). */
  .hero .process-chips { margin-left: calc(15vw - 17.5vw + 100px); }
}
.process-chips.is-hidden { display: none; }

/* Read-more-about-process toggle button — black circle with white
   down-arrow, sits below the .process-hed inside the .hero. */
.process-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Shrunk 30% from the previous 44 / 16. */
  width: 31px;
  height: 31px;
  border-radius: 50%;
  background: #1A1A18;
  color: #fff;
  border: none;
  cursor: pointer;
  margin-left: 0;
  flex-shrink: 0;
  transition: transform 0.25s var(--ease-out), background 0.2s ease;
}
.process-toggle svg { width: 11px; height: 11px; }
.process-toggle[aria-expanded="true"] { transform: rotate(180deg); }
.process-toggle:hover { background: #2A2A28; }

/* "Process" eyebrow row — toggle + label, sits above the discipline
   heading when a filter is active. */
.process-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}
.process-eyebrow__label {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0;
  color: var(--text);
  /* Match the toggle circle height so the visual baselines line up
     when flex centres the row (eliminates the ~6 px lift caused by
     the smaller text's intrinsic line-box height). */
  line-height: 31px;
  display: inline-flex;
  align-items: center;
}
/* Hidden when no discipline is picked (the chip-picker state). The
   JS toggles toggle.style.display = 'none' → also hide the eyebrow. */
.process-eyebrow:has(> #process-toggle[style*="display: none"]) {
  display: none;
}
/* Toggle now sits ABOVE the heading; alignment handled in the
   .hero .process-toggle block above. */

/* Content entrance — fade + slide-up with a per-block stagger,
   mirroring the home h1 word-wobble entrance. */
@keyframes processPanelIn {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: none; }
}
.process-panel.is-revealing .ph-block {
  opacity: 0;
  animation: processPanelIn 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.process-panel.is-revealing .ph-block:nth-child(1) { animation-delay: 0ms; }
.process-panel.is-revealing .ph-block:nth-child(2) { animation-delay: 120ms; }
.process-panel.is-revealing .ph-block:nth-child(3) { animation-delay: 220ms; }
.process-panel.is-revealing .ph-block:nth-child(n+4) { animation-delay: 320ms; }
/* Also fade the heading update so the new title settles in with the body. */
.process-hed.is-revealing .process-hed__text {
  display: inline-block;
  animation: processPanelIn 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* Expandable content panel — left padding matches the heading's
   10 vw column. */
.process-panel {
  display: block;
  margin: -40dvh 0 0;
  padding: 16px 28px 48px 28px !important;
  position: relative;
  z-index: 1;
}
.process-panel[hidden] { display: none; }
@media (min-width: 900px) {
  .process-panel {
    margin-top: -40dvh;
    /* Left padding matches the process eyebrow / heading column
       (15vw) so the description, diagram and pill clusters all
       align under the toggle + "Process" label. */
    padding: 16px 10vw 64px calc(15vw + 100px) !important;
  }
}
.process-panel .ph-block {
  margin: 0 0 56px;
  padding: 0;
}
/* Brute-force reset: every element inside the panel gets zero left
   inset so all body copy aligns with the panel's left padding edge. */
.process-panel,
.process-panel * {
  box-sizing: border-box;
}
.process-panel * {
  margin-left: 0 !important;
  padding-left: 0 !important;
  max-width: none !important;
  text-indent: 0 !important;
}

/* Single-column flow — description first, FAQ accordions follow in a
   full-width row that bleeds to the page's left edge (escapes the
   panel's left padding via negative margin). */
.process-panel > * {
  display: block;
}
.process-panel .ph-block:not(:first-child) {
  margin-left: calc(-1 * (10vw)) !important;   /* break out to viewport left edge */
  margin-right: calc(-1 * (10vw)) !important;
  padding-left: 28px !important;
  padding-right: 28px !important;
}
@media (max-width: 899px) {
  .process-panel .ph-block:not(:first-child) {
    margin-left: -28px !important;
    margin-right: -28px !important;
    padding-left: 16px !important;
    padding-right: 16px !important;
  }
}
.process-panel .ph-block { margin-bottom: 18px !important; }
.process-panel .about-block { margin-bottom: 32px !important; }
.process-panel .faq-section {
  margin-bottom: 0 !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  padding-left: 0 !important;
  padding-right: 0 !important;
  max-width: none !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
}
.process-panel .faq-inner {
  padding: 0 !important;
  margin: 0 !important;
}
.process-panel .about-body { margin-bottom: 28px !important; }
.process-panel .about-body p { margin: 0 0 18px !important; }
.process-panel .faq-list { list-style: none !important; }
/* Pills lay out in horizontal rows, wrapping naturally onto the next
   line when the row fills up. Each pill is content-width by default;
   on hover/open it expands to fill its row. */
.process-panel .faq-list {
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: wrap !important;
  align-items: flex-start !important;
  gap: 10px !important;
}
.process-panel .faq-item {
  width: auto !important;
  max-width: 100% !important;
  display: inline-block !important;
}
.process-panel .faq-q {
  width: auto !important;
  display: inline-flex !important;
}
.process-panel .faq-q__text {
  flex: 0 0 auto !important;
}
/* When a pill opens, expand to ~1/3 of the viewport (not the full
   pill cluster width). Title indent bumped so the heading aligns
   with the body copy below it. */
.process-panel .faq-item:has(.faq-q[aria-expanded="true"]) {
  width: min(33vw, 480px) !important;
  display: block !important;
  transition: width 220ms ease;
}
.process-panel .faq-item:has(.faq-q[aria-expanded="true"]) .faq-q {
  width: 100% !important;
  display: flex !important;
  /* Match the body's 28 px left inset so the title and body copy
     align on the same vertical line. */
  padding-left: 28px !important;
}
.process-panel .faq-item:has(.faq-q[aria-expanded="true"]) .faq-q__text {
  flex: 1 1 auto !important;
}

/* Accordion pills — match the home .intro-chip type treatment so the
   accordion titles read at the same weight/scale as the discipline
   pills. Sizes shrunk ~25% from the previous defaults. */
.process-panel .faq-q {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif !important;
  /* Matches the FAQ section pills (15.75 / 56 / 16-22 / 25 badge). */
  font-size: 15.75px !important;
  font-weight: 500 !important;
  letter-spacing: -0.005em !important;
  line-height: 1.25 !important;
  padding: 16px 22px !important;
  align-items: center !important;
  min-height: 56px;
}
.process-panel .faq-q__text {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif !important;
  font-size: 15.75px !important;
  font-weight: 500 !important;
  letter-spacing: -0.005em !important;
  line-height: 1.25 !important;
}
.process-panel .faq-icon {
  width: 25px !important;
  height: 25px !important;
}
.process-panel .faq-icon svg {
  width: 13px !important;
  height: 13px !important;
}
/* Chevron separator inside the H4 cluster labels. */
.process-panel .ph-title-chevron {
  opacity: 0.55;
  flex-shrink: 0;
}

/* FAQs collapsible block — black pill button with white chevron-down. */
.process-panel .ph-block--faqs {
  margin-top: 8px !important;
}
.process-panel .ph-faqs-toggle {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  background: #111111;
  color: #ffffff;
  border: none;
  border-radius: 999px;
  /* Extra inset on the left/right so the label has breathing room.
     !important is needed to override a `.process-panel *` reset. */
  padding: 12px 24px 12px 28px !important;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.25;
  cursor: pointer;
  transition: background 0.2s ease;
}
.process-panel .ph-faqs-toggle:hover { background: #000000; }
.process-panel .ph-faqs-toggle__chev {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.25s ease;
}
.process-panel .ph-faqs-toggle[aria-expanded="true"] .ph-faqs-toggle__chev {
  transform: rotate(180deg);
}
.process-panel .ph-faqs-panel {
  margin-top: 18px;
}
/* Body inside open accordion — restore left padding so it aligns with
   the pill's title text (28 px inset), not the pill's outer edge.
   Hidden answers use display:none (not just max-height) so their
   content width doesn't pad out the pill's intrinsic width. */
.process-panel .faq-a { padding-left: 28px !important; padding-right: 28px !important; }
.process-panel .faq-a > * { padding-left: 0 !important; }
.process-panel .faq-a ul { padding-left: 1.2em !important; }
.process-panel .faq-q[aria-expanded="false"] + .faq-a { display: none !important; }
.process-panel .faq-q[aria-expanded="true"] + .faq-a { display: block !important; }
.process-panel .ph-block .faq-title,
.process-panel .ph-block h2,
.process-panel .ph-block h4,
.process-panel .ph-block section.faq-section > .faq-inner > .faq-title {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif !important;
  font-size: 18px !important;
  font-weight: 500 !important;
  letter-spacing: -0.01em !important;
  line-height: 1.3 !important;
  /* +20 px padding under the H4 cluster headings (was 14). */
  margin: 0 0 34px !important;
  color: var(--text) !important;
  opacity: 1 !important;
  text-align: left !important;
  display: inline-flex !important;
  align-items: center !important;
  gap: 8px !important;
  /* Cancel the calc-based break-out margin inherited from the
     section.faq-section override (which pushes the heading to the
     viewport's 15vw column — wrong inside the panel grid). */
  margin-left: 0 !important;
  margin-right: 0 !important;
  max-width: none !important;
  width: auto !important;
}
.process-panel .faq-list { list-style: none; padding: 0; margin: 0; }
.process-panel .faq-q,
.process-panel .faq-a { color: var(--text); }
.process-panel .about-block { max-width: none; padding: 0; }

/* Process Diagram floats to the right of the description column. */
.process-panel .ph-diagram-wrap {
  width: 100%;
  margin: 0;
}
/* New layout: top row puts description column (left, ~30 % wide)
   beside the Process Diagram (right). Pill clusters sit full-width
   below, stacked. Stacks vertically on narrow viewports. */
.process-panel .ph-stack {
  display: flex;
  flex-direction: column;
  gap: 40px;
}
@media (min-width: 900px) {
  .process-panel .ph-stack {
    display: grid;
    grid-template-columns: minmax(220px, 30%) 1fr;
    column-gap: 48px;
    /* Row-gap sized so the second pill cluster sits ~60 px below the
       last pill of the first cluster. */
    row-gap: 42px;
    align-items: start;
  }
  /* Description block — left column, row 1. Pushed 50 px down so
     it sits below the eyebrow + heading with breathing room. */
  .process-panel .ph-stack > .ph-block--intro {
    grid-column: 1;
    grid-row: 1;
    margin-top: 50px;
  }
  /* Diagram — right column, row 1. Matched 50 px push-down. */
  .process-panel .ph-stack > .ph-diagram-wrap {
    grid-column: 2;
    grid-row: 1;
    margin-top: 50px;
  }
  /* Pill clusters and the FAQs block — full width, rows below the
     intro/diagram row, stacked. */
  .process-panel .ph-stack > .ph-block--pills,
  .process-panel .ph-stack > .ph-block--faqs {
    grid-column: 1 / -1;
    margin-top: 0 !important;
  }
}
.process-panel .ph-block--intro,
.process-panel .ph-block--intro .about-block {
  margin-bottom: 0 !important;
}
/* Cancel the legacy "break out to viewport edge" rule (line ~1176)
   for any .ph-block that lives inside a .ph-stack — those need to
   stay within the grid container so the diagram, description and
   pill columns share the same L/R margins. */
.process-panel .ph-stack > .ph-block,
.process-panel .ph-stack > .ph-block:not(:first-child) {
  margin-left: 0 !important;
  margin-right: 0 !important;
  padding-left: 0 !important;
  padding-right: 0 !important;
}
.process-panel .ph-block--intro,
.process-panel .ph-block--intro .about-block,
.process-panel .ph-block--intro .about-body {
  max-width: 100% !important;
  width: 100% !important;
}
.process-panel .ph-diagram {
  display: block;
  width: 100%;
  height: auto;
}
/* Match the hero's 17.5 vw left padding (desktop) so inline content
   reads alongside the heading instead of going edge-to-edge. */
.process-panel { padding: 0 28px 0 28px; }
@media (min-width: 900px) {
  .process-panel { padding: 0 17.5vw; }
}

/* H1 promoted into the about-block (above the .about-chip).
   Matches .trusted-hed--plain exactly: same font-size clamp, same
   left-alignment at the viewport's 10 vw column (breaks out of the
   .about-block's centered 660 px container). */
.about-h1 {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(0.79rem, 3.1vw, 3.06rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.02;
  color: var(--text);
  text-align: left;
  margin-top: 0;
  margin-bottom: 24px;
  margin-left: calc(50% - 50vw + 15vw + 100px);
  margin-right: calc(50% - 50vw + 15vw);
}
@media (max-width: 699px) {
  .about-h1 {
    font-size: clamp(0.72rem, 3.96vw, 1.62rem);
    margin-left: calc(50% - 50vw + 16px);
    margin-right: calc(50% - 50vw + 16px);
  }
}

/* Two-column variant — Experience card on the left, meta rows on the right. */
/* Single-column meta block — the avatar card is lifted out of this
   grid and pinned top-right of the parent .about-block (see rules
   below), so the Speciality / Experience rows now fall directly
   under the title + chip on the left. */
.about-meta--with-card {
  display: flex !important;
  flex-direction: column;
  gap: 18px;
  padding-bottom: 40px;
  margin-bottom: 40px;
}
.about-meta--with-card .about-meta__rows {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
/* Lift the avatar image to the top-right of the .about-block so it
   sits up alongside the title, while the text column (title, chip,
   meta rows, buttons) all left-align underneath. */
.work .about-block { position: relative; }
/* Desktop layout — title + meta on the left, avatar card floated
   absolutely on the right. Only kicks in at ≥1100 px so tablets
   (≤1024 px landscape) and small laptops get the stacked variant
   below instead of having the meta column squeezed to <200 px by
   the 720 px right-padding. */
@media (min-width: 1100px) {
  .work .about-block {
    padding-right: 720px;
  }
  .work .about-meta--with-card .about-meta__card {
    position: absolute;
    /* Dropped 30% down the about-block — sits lower alongside the
       chip / Speciality / Experience rows instead of crowning the
       title. */
    top: 30%;
    right: 15vw;          /* pull the photo in to match the L/R 15vw column */
    width: 360px;
    margin: 0;
  }
  /* Cap the Speciality / Experience meta rows to 75 % width so the
     long "Design Engineer, UX, Product Design …" string folds onto
     multiple lines instead of bumping into the avatar card. */
  .work .about-meta--with-card .about-meta-item {
    max-width: 75%;
    width: 75%;
    white-space: normal;
    overflow-wrap: anywhere;
  }
}

/* Mobile + tablet stacked layout (<1100 px). The DOM order is
   already title → chip → image → Speciality/Experience → buttons
   → description body, which IS the stack we want; we just need
   everything to flow at 90 % width with normal wrapping and drop
   the heading's `white-space: nowrap`. */
@media (max-width: 1099px) {
  .work .about-block {
    padding-right: 0;
  }
  .work .about-h1 {
    /* The default rule forces nowrap so the title sits on one line
       on desktop; on smaller screens that pushes the title off-screen.
       Allow normal wrapping and cap the width to ~90 %. */
    white-space: normal !important;
    max-width: 90%;
    word-break: normal;
    overflow-wrap: break-word;
  }
  .work .about-chip {
    max-width: 90%;
  }
  .work .about-meta--with-card .about-meta__card {
    /* In the flex flow rather than absolute — appears under the
       chip, above the Speciality / Experience rows. Cap width so
       the photo doesn't fill the whole tablet width. */
    position: static !important;
    width: min(360px, 80%);
    margin: 8px 0 16px 0;
  }
  .work .about-meta--with-card .about-meta-item {
    /* Override the desktop 75 % cap (which assumed a 720 px right
       gutter for the avatar). Use the full text column. */
    max-width: 90%;
    width: 90%;
    white-space: normal;
    overflow-wrap: break-word;
  }
  .work .about-more-body {
    max-width: 90%;
  }
}
/* Hide the "Experience" label tag on the avatar card. */
.work .about-meta--with-card .about-meta__label {
  display: none !important;
}
/* Buttons sit immediately under the meta rows, left-aligned to the
   title (no indent / centering). White pills with no outline; the
   arrow badge is a solid black circle. */
.work .about-actions {
  margin-top: 20px;
  justify-content: flex-start;
  margin-left: 0;
}
.work .about-actions .thoughts-see-all-btn,
.work .about-actions .about-more-btn,
.work .about-actions .about-experience-btn {
  background: #ffffff !important;
  border: none !important;
  color: #111 !important;
  box-shadow: none !important;
}
.work .about-actions .thoughts-see-all-btn:hover,
.work .about-actions .about-more-btn:hover,
.work .about-actions .about-experience-btn:hover {
  background: #f4f3ee !important;
  color: #111 !important;
}
.work .about-actions .btn-arrow-circle {
  background: #111111 !important;
  color: #ffffff !important;
}
/* Cancel the title's "break-out to 10vw" margin trick inside the
   .work section — it was designed for the centred about-block but
   here we want the title to flow normally so the chip, meta rows and
   buttons can left-align directly underneath. Also force it onto a
   single line. */
.work .about-h1 {
  margin-left: 0 !important;
  margin-right: 0 !important;
  white-space: nowrap;
}
.work .about-chip {
  margin-left: 0 !important;
}
.about-meta__card {
  position: relative;
  border-radius: 18px;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--bg-2, #EDE8DE);
}
.about-meta__card .about-meta__img,
.about-meta__card .about-meta__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.about-meta__card .about-meta__video {
  z-index: 1;
}
.about-meta__label {
  position: absolute;
  left: 16px;
  bottom: 14px;
  color: #fff;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  background: rgba(0,0,0,0.5);
  backdrop-filter: blur(6px);
  padding: 5px 12px;
  border-radius: 999px;
  z-index: 2;
}
@media (max-width: 699px) {
  .about-meta--with-card {
    grid-template-columns: 1fr;
    gap: 20px;
  }
  .about-meta__card { aspect-ratio: 16 / 10; }
}

.about-meta {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding-bottom: 40px;
  margin-bottom: 40px;
  border-bottom: 1px solid var(--border);
}

.about-meta-item {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 1rem;
  color: var(--text-2);
  line-height: 1.5;
}

.about-meta-item strong {
  display: block;
  font-weight: 500;
  color: var(--text);
  margin-bottom: 3px;
}

.about-body {
  margin-bottom: 48px;
}

.about-body p {
  font-family: 'Inter', sans-serif;
  font-size: 1.12rem;
  line-height: 1.78;
  color: var(--text-2);
  margin-bottom: 20px;
}

/* --- source lines 1914-2149 --- */
/* ======================================================
   TRUSTED BY
   ====================================================== */

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

.trusted-section {
  /* overflow: hidden removed — body overflow-x:clip handles horizontal bleed;
     pills need to be able to fall below this section's boundary during scatter */
  overflow: visible;
  padding: 220px 0 90px;     /* push the heading well below the intro */
  /* Bleed past parent section's horizontal padding so the marquee runs the full viewport width */
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  width: 100vw;
}

/* ─── Heading ────────────────────────────────────────── */
.trusted-hed {
  margin-bottom: 44px;
  pointer-events: none;
  /* overflow intentionally visible — text allowed to bleed off sides;
     body overflow-x:clip handles viewport clipping */
}

/* The heading is followed by a lede and a clarification line now, so it needs
   far less space beneath it than when it stood alone. Scoped to
   .trusted-section — .process-hed carries .trusted-hed--plain too. */
.trusted-section .trusted-hed--plain { margin-bottom: 20px; }

/* Supporting paragraph. Values follow .intro-supporting, but deliberately not
   its class: that one is display:none below 699px, which would be wrong here. */
.tb-lede {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 16px;
  line-height: 1.45;
  color: var(--text-2);
  /* same left column as the heading above it */
  margin: 0 28px 14px calc(15vw + 100px);
  max-width: min(52ch, calc(85vw - 128px));
}

/* Clarification line — the mono eyebrow convention used by .ph-phase. */
.tb-note {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 12px;
  line-height: 1.55;
  letter-spacing: 0.02em;
  color: var(--text-3);
  margin: 0 28px 44px calc(15vw + 100px);
  max-width: min(58ch, calc(85vw - 128px));
}

/* ─── Two-row marquee (row 0 forward, row 1 reverse) ─── */
.tb-rows {
  display: flex;
  flex-direction: column;
  gap: 14px;
  opacity: 0;
  transition: opacity 0.6s ease 0.25s;
  overflow-x: clip;    /* clips marquee at viewport edges */
  overflow-y: visible; /* lets scattered pills fall into the testimonials below */
}

/* Rows visible once text has landed */
.trusted-section.is-landed .tb-rows { opacity: 1; }
.trusted-section.is-split  .tb-rows { opacity: 1; }
/* Squiggle sweep removed — coordinated entrance instead:
   heading slides UP, logos drop DOWN, when section scrolls into view. */
.trusted-section .tb-rows {
  opacity: 0;
  transform: translateY(-60px);
  transition: opacity 0.7s ease, transform 0.9s var(--ease-out, cubic-bezier(0.22, 1, 0.36, 1));
}
.trusted-section.is-in .tb-rows {
  opacity: 1;
  transform: translateY(0);
}
.trusted-section .trusted-hed--plain {
  opacity: 0;
  transform: translateY(60px);
  transition: opacity 0.7s ease, transform 0.9s var(--ease-out, cubic-bezier(0.22, 1, 0.36, 1));
}
.trusted-section.is-in .trusted-hed--plain {
  opacity: 1;
  transform: translateY(0);
}

.tb-row {
  display: flex;
  align-items: center;
  gap: 14px;
  width: max-content;
  will-change: transform;
  /* position driven by JS marquee engine — no CSS animation */
}

/* ─── Organisation tooltip ────────────────────────────────
   Three lines: organisation, industry context, capability areas.
   Positioned by JS (placeTip in site.js) — it sets left/top, flips to
   .is-below when there is no room above, and sets --caret-x so the pointer
   still aims at the card after the box has been clamped inside the viewport. */
#tb-tooltip {
  position: fixed;
  z-index: 9999;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  gap: 5px;
  width: max-content;
  max-width: min(320px, calc(100vw - 24px));
  background: var(--text);
  border-radius: 10px;
  padding: 11px 15px 12px;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.18s ease, transform 0.18s ease;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.28);
}
/* Coming from below, the entrance should rise from the other direction. */
#tb-tooltip.is-below { transform: translateY(-6px); }
/* Declared after .is-below so it wins the tie at equal specificity. */
#tb-tooltip.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.tb-tip__org {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--bg);
}
.tb-tip__context {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 0.82rem;
  line-height: 1.4;
  color: rgba(244, 243, 238, 0.74);
}
.tb-tip__caps {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.68rem;
  line-height: 1.5;
  letter-spacing: 0.02em;
  color: rgba(244, 243, 238, 0.52);
  padding-top: 3px;
  border-top: 1px solid rgba(244, 243, 238, 0.14);
}

#tb-tooltip::after {
  content: '';
  position: absolute;
  top: 100%;
  left: var(--caret-x, 50%);
  transform: translateX(-50%);
  border: 7px solid transparent;
  border-top-color: var(--text);
}
#tb-tooltip.is-below::after {
  top: auto;
  bottom: 100%;
  border-top-color: transparent;
  border-bottom-color: var(--text);
}

/* ─── Organisation cards ──────────────────────────────────
   A <button> so every card is keyboard-reachable and gives the mobile
   tap-to-open tooltip a real activation target. */
.tb-card {
  flex-shrink: 0;
  width: 184px;
  height: 116px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px 12px;
  background: #ffffff;
  border: 1px solid var(--border);
  border-radius: 12px;
  box-sizing: border-box;
  font: inherit;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.28s ease, transform 0.28s var(--ease-out, cubic-bezier(0.16, 1, 0.3, 1)),
              box-shadow 0.28s ease;
}

/* Fixed logo box so every mark is optically centred on the same baseline
   regardless of its aspect ratio. */
.tb-card__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 42px;
}

.tb-card__logo img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  filter: grayscale(1);
  opacity: 0.72;
  transition: filter 0.35s ease, opacity 0.35s ease;
}

.tb-card__name {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 0.72rem;
  line-height: 1.25;
  letter-spacing: 0.01em;
  color: var(--text-2);
  /* Two lines max — "NSW Small Business Commissioner" needs them. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  transition: color 0.28s ease;
}

/* Hover and keyboard focus get identical treatment. */
.tb-card:hover,
.tb-card:focus-visible {
  border-color: rgba(0, 0, 0, 0.22);
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.07);
}
.tb-card:hover .tb-card__logo img,
.tb-card:focus-visible .tb-card__logo img {
  filter: grayscale(0);
  opacity: 1;
}
.tb-card:hover .tb-card__name,
.tb-card:focus-visible .tb-card__name { color: var(--text); }

/* Per-logo optical sizing. Aspect ratios vary wildly across 14 real marks —
   without this, a round roundel reads twice the weight of a wide wordmark. */
.tb-card[data-logo="bmw"]        .tb-card__logo img { max-height: 34px; }
.tb-card[data-logo="volkswagen"] .tb-card__logo img { max-height: 36px; }
.tb-card[data-logo="audi"]       .tb-card__logo img { max-width: 108px; }
.tb-card[data-logo="uber"]       .tb-card__logo img { max-height: 24px; }
.tb-card[data-logo="wikifolio"]  .tb-card__logo img { max-height: 22px; }
.tb-card[data-logo="bt"]         .tb-card__logo img { max-height: 30px; }
.tb-card[data-logo="amp"]        .tb-card__logo img { max-height: 38px; }
.tb-card[data-logo="roche"]      .tb-card__logo img { max-height: 38px; }
.tb-card[data-logo="applause"]   .tb-card__logo img { max-width: 128px; }
.tb-card[data-logo="oic"]        .tb-card__logo img { max-width: 124px; }
.tb-card[data-logo="goodgame"]   .tb-card__logo img { max-height: 42px; }
/* Wide lockups — these need the full card width to stay legible, so they are
   width-bound rather than height-bound. */
.tb-card[data-logo="nsw"]        .tb-card__logo img { max-width: 100%; }
.tb-card[data-logo="avocado"]    .tb-card__logo img { max-width: 100%; }
.tb-card[data-logo="bergstrom"]  .tb-card__logo img { max-width: 100%; }
.tb-card[data-logo="finstreet"]  .tb-card__logo img { max-height: 34px; }

/* Light, saturated marks desaturate to near-white and vanish against the card.
   Darken these while they are greyed, then hand back true colour on hover.
   TAL green, TAP yellow/green, Avocado green-and-gold, Finstreet blue-violet. */
.tb-card[data-logo="tal"]       .tb-card__logo img { filter: grayscale(1) brightness(0.55); }
.tb-card[data-logo="avocado"]   .tb-card__logo img { filter: grayscale(1) brightness(0.60); }
.tb-card[data-logo="tap"]       .tb-card__logo img { filter: grayscale(1) brightness(0.72); }
.tb-card[data-logo="finstreet"] .tb-card__logo img { filter: grayscale(1) brightness(0.82); }
.tb-card[data-logo="tal"] .tb-card__logo img { max-height: 32px; }
.tb-card[data-logo="tap"] .tb-card__logo img { max-height: 42px; }
.tb-card[data-logo="tal"]:hover       .tb-card__logo img,
.tb-card[data-logo="tal"]:focus-visible       .tb-card__logo img,
.tb-card[data-logo="tap"]:hover       .tb-card__logo img,
.tb-card[data-logo="tap"]:focus-visible       .tb-card__logo img,
.tb-card[data-logo="avocado"]:hover   .tb-card__logo img,
.tb-card[data-logo="avocado"]:focus-visible   .tb-card__logo img,
.tb-card[data-logo="finstreet"]:hover .tb-card__logo img,
.tb-card[data-logo="finstreet"]:focus-visible .tb-card__logo img {
  filter: grayscale(0) brightness(1);
}

/* Marquee clones must stay fully hoverable — at any moment most of the strip
   on screen IS clones, so making them inert would leave the section looking
   broken. They are kept out of the keyboard path instead, via tabindex="-1"
   set on each clone in site.js. */

/* Reduced motion: the marquee never starts, so a single 7-card row would run
   off the screen edge. Wrap into a static, centred grid instead — all 14
   organisations visible and readable, tooltips still working. */
@media (prefers-reduced-motion: reduce) {
  .tb-row {
    flex-wrap: wrap;
    justify-content: center;
    width: auto;
    /* 5 cards per line (5 x 184 + 4 x 14 gap = 976). Rows of 9 and 8 then break
       5+4 and 5+3 — no line left with a single orphan card. */
    max-width: min(980px, calc(100vw - 48px));
    margin: 0 auto;
  }
  .tb-card[aria-hidden="true"] { display: none; }
}

@media (max-width: 767px) {
  .trusted-section { padding: 60px 0 70px; }
  .tb-rows { opacity: 1; }

  /* The heading used to be hidden on phones (see the max-width:699px rule
     further down this file, now scoped to the legacy SVG heading only).
     It carries real copy now, so it stays — with the lede and note beneath. */
  .trusted-section .trusted-hed {
    overflow: visible;
    margin-bottom: 16px;
  }
  .tb-lede {
    font-size: 15px;
    margin: 0 16px 12px 16px;
    max-width: none;
  }
  .tb-note {
    font-size: 11px;
    margin: 0 16px 28px 16px;
    max-width: none;
  }
}

@media (max-width: 600px) {
  .tb-rows { gap: 10px; }
  .tb-row  { gap: 10px; }
  .tb-card {
    width: 150px;
    height: 100px;
    gap: 8px;
    padding: 12px 10px;
    border-radius: 10px;
  }
  .tb-card__logo { height: 34px; }
  .tb-card__name { font-size: 0.66rem; }
  .tb-card[data-logo="bmw"]        .tb-card__logo img { max-height: 28px; }
  .tb-card[data-logo="volkswagen"] .tb-card__logo img { max-height: 30px; }
  .tb-card[data-logo="tap"]        .tb-card__logo img { max-height: 34px; }
  .tb-card[data-logo="tal"]        .tb-card__logo img { max-height: 26px; }
  .tb-card[data-logo="uber"]       .tb-card__logo img { max-height: 24px; }
  .tb-card[data-logo="wikifolio"]  .tb-card__logo img { max-height: 22px; }
}

/* Arrow button */
.arrow-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1.5px solid var(--border);
  color: var(--text);
  transition: background 0.2s, border-color 0.2s, transform 0.25s var(--ease-out);
  flex-shrink: 0;
}
.arrow-btn:hover {
  background: var(--surface);
  border-color: rgba(0,0,0,0.2);
  transform: translateX(4px);
}

/* ========================================================================
   LAYER 06 · FIXED SITE CHROME — scroll hint, bottom tool nav, burger panel, analytics + contact panels, social buttons, Ask-AI
   ======================================================================== */

/* --- source lines 2150-2210 --- */
/* ======================================================
   SCROLL HINT
   ====================================================== */
#scroll-hint {
  position: fixed;
  bottom: max(92px, calc(80px + env(safe-area-inset-bottom))); /* clears toolbar + iOS safe area */
  left: 50%;
  transform: translateX(-50%) translateY(10px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.55s ease, transform 0.55s cubic-bezier(0.16, 1, 0.3, 1);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  z-index: 9000;
  white-space: nowrap;
  /* Reset button defaults so the element looks identical to the previous div */
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
#scroll-hint.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
#scroll-hint:hover .scroll-hint-chevron { animation-play-state: paused; transform: translateY(2px); }
.scroll-hint-chevron {
  color: var(--text-2);
  animation: sh-bounce 1.5s ease-in-out infinite;
}
@keyframes sh-bounce {
  0%, 100% { transform: translateY(0); }
  50%       { transform: translateY(7px); }
}
.scroll-hint-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  color: var(--text-2);
  margin: 0;
  text-transform: lowercase;
}
.sh-o {
  display: inline-block;
  animation: sh-o-out 2s ease-in-out infinite;
}
.sh-o:nth-child(1) { animation-delay: 0s; }
.sh-o:nth-child(2) { animation-delay: 0.22s; }
.sh-o:nth-child(3) { animation-delay: 0.44s; }
.sh-o:nth-child(4) { animation-delay: 0.66s; }
@keyframes sh-o-out {
  0%, 35%, 100% { transform: scaleX(1) translateY(0); opacity: 1; }
  60%            { transform: scaleX(0.05) translateY(1px); opacity: 0; }
  80%            { transform: scaleX(1.15) translateY(-1px); opacity: 1; }
}

/* --- source lines 2211-2317 --- */
/* ======================================================
   BOTTOM NAV PILL
   ====================================================== */
.bottom-nav {
  position: fixed;
  bottom: max(28px, calc(16px + env(safe-area-inset-bottom)));
  left: 50%;
  transform: translateX(-50%);
  background: var(--pill-bg);
  border-radius: 100px;
  padding: 12px 28px;
  display: flex;
  align-items: center;
  gap: 24px;
  z-index: 9900;
  box-shadow: 0 8px 32px rgba(0,0,0,0.18);
  transition: transform 0.4s var(--ease-out), opacity 0.4s ease;
}
.bottom-nav--hidden {
  transform: translateX(-50%) translateY(80px);
  opacity: 0;
  pointer-events: none;
}

/* On mobile, wide marquee rows inflate the layout width so left:50% overshoots.
   Switch to margin:auto centering which always uses the visual viewport. */
@media (max-width: 767px) {
  .bottom-nav {
    left: 0;
    right: 0;
    width: max-content;
    margin: 0 auto;
    transform: none;
  }
  .bottom-nav--hidden {
    transform: translateY(80px);
  }
}

.nav-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: rgba(255,255,255,0.45);
  transition: color 0.2s;
  position: relative;
}
.nav-icon:hover,
.nav-icon.active {
  color: #ffffff;
}

/* ── Nav tooltips ── */
.nav-tooltip {
  position: absolute;
  bottom: calc(100% + 16px);
  left: 50%;
  transform: translateX(-50%) translateY(10px) scale(0.86);
  transform-origin: center bottom;
  background: #1a1a18;
  color: #ffffff;
  padding: 7px 14px;
  border-radius: 100px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
  opacity: 0;
  box-shadow: 0 6px 24px rgba(0,0,0,0.28), 0 1px 4px rgba(0,0,0,0.16);
  transition:
    opacity 0.14s ease,
    transform 0.38s cubic-bezier(0.34, 1.56, 0.64, 1);
  z-index: 9200;
}

/* Tiny caret pointing down toward the toolbar */
.nav-tooltip::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: #1a1a18;
}

.nav-icon:hover .nav-tooltip {
  opacity: 1;
  transform: translateX(-50%) translateY(0) scale(1);
  transition:
    opacity 0.12s ease,
    transform 0.38s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Dismiss instantly on mouseout */
.nav-icon:not(:hover) .nav-tooltip {
  transition:
    opacity 0.12s ease,
    transform 0.2s ease;
}

/* --- source lines 2318-2380 --- */
/* ======================================================
   BURGER MENU PANEL
   ====================================================== */
.nav-menu-panel {
  position: fixed;
  background: #1a1a18;
  border-radius: 12px;
  padding: 4px 0;
  min-width: 160px;
  opacity: 0;
  transform: translateY(6px) scale(0.96);
  transform-origin: bottom center;
  pointer-events: none;
  transition: opacity 0.2s ease,
              transform 0.22s cubic-bezier(0.16, 1, 0.3, 1);
  z-index: 9850;
  box-shadow: 0 8px 40px rgba(0,0,0,0.28);
}
.nav-menu-panel.is-open {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.nav-menu-item {
  display: block;
  padding: 7px 18px;
  color: rgba(232, 230, 220, 0.8);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  text-decoration: none;
  transition: color 0.15s ease, background 0.15s ease;
}
.nav-menu-item:hover {
  color: #fff;
  background: rgba(255,255,255,0.07);
}
.nav-menu-item + .nav-menu-item {
  border-top: 1px solid rgba(255,255,255,0.06);
}
.nav-burger[aria-expanded="true"] {
  color: #fff;
}

/* Burger → X animation */
.nav-burger svg line {
  transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1),
              opacity 0.2s ease;
  transform-box: fill-box;
  transform-origin: center;
}
.nav-burger[aria-expanded="true"] svg line:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.nav-burger[aria-expanded="true"] svg line:nth-child(2) {
  opacity: 0;
  transform: scaleX(0);
}
.nav-burger[aria-expanded="true"] svg line:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* --- source lines 2381-2463 --- */
/* ======================================================
   ANALYTICS PANEL
   ====================================================== */

/*
  The dashboard .dash is exactly 800 × 600px.
  The dashboard body has 24px padding all round, so the
  full iframe document is 848 × 648px.
  We size the panel to 800 × 600 and offset the iframe
  by -24px to clip that padding, showing the .dash flush.
*/
.analytics-panel {
  position: fixed;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  bottom: calc(max(28px, 16px + env(safe-area-inset-bottom)) + 56px + 14px);
  width: min(calc(100vw - 32px), 800px);
  height: 600px;
  background: #000;
  border-radius: 14px;
  overflow: hidden;
  z-index: 9850;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease,
              transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
  box-shadow: 0 -4px 60px rgba(0,0,0,0.6),
              0 0 0 1px rgba(255,255,255,0.06) inset;
}
.analytics-panel.is-open {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}

/* Iframe: 48px larger on each axis, pulled back 24px to clip body padding */
.analytics-panel__iframe {
  position: absolute;
  top: -24px;
  left: -24px;
  width: calc(100% + 48px);
  height: calc(100% + 48px);
  border: none;
  display: block;
}

/* Close X — floats top-right over the iframe */
.analytics-panel__close {
  all: unset;
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 10;
  cursor: pointer;
  color: rgba(255,255,255,0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: rgba(0,0,0,0.5);
  backdrop-filter: blur(6px);
  transition: color 0.15s, background 0.15s;
}
.analytics-panel__close:hover {
  color: #fff;
  background: rgba(255,255,255,0.12);
}

/* Analytics btn — active state */
.nav-analytics-btn[aria-expanded="true"] {
  color: #fff;
}

/* Mobile: clamp height so it fits */
@media (max-width: 599px) {
  .analytics-panel {
    width: calc(100vw - 16px);
    height: 80vh;
  }
}

/* --- source lines 2464-2591 --- */
/* ======================================================
   CONTACT PANEL
   ====================================================== */
.contact-panel {
  position: fixed;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  bottom: calc(max(28px, 16px + env(safe-area-inset-bottom)) + 56px + 14px);
  width: min(calc(100vw - 32px), 480px);
  background: #1a1a18;
  border-radius: 14px;
  overflow: hidden;
  z-index: 9850;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease,
              transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
  box-shadow: 0 -4px 60px rgba(0,0,0,0.6),
              0 0 0 1px rgba(255,255,255,0.06) inset;
}
.contact-panel.is-open {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}

.contact-panel__inner {
  padding: 28px 28px 24px;
}

.contact-panel__heading {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.9);
  margin: 0 0 20px;
}

/* Close X — floats top-right */
.contact-panel__close {
  all: unset;
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 10;
  cursor: pointer;
  color: rgba(255,255,255,0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: rgba(255,255,255,0.06);
  transition: color 0.15s, background 0.15s;
}
.contact-panel__close:hover {
  color: #fff;
  background: rgba(255,255,255,0.14);
}

/* Dark-theme overrides for form elements inside the panel */
.contact-panel .contact-card {
  background: transparent;
  box-shadow: none;
  padding: 0;
  border-radius: 0;
}
.contact-panel .form-input {
  background: rgba(255,255,255,0.07);
  border-color: rgba(255,255,255,0.1);
  color: rgba(255,255,255,0.9);
}
.contact-panel .form-input:focus {
  border-color: rgba(255,255,255,0.25);
  background: rgba(255,255,255,0.1);
}
.contact-panel .form-input::placeholder {
  color: rgba(255,255,255,0.3);
}
.contact-panel .form-robot-check {
  color: rgba(255,255,255,0.45);
}
.contact-panel .form-robot-check input[type="checkbox"] {
  border-color: rgba(255,255,255,0.25);
  background: transparent;
}
.contact-panel .form-robot-check input[type="checkbox"]:checked {
  background: rgba(255,255,255,0.85);
  border-color: rgba(255,255,255,0.85);
}
.contact-panel .form-robot-check input[type="checkbox"]:checked::after {
  border-color: #1a1a18;
}
.contact-panel .form-submit {
  background: #fff;
  color: #1a1a18;
  padding-top: 18px;
  padding-bottom: 18px;
}
.contact-panel .form-submit:hover {
  background: rgba(255,255,255,0.88);
}
.contact-panel .form-success-msg {
  color: rgba(255,255,255,0.9);
}
.contact-panel .form-success-sub,
.contact-panel .form-success-sub a {
  color: rgba(255,255,255,0.45);
}
.contact-panel .form-success-sub a:hover {
  color: rgba(255,255,255,0.75);
}
.contact-panel .form-sending-overlay {
  background: rgba(26,26,24,0.7);
}

@media (max-width: 599px) {
  .contact-panel {
    width: calc(100vw - 16px);
  }
  .contact-panel__inner {
    padding: 24px 20px 20px;
  }
}

/* --- source lines 2592-2635 --- */
/* ======================================================
   SOCIAL (fixed bottom-right)
   ====================================================== */
.social-fixed {
  position: fixed;
  bottom: 28px;
  right: 28px;
  display: flex;
  gap: 8px;
  /* Above #intro-pills (z-index: 500) so the X / LinkedIn icons stay
     interactive even when pills cluster bottom-right. */
  z-index: 600;
}

.social-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 8px;
  transition: opacity 0.2s, transform 0.2s var(--ease-out);
}
.social-btn:hover { opacity: 0.82; transform: translateY(-2px); }

.social-btn--x  { background: #1A1A18; color: #fff; }
.social-btn--li { background: #0A66C2; color: #fff; }

.social-fixed {
  transition: opacity 0.4s ease, transform 0.4s var(--ease-out);
}
.social-fixed--hidden {
  opacity: 0;
  pointer-events: none;
  transform: translateY(12px);
}

@media (max-width: 768px) {
  .social-fixed {
    flex-direction: column;
    bottom: 124px;
  }
}

/* --- source lines 2636-2899 --- */
/* ======================================================
   ASK AI — its own pill, sits next to the bottom-nav
   (same height as .bottom-nav so they read as a row).
   ====================================================== */
.ask-ai-btn {
  position: fixed;
  /* Sit at the same vertical line as .bottom-nav and immediately to its right.
     The bottom-nav is centred via translateX(-50%); this pill anchors at
     viewport-centre + half the nav's measured width + a gap. JS keeps the
     left offset in sync via the --nav-half-width variable so the pill always
     hugs the nav regardless of width. */
  left: calc(50% + var(--nav-half-width, 200px) + 14px);
  bottom: max(28px, calc(16px + env(safe-area-inset-bottom)));
  /* Match the bottom-nav's measured height (set by JS to --nav-height). */
  width: var(--nav-height, 44px);
  height: var(--nav-height, 44px);
  background: var(--pill-bg);
  color: #fff;
  border: none;
  border-radius: 999px; /* pill once expanded; circle while square */
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  padding: 0;
  cursor: pointer;
  z-index: 9900;
  overflow: hidden;
  white-space: nowrap;
  box-shadow: 0 8px 32px rgba(0,0,0,0.18);
  transition: width 0.32s var(--ease-out), padding 0.32s var(--ease-out),
              transform 0.25s var(--ease-out), opacity 0.3s ease,
              background 0.2s ease;
}
.ask-ai-btn__icon {
  display: block;
  pointer-events: none;
  flex-shrink: 0;
  margin-left: calc((var(--nav-height, 44px) - 18px) / 2);
}
/* Label uses IBM Plex Mono and animates letter-by-letter on hover.
   The button width transitions (set on .ask-ai-btn above), so the pill
   visually grows alongside the typed-out text. */
.ask-ai-btn__label {
  display: inline-flex;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: #fff;
  pointer-events: none;
  white-space: pre; /* keep spaces in split chars */
}
.ask-ai-btn__char {
  display: inline-block;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.18s var(--ease-out),
              transform 0.18s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 18ms);
}
.ask-ai-btn:hover {
  width: auto;
  padding-right: 18px;
  transform: translateY(-2px);
}
.ask-ai-btn:hover .ask-ai-btn__char {
  opacity: 1;
  transform: translateY(0);
  /* On enter, stagger forward; reverse the delay so the first char wins
     out fastest and the last char trails. */
  transition-delay: calc(var(--i, 0) * 24ms + 60ms);
}
.ask-ai-btn .nav-tooltip {
  /* reuse the same hover tooltip style as the bottom-nav icons */
  bottom: calc(100% + 8px);
}
.ask-ai-btn.is-open {
  background: #fff;
  color: var(--text);
}
/* Hide while the bottom-nav itself is hidden (mirrors .bottom-nav--hidden) */
.bottom-nav--hidden ~ .ask-ai-btn {
  opacity: 0;
  pointer-events: none;
  transform: translateY(80px);
}

.ai-chat {
  position: fixed;
  right: 28px;
  bottom: 100px;                            /* sits above bottom-nav */
  width: 380px;
  max-width: calc(100vw - 56px);
  height: min(560px, calc(100vh - 200px));
  background: var(--pill-bg);
  color: #fff;
  border-radius: 22px;
  box-shadow: 0 16px 48px rgba(0,0,0,0.32);
  z-index: 9850;
  opacity: 0;
  transform: translateY(20px);
  pointer-events: none;
  transition: opacity 0.32s var(--ease-out), transform 0.32s var(--ease-out);
}
.ai-chat.is-open {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.ai-chat__inner {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 20px 20px 18px;
  box-sizing: border-box;
}
.ai-chat__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
  flex-shrink: 0;
}
.ai-chat__title {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.78;
}
.ai-chat__close {
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
  padding: 6px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0.7;
  transition: opacity 0.15s ease, background 0.15s ease;
}
.ai-chat__close:hover { opacity: 1; background: rgba(255,255,255,0.08); }

.ai-chat__log {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-right: 4px;
  margin-bottom: 12px;
}
.ai-chat__msg {
  max-width: 88%;
  font-family: 'Inter', sans-serif;
  font-size: 0.92rem;
  line-height: 1.55;
  padding: 10px 14px;
  border-radius: 14px;
  word-wrap: break-word;
}
.ai-chat__msg--bot {
  background: rgba(255,255,255,0.085);
  align-self: flex-start;
  border-bottom-left-radius: 6px;
}
.ai-chat__msg--user {
  background: #fff;
  color: var(--text);
  align-self: flex-end;
  border-bottom-right-radius: 6px;
}

/* Inline navigation pills the bot can offer at the end of a reply.
   The bot emits [Label](#anchor) or [Label](/path); the client converts
   them into clickable pills that scroll/navigate when tapped. */
.ai-chat__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 10px;
}
.ai-chat__action {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(255,255,255,0.12);
  color: #fff;
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 999px;
  padding: 6px 12px 6px 12px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.005em;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease;
}
.ai-chat__action:hover {
  background: rgba(255,255,255,0.22);
  border-color: rgba(255,255,255,0.4);
}
.ai-chat__action::after {
  content: '↗';
  font-size: 11px;
  opacity: 0.7;
}

.ai-chat__form {
  display: flex;
  gap: 8px;
  align-items: stretch;
  flex-shrink: 0;
}
.ai-chat__input {
  flex: 1;
  background: rgba(255,255,255,0.085);     /* same vibe as .form-input on light bg */
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 14px 16px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.92rem;
  color: #fff;
  outline: none;
  transition: border-color 0.2s;
  box-sizing: border-box;
}
.ai-chat__input::placeholder { color: rgba(255,255,255,0.45); }
.ai-chat__input:focus { border-color: rgba(255,255,255,0.25); }

.ai-chat__send {
  background: #fff;
  color: var(--text);
  border: none;
  border-radius: 100px;
  width: 48px;
  flex-shrink: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.15s ease, transform 0.2s var(--ease-out);
}
.ai-chat__send:hover {
  opacity: 0.88;
  transform: translateY(-1px);
}

/* Mobile: chat panel centred (per user spec). Pill stays adjacent to the
   nav-row (left offset still set by JS via --nav-half-width). */
@media (max-width: 768px) {
  .ai-chat {
    right: 16px;
    left: 16px;
    width: auto;
    max-width: none;
    bottom: 100px;
    height: min(70vh, 520px);
  }
}

/* ========================================================================
   LAYER 07 · CONTENT SECTIONS — part 2: FAQ accordion (+ nav ordering + shared heading harmonisation), contact form, social profile cards
   ======================================================================== */

/* --- source lines 2900-3363 --- */
/* ======================================================
   FAQ
   ====================================================== */
.faq-section {
  padding: 80px 28px 100px;
  max-width: 760px;
  margin: 0 auto;
}

.faq-title {
  font-family: 'Inter', sans-serif;
  font-size: clamp(2rem, 5vw, 3.8rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  color: var(--text);
  margin-bottom: 56px;
}

/* ─────────────────────────────────────────────────────────
   Bottom nav (black footer toolbar) — visibility + order.
   Hide: game, sticky-note, transform. Arrow is hidden by
   default but appears when the pen tool is active so the
   user can switch back. Order: menu, contact, pen, analytics.
   ───────────────────────────────────────────────────────── */
.bottom-nav .nav-icon[data-tool="game"],
.bottom-nav .nav-icon[data-tool="sticky"],
.bottom-nav .nav-icon[data-tool="transform"],
.bottom-nav #nav-game-btn {
  display: none !important;
}
.bottom-nav .nav-icon[data-tool="arrow"] {
  display: none !important;
}
body[data-tool="pen"] .bottom-nav .nav-icon[data-tool="arrow"] {
  display: inline-flex !important;
}
.bottom-nav { /* enable ordering via flex */
  display: flex;
}
.bottom-nav #nav-burger                       { order: 1; }
.bottom-nav .nav-icon[data-tool="email"]      { order: 2; }
.bottom-nav .nav-icon[data-tool="pen"]        { order: 3; }
.bottom-nav .nav-icon[data-tool="arrow"]      { order: 4; }
.bottom-nav #nav-analytics-btn                { order: 5; }

/* Hide thumbs beyond the first 7 when the cap is active. The
   selector is duplicated with extra specificity to beat the
   `.work-zoom[data-view="rows"] .work-thumb { display: block
   !important }` rule that would otherwise override it. */
.work-thumb--cap-hidden,
.work-zoom .work-thumb--cap-hidden,
.work-zoom[data-view="rows"] .work-thumb.work-thumb--cap-hidden,
.work-panel__grid .work-thumb.work-thumb--cap-hidden {
  display: none !important;
}
/* "Show more" pill sits directly under the capped grid — centred,
   black background, white text, no border. */
.work-show-more {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #111111;
  color: #ffffff;
  border: none;
  border-radius: 999px;
  padding: 14px 28px;
  font-family: 'Inter', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: 0;
  cursor: pointer;
  /* Centred horizontally + extra 50 px breathing room above. */
  margin: 82px auto 32px;
  transition: background 0.2s ease;
}
.work-show-more:hover { background: #000000; }

/* ─────────────────────────────────────────────────────────
   Match the section heading style of "More about process"
   (.trusted-hed--plain) for Need a hand?, Let's connect, and
   the FAQ title. Same font/clamp/letter-spacing, and same
   10vw left margin so all four headings share the column.
   ───────────────────────────────────────────────────────── */
.contact-heading,
.social-profiles-label,
section.faq-section > .faq-inner > .faq-title {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif !important;
  font-size: clamp(0.79rem, 3.1vw, 3.06rem) !important;
  font-weight: 400 !important;
  letter-spacing: -0.03em !important;
  line-height: 1.02 !important;
  color: var(--text) !important;
  text-align: left !important;
  padding: 0 !important;
  /* Break out of any centred / padded parent (.contact, .social-
     profiles, .faq-inner) so the heading's left edge sits at the
     same viewport 15vw column as "More about process".  Note: the
     desktop 2-column override below cancels these breakouts. */
  width: auto !important;
  max-width: none !important;
  margin-left: calc(50% - 50vw + 15vw + 100px) !important;
  margin-right: calc(50% - 50vw + 28px) !important;
  margin-top: 0 !important;
  margin-bottom: 60px !important;
}

/* ─────────────────────────────────────────────────────────
   Desktop only — Contact / Let's connect / FAQs become a
   2-column row: left col = heading (anchored ~30 % from the
   top of the section); right col = content (form / cards /
   accordion). Mobile keeps the existing stacked layout.
   ───────────────────────────────────────────────────────── */
@media (min-width: 900px) {
  .contact,
  .social-profiles,
  section.faq-section#faq {
    display: grid !important;
    grid-template-columns: minmax(280px, 1fr) minmax(0, 2fr) !important;
    column-gap: 60px !important;
    padding-left: calc(15vw + 100px) !important;
    padding-right: 5vw !important;
    align-items: start !important;
    box-sizing: border-box;
    /* Override the centred max-width on each base rule so the grid
       can span the full viewport. */
    max-width: none !important;
    width: 100% !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
  /* Headings live in col 1 and sit at the top of the row. Cancel
     the viewport break-out margins set above so they stay in
     the column. */
  .contact > .contact-heading,
  .social-profiles > .social-profiles-label,
  section.faq-section#faq > .faq-inner > .faq-title {
    margin-left: 0 !important;
    margin-right: 0 !important;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
    align-self: start !important;
    padding-top: 0 !important;
  }
  /* "Need a hand?" title pushed 100 px down. */
  .contact > .contact-heading {
    padding-top: 100px !important;
  }
  /* Right-column content. */
  .contact > .contact-card {
    grid-column: 2 !important;
    margin: 0 !important;
    max-width: 640px;
  }
  .social-profiles > .social-cards-row {
    grid-column: 2 !important;
    margin: 0 !important;
  }
  /* Stack each word of the FAQ heading on its own line. */
  .faq-title--stacked > span {
    display: block !important;
  }
  /* The FAQ section wraps its title + list in .faq-inner — keep
     .faq-inner contents un-gridded but make the inner element span
     both columns so the H2 + list layout still works visually. */
  section.faq-section#faq > .faq-inner {
    grid-column: 1 / -1 !important;
    display: grid !important;
    grid-template-columns: minmax(280px, 1fr) minmax(0, 2fr) !important;
    column-gap: 60px !important;
    align-items: start !important;
  }
  section.faq-section#faq > .faq-inner > .faq-list {
    grid-column: 2 !important;
    margin: 0 !important;
    padding: 0 !important;
  }
  /* "Show more questions" button — pin to column 2 so it left-
     aligns with the accordion above it. */
  section.faq-section#faq > .faq-inner > .faq-more-btn {
    grid-column: 2 !important;
    justify-self: start !important;
    margin: 18px 0 0 !important;
  }
}

/* FAQ pills hug their text + arrow exactly (was stretching to 82%
   of the container). Each pill ends just after the yellow arrow
   badge instead of running on to the right margin. */
.faq-section#faq .faq-list {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}
.faq-section#faq .faq-item {
  /* Width is set inline by the FAQ pill sizing IIFE in script.js
     (per-question pixel value = text + chrome). Just ensure flex
     doesn't stretch the item. */
  max-width: 100% !important;
  flex: 0 0 auto !important;
}
.faq-section#faq .faq-q {
  width: auto !important;
  justify-content: flex-start !important;
  gap: 14px;
}
.faq-section#faq .faq-q__text {
  flex: 0 0 auto;
}
/* When a pill expands, allow it to grow to a moderate cap. */
.faq-section#faq .faq-item:hover,
.faq-section#faq .faq-item:has(.faq-q[aria-expanded="true"]) {
  /* Expand to a comfortable reading width when opened. */
  width: min(620px, 100%) !important;
  flex: 0 0 auto !important;
}
.faq-section#faq .faq-item:hover .faq-q__text,
.faq-section#faq .faq-item:has(.faq-q[aria-expanded="true"]) .faq-q__text {
  flex: 1 1 auto;
}

/* FAQ accordion pills — sized 25% larger than the process section
   pills (was 12.6 / 45 / 13-18 / 20). Extra right padding so the
   yellow arrow has breathing room before the pill ends. */
.faq-section#faq .faq-q {
  font-size: 15.75px !important;
  font-weight: 500 !important;
  letter-spacing: -0.005em !important;
  line-height: 1.25 !important;
  /* Padding-right reduced from 28 to 12 so the pill ends just past
     the yellow arrow badge instead of leaving a wide empty gap.
     The companion IIFE in script.js computes the pill's pixel width
     from the same chrome values — keep them in sync. */
  padding: 16px 12px 16px 22px !important;
  min-height: 56px !important;
}
.faq-section#faq .faq-q__text {
  font-size: 15.75px !important;
  font-weight: 500 !important;
  letter-spacing: -0.005em !important;
  line-height: 1.25 !important;
}
.faq-section#faq .faq-icon {
  width: 25px !important;
  height: 25px !important;
}
.faq-section#faq .faq-icon svg {
  width: 13px !important;
  height: 13px !important;
}
@media (max-width: 699px) {
  /* FAQ title removed from this rule — kept at the larger H2-tier
     mobile size via the global mobile heading rule near the end of
     this stylesheet. Was being scaled down to ~12 px which read as
     a caption. */
  .contact-heading,
  .social-profiles-label {
    font-size: clamp(0.72rem, 3.96vw, 1.62rem) !important;
    margin-left: calc(50% - 50vw + 16px) !important;
    margin-right: calc(50% - 50vw + 16px) !important;
    margin-bottom: 32px !important;
  }
}
/* Toggle full vs short FAQ title by viewport */
.faq-title--mobile { display: none; }
@media (max-width: 768px) {
  .faq-title--desktop { display: none; }
  .faq-title--mobile  { display: block; }
}

.faq-list {
  list-style: none;
  padding: 0;
  margin: 0 0 36px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.faq-item {
  /* Pill is sized to its content (question text + arrow + padding)
     in the collapsed state — so the white background only extends
     just past the yellow arrow badge instead of running across the
     whole column. Capped at 82 % so longer questions don't push
     into the heading column on wide viewports. Hover / expanded
     state below grows it to the full 100 % to make room for the
     answer body. */
  width: fit-content;
  max-width: var(--faq-item-w, 82%);
  background: #fff;
  border-radius: 41px;
  overflow: hidden;
  transition: width 0.65s cubic-bezier(0.16, 1, 0.3, 1),
              max-width 0.65s cubic-bezier(0.16, 1, 0.3, 1);
}

.faq-item:last-child {
  /* no border in pill mode */
}

.faq-item:hover,
.faq-item:has(.faq-q[aria-expanded="true"]) {
  /* Override both: width expands the inner shrink-to-fit box, and
     max-width unblocks the 82 % cap so the pill can reach edge-to
     edge of its column when it actually has content to show. */
  width: 100%;
  max-width: 100%;
}

/* Hidden items (show more) */
.faq-item--more {
  display: none;
}

.faq-item--more.is-visible {
  display: block;
}

.faq-q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 28px 32px;
  background: none;
  border: none;
  cursor: pointer;
  font-family: 'Inter', sans-serif;
  font-size: 1.575rem;
  font-weight: 500;
  color: var(--text);
  text-align: left;
  gap: 16px;
  transition: color 0.2s ease;
  /* Allow long questions to wrap onto multiple lines so they don't
     get clipped on narrower pills (e.g. the /faqs page). */
  white-space: normal;
  align-items: flex-start;
}

.faq-q__text {
  min-width: 0;
  flex: 1;
  overflow-wrap: break-word;
}

.faq-q:hover {
  color: var(--accent, #3a3a2e);
}

/* Mobile — smaller question font, allow wrap to multiple lines, indent matches answer */
@media (max-width: 768px) {
  .faq-q {
    font-size: 0.95rem !important;
    white-space: normal;
    align-items: flex-start;
    padding: 20px 32px;
  }
  .faq-q__text {
    overflow: visible;
    white-space: normal;
    overflow-wrap: break-word;
    line-height: 1.35;
  }
}

/* Arrow icon — uses pb-bar__btn for base styles; only FAQ-specific overrides here */
/* Match the pricing bar's font stack so ↗ falls back to the same system font */
.faq-icon {
  font-family: Inter, -apple-system, "system-ui", sans-serif;
  color: #000;
}

.faq-q .faq-icon { background: #FFD600; }

.faq-item:hover .faq-icon { background: #f0c800; }

.faq-q[aria-expanded="true"] .faq-icon {
  transform: rotate(180deg);
  background: #FF5733;
  color: #fff;
}

/* Answer — max-height transition matches the pricing bar body approach */
.faq-a {
  max-height: 0;
  overflow: hidden;
  padding: 0 32px;
  transition: max-height 0.65s cubic-bezier(0.16, 1, 0.3, 1),
              padding-bottom 0.5s ease;
}

.faq-q[aria-expanded="true"] + .faq-a {
  max-height: 480px;
  padding-bottom: 25px;
}

.faq-a p {
  font-family: 'Inter', sans-serif;
  font-size: 1rem;
  line-height: 1.75;
  color: var(--text-2);
  padding-bottom: 16px;
  margin: 0;
}

.faq-a ul {
  list-style: none;
  padding: 0;
  margin: 0 0 16px;
}

.faq-a ul li {
  font-family: 'Inter', sans-serif;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--text-2);
  padding: 4px 0 4px 18px;
  position: relative;
}

.faq-a ul li::before {
  content: '—';
  position: absolute;
  left: 0;
  color: var(--text-3);
  font-size: 0.85rem;
}

/* Show more button */
.faq-more-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: 1.5px solid var(--border);
  border-radius: 100px;
  padding: 10px 22px;
  font-family: 'Inter', sans-serif;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--text-2);
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.faq-more-btn:hover {
  border-color: var(--text);
  color: var(--text);
}

.faq-more-icon {
  transition: transform 0.3s ease;
}

.faq-more-btn[aria-expanded="true"] .faq-more-icon {
  transform: rotate(180deg);
}

.faq-more-btn[aria-expanded="true"] {
  display: none; /* hide once expanded */
}

/* --- source lines 3364-3584 --- */
/* ======================================================
   CONTACT
   ====================================================== */
.contact {
  padding: 60px 28px 80px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  max-width: 660px;
  margin: 0 auto;
  box-sizing: border-box;
  width: 100%;
  /* Always visible — email button scrolls directly here */
}

.contact-heading {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(2rem, 5vw, 3.8rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.08;
  margin-bottom: 36px;
  color: var(--text);
  text-align: left;
}

.contact-card {
  background: #fff;
  border-radius: var(--r-card);
  padding: 28px;
  width: 100%;
  max-width: 540px;
  box-sizing: border-box;
}

.contact-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
}

.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
@media (max-width: 768px) {
  .form-row { grid-template-columns: 1fr; }
}

.form-input {
  width: 100%;
  background: rgba(0,0,0,0.055);
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 14px 16px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.95rem;
  color: var(--text);
  outline: none;
  transition: border-color 0.2s;
  box-sizing: border-box;
}
.form-input:focus { border-color: rgba(0,0,0,0.18); }
.form-input::placeholder { color: var(--text-3); }

.form-textarea {
  resize: none;
  height: 140px;
}

.form-submit {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--text);
  color: #fff;
  border: none;
  border-radius: 100px;
  padding: 18px 28px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.95rem;
  cursor: pointer;
  transition: opacity 0.2s, transform 0.25s var(--ease-out);
  align-self: flex-start;
}
.form-submit:hover {
  opacity: 0.85;
}
.form-submit:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

/* Textarea wrapper — needed for the sending overlay */
.form-textarea-wrap {
  position: relative;
}

/* Loading overlay that appears over the textarea while sending */
.form-sending-overlay {
  position: absolute;
  inset: 0;
  background: rgba(255,255,255,0.85);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}
.form-textarea-wrap.form-is-sending .form-sending-overlay {
  opacity: 1;
  pointer-events: all;
}

/* Spinner */
@keyframes form-spin { to { transform: rotate(360deg); } }
.form-spinner {
  width: 22px;
  height: 22px;
  border: 2.5px solid rgba(0,0,0,0.12);
  border-top-color: var(--text);
  border-radius: 50%;
  animation: form-spin 0.7s linear infinite;
}

/* Checkbox + submit row */
.form-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

/* "I promise I am not an agent" checkbox */
.form-robot-check {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.82rem;
  color: var(--text-2);
  user-select: none;
  white-space: nowrap;
}
@media (max-width: 768px) {
  .form-robot-check { font-size: 0.7rem; }
}
.form-robot-check input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 17px;
  height: 17px;
  border: 1.5px solid rgba(0,0,0,0.25);
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.15s, border-color 0.15s;
  position: relative;
}
.form-robot-check input[type="checkbox"]:checked {
  background: var(--text);
  border-color: var(--text);
}
.form-robot-check input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  left: 3px;
  top: 1px;
  width: 5px;
  height: 9px;
  border: 2px solid #fff;
  border-top: none;
  border-left: none;
  transform: rotate(45deg);
}
@keyframes robot-shake {
  0%,100% { transform: translateX(0); }
  20%      { transform: translateX(-4px); }
  40%      { transform: translateX(4px); }
  60%      { transform: translateX(-3px); }
  80%      { transform: translateX(3px); }
}
.form-robot-check--shake { animation: robot-shake 0.4s ease; }

/* Success state — shown after send */
.form-success {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 0 4px;
}
.form-success[aria-hidden="true"] { display: none; }

.form-success-msg {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 1.05rem;
  font-weight: 400;
  color: var(--text);
  margin: 0;
}
.form-success-sub {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.9rem;
  color: var(--text-2);
  margin: 0;
}
.form-success-sub a {
  color: var(--text);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.form-success-sub a:hover { opacity: 0.7; }

/* --- source lines 3585-3699 --- */
/* ======================================================
   SOCIAL PROFILE CARDS (LinkedIn + X)
   ====================================================== */
.social-profiles {
  max-width: 660px;
  margin: 0 auto;
  padding: 120px 28px 160px;
  width: 100%;
  box-sizing: border-box;
}

.social-profiles-label {
  font-family: 'Inter', sans-serif;
  font-size: clamp(2rem, 5vw, 3.8rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.08;
  color: var(--text);
  margin-bottom: 36px;
}

.social-profiles .social-cards-row {
  max-width: 540px;
}

.social-cards-row {
  display: flex;
  gap: 10px;
}

/* Base card — mirrors .card without triggering JS canvas listeners */
.social-card {
  flex: 1;
  border-radius: var(--r-card);
  display: flex;
  flex-direction: column;
  text-decoration: none;
  cursor: pointer;
  position: relative;
  container-type: inline-size;
  transition: transform 0.35s var(--ease-out);
  user-select: none;
}

.social-card:hover {
  transform: translateY(-6px) scale(1.02);
}

/* Top row — avatar left, logo right */
.social-card-top {
  flex: 1;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  padding: 24px 24px 16px;
}

.social-logo-large {
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  opacity: 0.92;
}

.social-avatar {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center 12%;
  flex-shrink: 0;
  border: 2px solid rgba(255,255,255,0.28);
}

/* Footer — name only */
.social-card-footer {
  display: flex;
  align-items: center;
  padding: 16px 24px 20px;
}

.social-card-name {
  font-family: 'IBM Plex Mono', monospace;
  font-size: min(7cqi, 1.3rem);
  font-weight: 400;
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* LinkedIn */
.social-card--linkedin                      { background: #0A66C2; }
.social-card--linkedin .social-logo-large   { color: #fff; }
.social-card--linkedin .social-card-footer  { color: #fff; }

/* X */
.social-card--x                      { background: #1A1A18; }
.social-card--x .social-logo-large   { color: rgba(255,255,255,0.88); }
.social-card--x .social-card-footer  { color: rgba(255,255,255,0.90); }

/* Stack on mobile — X on top, LinkedIn below; extra room above nav toolbar */
@media (max-width: 767px) {
  .social-profiles {
    padding-bottom: 220px;
  }
  .social-profiles .social-cards-row {
    flex-direction: column;
    max-width: 100%;
  }
  .social-card--x        { order: -1; }
  .social-card--linkedin { order:  1; }
}

/* ========================================================================
   LAYER 08 · ANNOTATION TOOLS — sticky notes, clear-all, draw canvas, tool cursor states
   ======================================================================== */

/* --- source lines 3700-3849 --- */
/* ======================================================
   STICKY NOTES
   ====================================================== */
.sticky-note {
  position: absolute;
  width: 164px;
  background: #FFF9B1;
  padding: 8px;
  border-radius: 2px;
  box-shadow: 2px 4px 14px rgba(0,0,0,0.16), 0 1px 3px rgba(0,0,0,0.08);
  z-index: 9700;
  cursor: grab;
}
.sticky-note:active { cursor: grabbing; }

/* Textarea — margin-top leaves room for the delete × button */
.sticky-note textarea {
  width: 100%;
  height: 80px;
  border: none;
  background: transparent;
  resize: none;
  font-family: 'Inter', -apple-system, sans-serif;
  font-size: 0.8rem;
  line-height: 1.55;
  color: #3a3000;
  outline: none;
  cursor: text;
  display: block;
  margin-top: 14px;
}

/* ── Delete × button (top-right, appears on hover) ── */
.sticky-delete {
  position: absolute;
  top: 5px;
  right: 5px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: none;
  background: rgba(0,0,0,0.10);
  color: #3a3000;
  font-size: 0.78rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.15s, background 0.15s;
  padding: 0;
}
.sticky-note:hover .sticky-delete { opacity: 1; }
.sticky-delete:hover { background: rgba(0,0,0,0.22); }

/* ── From email row ── */
.sticky-from-row {
  display: flex;
  align-items: center;
  gap: 5px;
  border-top: 1px solid rgba(58,48,0,0.12);
  padding-top: 6px;
  margin-top: 4px;
}
.sticky-from-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.6rem;
  color: rgba(58,48,0,0.45);
  letter-spacing: 0.04em;
  flex-shrink: 0;
  user-select: none;
}
.sticky-from-input {
  flex: 1;
  min-width: 0;
  border: none;
  background: transparent;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  color: #3a3000;
  outline: none;
  cursor: text;
  padding: 0;
  line-height: 1.4;
}
.sticky-from-input::placeholder { color: rgba(58,48,0,0.30); }

/* ── Send button (paper airplane, bottom-left) ── */
.sticky-send {
  display: flex;
  align-items: center;
  gap: 5px;
  border: none;
  background: none;
  color: rgba(58,48,0,0.30);
  cursor: pointer;
  padding: 5px 0 2px 0;
  transition: color 0.15s;
  overflow: hidden;
  max-width: 100%;
}
.sticky-send:hover { color: rgba(58,48,0,0.72); }
.sticky-send svg { flex-shrink: 0; }

/* Label slides in on hover */
.sticky-send-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.65rem;
  white-space: nowrap;
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-width 0.25s var(--ease-out), opacity 0.2s;
}
.sticky-send:hover .sticky-send-label {
  max-width: 120px;
  opacity: 1;
}

/* Sending / sent states — label always visible, no hover needed */
.sticky-send[data-state] { color: rgba(58,48,0,0.72); cursor: default; }
.sticky-send[data-state] .sticky-send-label { max-width: 120px; opacity: 1; }
.sticky-send[data-state="sent"] { color: rgba(30,120,60,0.80); }

/* Spinner */
.sticky-spinner {
  flex-shrink: 0;
  width: 10px;
  height: 10px;
  border: 1.5px solid rgba(58,48,0,0.18);
  border-top-color: rgba(58,48,0,0.65);
  border-radius: 50%;
  animation: sticky-spin 0.7s linear infinite;
}
@keyframes sticky-spin { to { transform: rotate(360deg); } }

/* Validation shake on the textarea / from input when the user tries to
   send without filling them in. */
.sticky-shake { animation: sticky-shake 0.45s cubic-bezier(0.36, 0.07, 0.19, 0.97); }
@keyframes sticky-shake {
  10%, 90% { transform: translateX(-1px); }
  20%, 80% { transform: translateX(2px); }
  30%, 50%, 70% { transform: translateX(-3px); }
  40%, 60% { transform: translateX(3px); }
}

/* Home-context notes are hidden when canvas is open */
body[data-card] .sticky-note[data-page="home"] { display: none; }

/* --- source lines 3850-3894 --- */
/* ======================================================
   CLEAR ALL BUTTON
   ====================================================== */
.clear-all-btn {
  position: fixed;
  bottom: max(28px, calc(16px + env(safe-area-inset-bottom)));
  /* left is set dynamically by JS to hug the right of the toolbar */
  left: 0;
  z-index: 9750;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.76rem;
  font-weight: 400;
  color: rgba(255,255,255,0.9);
  background: rgba(17,17,17,0.92);
  border: none;
  border-radius: 100px;
  padding: 12px 18px;
  cursor: pointer;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s var(--ease-out), transform 0.2s var(--ease-out);
  transform: translateY(8px);
  letter-spacing: 0.02em;
  box-shadow: 0 8px 32px rgba(0,0,0,0.18);
}
.clear-all-btn.visible {
  opacity: 1;
  pointer-events: all;
  transform: translateY(0);
}
.clear-all-btn:hover { background: rgba(26,26,24,0.98); }

/* Mobile — pin to top-right corner and shorten label to just "Clear" */
@media (max-width: 768px) {
  .clear-all-btn {
    bottom: auto !important;
    top: 16px;
    right: 16px;
    left: auto !important;
  }
  .clear-all-btn__rest { display: none; }
}

/* --- source lines 3895-3906 --- */
/* ======================================================
   DRAW CANVAS
   ====================================================== */
.draw-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 9700;
}

/* --- source lines 3907-3929 --- */
/* ======================================================
   TOOL CURSOR STATES
   ====================================================== */
body[data-tool="pen"] {
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z' fill='white' stroke='%231A1A18' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") 2 22, crosshair;
  overflow: hidden; /* lock page scroll while drawing */
}
/* Lock html scroll container too (body alone isn't always enough) */
html:has(body[data-tool="pen"]) {
  overflow: hidden;
}
/* Lock canvas overlay scroll while drawing */
body[data-tool="pen"] .canvas-overlay {
  overflow: hidden;
}
body[data-tool="sticky"] {
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22' viewBox='0 0 24 24'%3E%3Cpath d='M5 3h14a2 2 0 012 2v10l-7 7H5a2 2 0 01-2-2V5a2 2 0 012-2z' fill='%23FFF9B1' stroke='%231A1A18' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M14 21v-7h7' fill='none' stroke='%231A1A18' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") 0 0, crosshair;
}

/* Always restore correct cursors on interactive elements regardless of active tool */
a, button, .nav-icon, .social-btn, .arrow-btn, .form-submit, label { cursor: pointer; }
input, textarea, select { cursor: text; }

/* ========================================================================
   LAYER 09 · CONTENT SECTIONS — part 3: thoughts strip, testimonials fan, responsive tweaks, footer pills, intro stage, site footer
   ======================================================================== */

/* --- source lines 3930-4303 --- */
/* ======================================================
   THOUGHTS STRIP
   ====================================================== */
.thoughts-section {
  padding: 80px 0 80px; /* no horizontal padding — heading handles its own indent */
  display: none; /* hidden for now */
}

.thoughts-eyebrow {
  /* Matches .faq-section: max-width 760px centred, 28px inner padding */
  max-width: 760px;
  margin: 0 auto 80px;
  padding: 0 28px;
  font-family: 'Inter', sans-serif;
  font-size: clamp(2rem, 5vw, 3.8rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.08;
  color: var(--text);
  text-align: left;
}

/* ── Mobile + tablet: 2-col horizontal card grid ── */
.thoughts-strip {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  padding: 0 28px;
}

/* Defeat any JS-set inline left/top/height on tablet + mobile */
@media (max-width: 899px) {
  .thoughts-strip { height: auto !important; }
  .thought-card   { left: auto !important; top: auto !important; position: relative !important; }
}
@media (max-width: 699px) {
  .thoughts-strip { grid-template-columns: 1fr; padding: 0 20px; }
}

/* Horizontal card — illustration left, text right (mobile/tablet) */
.thought-card {
  position: relative;
  display: flex;
  flex-direction: row;
  width: 100%;
  min-height: 130px;
  border-radius: 20px;
  background: var(--bg);
  color: var(--txt);
  text-decoration: none;
  overflow: hidden;
  cursor: pointer;
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.55s var(--ease-out),
              transform 0.55s var(--ease-out);
}

.thoughts-strip.is-visible .thought-card {
  opacity: 1;
  transform: translateY(0);
}

.thought-card:hover {
  transform: translateY(-5px) scale(1.02) !important;
  transition: transform 0.25s var(--ease-out) !important;
}

.thought-card:active {
  transform: translateY(-2px) scale(1.01) !important;
  transition: transform 0.1s ease !important;
}

/* Illustration — left column */
.thought-pattern {
  flex-shrink: 0;
  width: 120px;
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: rgba(0,0,0,0.08);
}
.thought-pattern svg {
  width: 85%;
  height: 85%;
  color: var(--txt);
  opacity: 0.38;
}

/* Text — right column */
.thought-body {
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: 1;
  gap: 8px;
}

.thought-title {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: -0.01em;
}

.thought-tag {
  display: inline-block;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 0.58rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  opacity: 0.55;
}

/* ── Desktop: original overlapping stacked fan grid ── */
@media (min-width: 900px) {
  .thoughts-strip {
    display: block;   /* JS controls layout via position:absolute */
    position: relative;
    height: 560px;    /* JS overrides on resize */
    padding: 0;
  }

  .thought-card {
    position: absolute;
    width: 240px;
    height: 240px;
    flex-direction: column;
    border-radius: 24px;
    min-height: unset;
    opacity: 0;
    transform: translateY(70px);
  }

  /* Per-card fan rotations — initial dropped state */
  .thought-card:nth-child(1) { transform: rotate(-5deg)  translateY(70px); z-index:1; }
  .thought-card:nth-child(2) { transform: rotate(4deg)   translateY(70px); z-index:2; }
  .thought-card:nth-child(3) { transform: rotate(-2deg)  translateY(70px); z-index:3; }
  .thought-card:nth-child(4) { transform: rotate(7deg)   translateY(70px); z-index:4; }
  .thought-card:nth-child(5) { transform: rotate(3deg)   translateY(70px); z-index:5; }
  .thought-card:nth-child(6) { transform: rotate(-7deg)  translateY(70px); z-index:6; }
  .thought-card:nth-child(7) { transform: rotate(5deg)   translateY(70px); z-index:7; }
  .thought-card:nth-child(8) { transform: rotate(-3deg)  translateY(70px); z-index:8; }

  /* Settled fan */
  .thoughts-strip.is-visible .thought-card:nth-child(1) { opacity:1; transform: rotate(-5deg);  }
  .thoughts-strip.is-visible .thought-card:nth-child(2) { opacity:1; transform: rotate(4deg);   }
  .thoughts-strip.is-visible .thought-card:nth-child(3) { opacity:1; transform: rotate(-2deg);  }
  .thoughts-strip.is-visible .thought-card:nth-child(4) { opacity:1; transform: rotate(7deg);   }
  .thoughts-strip.is-visible .thought-card:nth-child(5) { opacity:1; transform: rotate(3deg);   }
  .thoughts-strip.is-visible .thought-card:nth-child(6) { opacity:1; transform: rotate(-7deg);  }
  .thoughts-strip.is-visible .thought-card:nth-child(7) { opacity:1; transform: rotate(5deg);   }
  .thoughts-strip.is-visible .thought-card:nth-child(8) { opacity:1; transform: rotate(-3deg);  }

  /* Hover lifts card */
  .thoughts-strip.is-visible .thought-card:hover {
    transform: rotate(0deg) translateY(-10px) scale(1.04) !important;
    z-index: 20 !important;
    transition: transform 0.25s var(--ease-out) !important;
  }

  /* Active */
  .thoughts-strip.is-visible .thought-card:active {
    transform: rotate(0deg) translateY(-6px) scale(1.01) !important;
    transition: transform 0.1s ease !important;
  }

  /* Illustration — top portion, full width */
  .thought-pattern {
    width: 100%;
    height: 130px;
    align-self: auto;
  }
  .thought-pattern svg {
    width: 100%;
    height: 100%;
  }

  /* Text — below illustration */
  .thought-body {
    padding: 10px 16px 14px;
    justify-content: space-between;
    gap: 0;
  }
}

/* Actions row: Show more + See all — aligned with eyebrow */
.thoughts-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 28px 0 0 max(28px, calc((100% - 760px) / 2 + 28px));
}
@media (max-width: 699px) {
  .thoughts-actions { margin-left: 20px; }
}

/* Cards inside more-strip must stay in grid flow, not the fan/scatter layout */
.thoughts-more-strip .thought-card {
  position: relative !important;
  width: auto !important;
  left: auto !important;
  top: auto !important;
  transform: none !important;
  opacity: 1 !important;
}
.thoughts-more-strip .thought-card:hover {
  transform: translateY(-5px) scale(1.02) !important;
}

/* More cards grid — same style as the mobile/tablet grid */
.thoughts-more-strip {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  padding: 14px 28px 0;
  max-width: calc(760px + 56px);
}
@media (min-width: 900px) {
  .thoughts-more-strip {
    grid-template-columns: repeat(4, 1fr);
    padding: 28px max(28px, calc((100% - 760px) / 2 + 28px)) 0;
    max-width: 100%;
  }
}
@media (max-width: 699px) {
  .thoughts-more-strip { grid-template-columns: 1fr; padding: 14px 20px 0; }
}

/* Shared pill style for both buttons */
.thoughts-show-more-btn,
.thoughts-see-all-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: 1.5px solid var(--border);
  border-radius: 100px;
  padding: 10px 22px;
  font-family: 'Inter', sans-serif;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--text-2);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}

.thoughts-show-more-btn:hover,
.thoughts-see-all-btn:hover {
  border-color: var(--text);
  color: var(--text);
}

.thoughts-show-more-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

/* About → Experience Timeline + More buttons — same pill base, with a filled
   circular arrow badge after the label (matches the work-thumb hover badge). */
.about-actions {
  margin-top: 32px;
  display: flex;
  justify-content: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}
.about-experience-btn .btn-arrow-circle,
.about-more-btn .btn-arrow-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  /* Match the Experience card on the hero (.card--ai background #0E4C4B) */
  background: #0E4C4B;
  color: #fff;
  margin-left: 6px;
  flex-shrink: 0;
  transition: transform 0.22s var(--ease-out), background 0.2s ease;
}
.about-experience-btn:hover .btn-arrow-circle {
  transform: translate(2px, -2px);
}
.about-more-btn:hover .btn-arrow-circle {
  transform: translateY(2px);
}
/* Rotate the down-chevron 180° when the section is expanded so it reads
   as a "less / collapse" affordance. */
.about-more-btn[aria-expanded="true"] .btn-arrow-circle--down {
  transform: rotate(180deg);
}
.about-more-btn[aria-expanded="true"]:hover .btn-arrow-circle--down {
  transform: rotate(180deg) translateY(2px);
}

/* Collapsible "more about" paragraphs. Renamed to .about-more-body so the
   scatter-text effect (which targets `.about-body`) leaves it alone — we
   want the collapse to actually clip via max-height, not be absolutely
   positioned by the scatter wrapper. */
.about-more-body {
  display: block;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  margin-top: 0;
  transition: max-height 0.5s var(--ease-out),
              opacity   0.4s ease,
              margin-top 0.4s var(--ease-out),
              margin-bottom 0.4s var(--ease-out);
}
.about-more-body.is-expanded {
  max-height: 1200px;
  opacity: 1;
  margin-top: 0;
  margin-bottom: 28px;
}
/* Paragraphs inside the more-body inherit the same body type as .about-body p */
.about-more-body p {
  font-family: 'Inter', sans-serif;
  font-size: 1.12rem;
  line-height: 1.78;
  color: var(--text-2);
  margin-bottom: 20px;
}

/* Scatter overlay — canvas absolutely positioned over the paragraphs, real
   text hidden until the assemble animation finishes. */
.about-more-scatter-wrap {
  position: relative;
}
.about-more-scatter-canvas {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.35s ease;
  z-index: 2;
}
.about-more-scatter-canvas.is-assembled {
  opacity: 0;
}
.about-more-body p {
  opacity: 0;
  transition: opacity 0.35s ease;
}
.about-more-body.is-assembled p {
  opacity: 1;
}

/* DOM order is buttons → body, but visually we want body ABOVE the buttons
   when expanded. Make the about-block a flex column and use `order` so the
   body drops in above the actions on expand, pushing them down. */
.about-block {
  display: flex;
  flex-direction: column;
}
.about-block > .about-title,
.about-block > .about-chip,
.about-block > .about-meta { order: 1; }
.about-more-body,
.about-more-scatter-wrap { order: 2; }   /* sits above the actions when expanded */
.about-actions   { order: 3; }
.about-block > svg.about-curve-svg,
.about-block > .about-scatter-wrap { order: 4; }

/* --- source lines 4834-5081 --- */
/* ======================================================
   TESTIMONIALS
   ====================================================== */
.testimonials {
  /* Sits cleanly below the process panel — no negative margin so
     the expanded panel pushes testimonials down instead of being
     overlapped by them. */
  padding: 60px 0 120px;
  margin-top: 0;
  position: relative;
  z-index: 0;
}

.testimonials-header {
  padding: 0 28px 60px;
  max-width: 660px;
  margin: 0 auto;
  width: 100%;
  box-sizing: border-box;
  flex-shrink: 0;
}

.testimonials-heading {
  font-family: 'Inter', sans-serif;
  font-size: clamp(2.5rem, 6.25vw, 4.75rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.08;
  color: var(--text);
}

.testimonials-sticky {
  display: flex;
  flex-direction: column;
  overflow: visible;
  box-sizing: border-box;
}

.testimonials-track {
  display: flex;
  gap: 0;
  /* Generous horizontal padding so every card has space to be dragged
     into view; horizontal alignment is flex-start so the drag bounds
     compute cleanly (trackX=0 = first card flush left, trackX=-N = last
     card flush right). Initial centering of card 3 is done in JS. */
  padding: 40px 50vw 60px;
  will-change: transform;
  justify-content: flex-start;
  align-items: center;
}

.testimonial-card {
  flex-shrink: 0;
  width: 260px;
  min-height: 320px;
  border-radius: 20px;
  padding: 28px 28px 24px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  position: relative;
  /* Start invisible — JS triggers reveal on scroll */
  opacity: 0;
  margin-left: -55px;
  transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.5s ease, z-index 0s;
  user-select: none;
  cursor: default;
}

.testimonial-card:first-child { margin-left: 0; }

/* Large opening quote mark */
.testimonial-card::before {
  content: '\201C';
  font-family: Georgia, serif;
  font-size: 3.5rem;
  line-height: 1;
  display: block;
  margin-bottom: 8px;
  opacity: 0.55;
}

/* Per-card pastel colour + fan rotation (start dropped 70px) */
.testimonial-card:nth-child(1) { background: #2A6042; color: #C8F0D8; z-index:1; transform: rotate(-4deg)   translateY(70px); }
.testimonial-card:nth-child(2) { background: #F5C340; color: #2A1A00; z-index:2; transform: rotate(-1.5deg) translateY(70px); }
.testimonial-card:nth-child(3) { background: #2D1B56; color: #E0D0F8; z-index:3; transform: rotate(0.5deg)  translateY(70px); }
.testimonial-card:nth-child(4) { background: #FF7A00; color: #1A1A18; z-index:4; transform: rotate(2.5deg)  translateY(70px); } /* Bugcrowd orange */
.testimonial-card:nth-child(5) { background: #FFFFFF; color: #1A1A18; z-index:5; transform: rotate(4.5deg)  translateY(70px); } /* Johnson Bikes — white */
.testimonial-card:nth-child(6) { background: #3676FF; color: #FFFFFF; z-index:6; transform: rotate(6.5deg)  translateY(70px); } /* Apps blue for 3 Bees */
.testimonial-card:nth-child(7) { background: #EE3F8E; color: #FFFFFF; z-index:7; transform: rotate(8.5deg)  translateY(70px); } /* Magic Bra pink */
.testimonial-card:nth-child(8) { background: #111111; color: #F4F3EE; z-index:8; transform: rotate(10.5deg) translateY(70px); } /* Curiious black */
.testimonial-card:nth-child(9) { background: #AAEA38; color: #182400; z-index:9; transform: rotate(12.5deg) translateY(70px); } /* matches the "Pest Management Inspection App" pill */
.testimonial-card:nth-child(10) { background: #FFA500; color: #1A1A18; z-index:10; transform: rotate(14.5deg) translateY(70px); } /* Giles Anderton — Storekat orange */

/* Settled (fan) state */
.testimonials-track.is-visible .testimonial-card              { opacity: 1; }
.testimonials-track.is-visible .testimonial-card:nth-child(1) { transform: rotate(-4deg);   }
.testimonials-track.is-visible .testimonial-card:nth-child(2) { transform: rotate(-1.5deg); }
.testimonials-track.is-visible .testimonial-card:nth-child(3) { transform: rotate(0.5deg);  }
.testimonials-track.is-visible .testimonial-card:nth-child(4) { transform: rotate(2.5deg);  }
.testimonials-track.is-visible .testimonial-card:nth-child(5) { transform: rotate(4.5deg);  }
.testimonials-track.is-visible .testimonial-card:nth-child(6) { transform: rotate(6.5deg);  }
.testimonials-track.is-visible .testimonial-card:nth-child(7) { transform: rotate(8.5deg);  }
.testimonials-track.is-visible .testimonial-card:nth-child(8) { transform: rotate(10.5deg); }
.testimonials-track.is-visible .testimonial-card:nth-child(9) { transform: rotate(12.5deg); }
.testimonials-track.is-visible .testimonial-card:nth-child(10) { transform: rotate(14.5deg); }

.testimonial-card:hover {
  transform: rotate(0deg) translateY(-6px) scale(1.04) !important;
  z-index: 10;
}

/* Mobile — vertical sticky stack. Each card anchors at a slightly lower
   "top" than the one before, so they pile on top each other near the top of
   the viewport as the user scrolls. The first card (green) needs an explicit
   sticky stop now that the heading is gone, otherwise it flies past. */
@media (max-width: 768px) {
  .testimonials-track {
    flex-direction: column;
    align-items: stretch;
    padding: 40px 20px 60px;
    gap: 24px;
  }
  .testimonial-card {
    width: 100%;
    margin-left: 0;
    position: sticky;
    transform: none !important;
  }
  /* Anchor the first card at top-quarter of the viewport, then stack each
     subsequent card 14px lower so they fan out as the user scrolls past. */
  .testimonial-card:nth-child(1) { top: 14vh; }
  .testimonial-card:nth-child(2) { top: calc(14vh + 14px); }
  .testimonial-card:nth-child(3) { top: calc(14vh + 28px); }
  .testimonial-card:nth-child(4) { top: calc(14vh + 42px); }
  .testimonial-card:nth-child(5) { top: calc(14vh + 56px); }
}

.testimonial-quote {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 1.08rem;
  font-weight: 400;
  line-height: 1.6;
  color: inherit;
  flex: 1;
  margin: 0 0 16px;
  /* Collapsed: ~5 lines of content (5 × 1.6 line-height = 8em). Animated
     to/from "full height" via max-height so the open/close eases nicely. */
  max-height: 8em;
  overflow: hidden;
  transition: max-height 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.testimonial-card.is-expanded .testimonial-quote {
  /* Generous ceiling — comfortably bigger than any quote so the eased
     transition still feels smooth right to the end. */
  max-height: 60em;
}

/* Small hollow "+ More" pill below the quote. Inherits text colour from
   the card (so it adapts to each card's palette). */
.testimonial-more-btn {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 1px solid currentColor;
  color: inherit;
  font: inherit;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 4px 10px 4px 8px;
  border-radius: 999px;
  cursor: pointer;
  margin: 0 0 16px;
  opacity: 0.85;
  transition: opacity 0.18s ease, background 0.18s ease;
}
.testimonial-more-btn:hover { opacity: 1; background: rgba(0,0,0,0.06); }

.testimonial-author {
  display: flex;
  align-items: center;
  gap: 10px;
}

.testimonial-author-info {
  display: flex;
  flex-direction: column;
}

.testimonial-name {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 0.82rem;
  font-weight: 700;
  color: inherit;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.testimonial-role {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 0.72rem;
  color: inherit;
  opacity: 0.55;
  margin-top: 2px;
}

/* Custom drag cursor (follows mouse, fixed position) */
.drag-cursor {
  position: fixed;
  top: 0;
  left: 0;
  width: 88px;
  height: 88px;
  border-radius: 50%;
  background: #1A1714;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  z-index: 9999;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.6);
  transition: opacity 0.2s ease, transform 0.2s ease;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.58rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}

.drag-cursor.is-visible {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

/* Mobile: stack cards vertically, fade in on scroll */
@media (max-width: 699px) {
  .testimonials-sticky    { overflow: visible; }
  .testimonials-track     { flex-direction: column; padding: 0 20px; gap: 16px; transform: none !important; }
  .testimonial-card       { width: 100%; margin-left: 0; opacity: 0; transform: translateY(28px) rotate(0deg) !important;
                            transition: opacity 0.5s ease, transform 0.5s ease; }
  .testimonial-card.is-visible { opacity: 1; transform: translateY(0) rotate(0deg) !important; }
}

/* --- source lines 5082-5109 --- */
/* ======================================================
   RESPONSIVE
   ====================================================== */
/* On mobile, pin logo to top-left — JS alignment with "Build anything." only applies at wider widths */
@media (max-width: 699px) {
  .logo { left: 20px !important; top: 28px; }

  /* ── Equal section top spacing ─────────────────────────────────────────
     Every section heading gets the same breathing room above it on mobile.
     Halved from the original 80 px → 40 px so the page reads tighter on
     phones (was creating dead bands above each H2). */
  .hero           { padding-top: 20px; }
  .about-block    { padding-top: 20px; }
  .testimonials   { padding-top: 20px; }
  .thoughts-section { padding-top: 20px; }
  .faq-section    { padding-top: 20px; }
  .contact        { padding-top: 20px; }
}

@media (min-width: 900px) {
  /* Logo left is set dynamically by JS to align with the B of "Build anything." */
  .logo { top: 48px; }
  .hero { padding: 104px 17.5vw 104px; }
  .work { padding: 80px 28px 18vh calc(15vw + 100px); }
  /* Work panel title left-aligns with hero H1 */
  .work-panel { padding-left: 17.5vw; }
}

/* --- source lines 5110-5193 --- */
/* ======================================================
   FOOTER PILLS
   ====================================================== */
/* Intro pills — fixed overlay on the hero screen */
#intro-pills {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 500;
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.6s ease;
}
#intro-pills.is-visible { opacity: 1; }
#intro-pills .footer-pill,
#footer-pills .footer-pill,
#canvas-footer-pills .footer-pill { pointer-events: auto; }

/* Sticky-note + pen tools active: disable pill interactions so the user can
   work over the hero header without dismissing pills. The body-level click
   handler creates the note (sticky) or the canvas catches the stroke (pen);
   pills become a non-interactive backdrop. */
body[data-tool="sticky"] #intro-pills,
body[data-tool="sticky"] #intro-pills .footer-pill,
body[data-tool="sticky"] #footer-pills .footer-pill,
body[data-tool="sticky"] #canvas-footer-pills .footer-pill,
body[data-tool="pen"] #intro-pills,
body[data-tool="pen"] #intro-pills .footer-pill,
body[data-tool="pen"] #footer-pills .footer-pill,
body[data-tool="pen"] #canvas-footer-pills .footer-pill { pointer-events: none; }

/* Footer pills — absolute inside .site-footer so they scroll with the page.
   Since .site-footer is 100svh tall the coordinate space is identical to fixed. */
#footer-pills {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 10;
  /* Clip so the off-screen "waiting to drop" pills (parked at negative
     top values) don't leak into the previous section on phones where
     the body doesn't clip them automatically. */
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.6s ease;
}
/* Once pills have spawned, stays visible regardless of scroll position */
#footer-pills.is-visible,
#footer-pills.has-spawned { opacity: 1; }

/* Canvas footer pills — fixed overlay used only when the canvas panel is open */
#canvas-footer-pills {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9200;
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.6s ease;
}
#canvas-footer-pills.is-visible { opacity: 1; }

.footer-pill {
  position: absolute;
  height: clamp(30px, 3vw, 48px);
  padding: 0 clamp(11px, 1.2vw, 20px);
  border-radius: clamp(15px, 1.5vw, 24px);
  display: inline-flex;
  align-items: center;
  font-family: 'Inter', -apple-system, sans-serif;
  font-size: clamp(0.7rem, 1.05vw, 1rem);
  font-weight: 500;
  white-space: nowrap;
  letter-spacing: -0.01em;
  will-change: top, transform;
}

@keyframes pill-squish {
  0%   { transform: var(--pill-rot) scaleX(1)    scaleY(1);    }
  35%  { transform: var(--pill-rot) scaleX(1.12) scaleY(0.78); }
  65%  { transform: var(--pill-rot) scaleX(0.96) scaleY(1.08); }
  100% { transform: var(--pill-rot) scaleX(1)    scaleY(1);    }
}
.footer-pill.squish { animation: pill-squish 0.28s ease forwards; }

/* --- source lines 5194-5508 --- */
/* ======================================================
   INTRO STAGE — "Build anything." full-screen opener
   ====================================================== */
.intro-stage {
  position: relative;
  height: 100vh;
  display: flex;
  /* Column + left-align so the headline and chips stack vertically and
     both hug the left edge of the viewport (28 px gutter, matching the
     .pb-section / logo inset). The flex container still vertically
     centres the lockup as a whole. */
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  overflow: hidden;
  background-color: var(--bg);
  background-image: radial-gradient(circle, rgba(0,0,0,0.18) 1px, transparent 1px);
  background-size: 28px 28px;
}

.intro-canvas {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* opacity toggled by JS */
}

.intro-giant {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(3rem, 13.5vw, 18rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  color: var(--text);
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  user-select: none;
  cursor: default;
  /* Hidden until JS splits the text into chars — prevents the plain
     "Build anything." flash before the per-letter animation kicks in. */
  visibility: hidden;
  /* opacity toggled by JS — hidden when canvas is active */
}
.intro-giant.is-split {
  visibility: visible;
}

/* Supporting kicker line under the H1 — regular Helvetica 16 px.
   Left-aligns to the H1's 10vw column (mobile keeps 16 px gutter). */
.intro-supporting {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 16px;
  font-weight: 400;
  letter-spacing: -0.005em;
  line-height: 1.45;
  color: var(--text-2, rgba(0,0,0,0.65));
  margin: 18px 28px 0 10vw;
  /* Cap at 50% viewport so the sub-line never reaches further
     than the H1 column above it (60vw cap) — keeps the lockup
     visually balanced on every page (homepage + campaign). */
  max-width: min(50vw, calc(90vw - 28px));
}
@media (max-width: 699px) {
  .intro-supporting {
    /* Lifted from 14 px to 20 px (≥ 16 px floor) so the sub-line
       reads at body-copy size on phones. Width pulled out to 79 vw
       so it doesn't get cramped under the bigger H1 above. */
    font-size: 18px;
    margin: 10px 16px 0;
    max-width: 79vw;
  }
}

/* Mobile — pull "Build anything." 10% higher in the intro stage */
@media (max-width: 699px) {
  .intro-stage { align-items: flex-start; padding-top: 40vh; }
}
/* Only during the sun (radial) phase: lift the headline so right-side rays
   render behind it. Left-side rays escape via #intro-pills-front (z-index 800). */
body.is-sun-phase .intro-giant {
  position: relative;
  z-index: 700;
}

/* ── Intro quote — flashes on "Play again" before re-animation ── */
.intro-quote {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 8%;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(1.1rem, 2.8vw, 3rem);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1.35;
  color: var(--text);
  pointer-events: none;
  opacity: 0;
  z-index: 3;
  transition: opacity 0.5s ease;
}
.intro-quote.is-visible { opacity: 1; }
.intro-quote em { font-style: italic; }
.intro-quote__attr {
  display: block;
  margin-top: 0.6em;
  font-size: 0.65em;
  color: var(--text-2);
  letter-spacing: 0;
}

/* ── Intro stopwatch — fixed to viewport so intro-stage overflow:hidden can't clip the bounce ── */
.intro-stopwatch {
  position: fixed;
  /* Centre horizontally, sit just above "Build anything." (at ~50vh) */
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Anchor the bottom of the assembly to just above the text */
  justify-content: flex-end;
  /* Push bottom of assembly (= bottom of circle) just above "Build anything." at 50vh */
  padding-bottom: calc(50vh + clamp(1.5rem, 6.75vw, 9rem) + 1rem);
  pointer-events: none;
  z-index: 5;
  /* hidden until game starts — controlled by is-active class */
  visibility: hidden;
}
.intro-stopwatch.is-active {
  visibility: visible;
}

/* The physical assembly that GSAP animates */
.sw-assembly {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex-shrink: 0;
  position: relative;
  overflow: visible;
}

/* Two button shapes either side of circle top — positioned inside .sw-circle */
.sw-crowns {
  position: absolute;
  top: -10px;
  left: 50%;
  transform: translateX(-50%);
  width: 130px;
  display: flex;
  justify-content: space-between;
  pointer-events: none;
}
.sw-crown {
  width: 28px;
  height: 16px;
  border: 1.5px solid var(--text);
  border-radius: 6px;
  background: var(--bg);
  opacity: 0.7;
}
.sw-crown:first-child { transform: rotate(-38deg); }
.sw-crown:last-child  { transform: rotate(38deg); }

/* Curvy strings SVG — absolute, anchored to circle bottom, paths go upward off-screen */
.sw-strings {
  position: absolute;
  /* bottom of SVG aligns with bottom of circle (180px tall) */
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 200px;
  height: 180px;
  overflow: visible;
  pointer-events: none;
  opacity: 0.28;
  color: var(--text);
  z-index: -1; /* sit behind the circle */
}

/* Circle wrapping the pill */
.sw-circle {
  position: relative;
  width: 180px;
  height: 180px;
  border: 1.5px solid var(--text);
  border-radius: 50%;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: visible;
}

/* Pill containing the clock */
.sw-pill {
  border: 1.5px solid var(--text);
  border-radius: 100px;
  padding: 0.4em 1em;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Time display inside the pill */
.intro-stopwatch__time {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(1.1rem, 2.8vw, 2.2rem);
  font-weight: 400;
  letter-spacing: -0.05em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  line-height: 1;
}


/* Wrapper that stacks the playing/stopped messages in the same layout slot
   so toggling between them never causes a layout shift. */
.sw-messages {
  display: grid;
  grid-template-columns: 1fr;
  margin-top: 1rem;
  width: 90vw;
  max-width: 680px;
  flex-shrink: 0;
}
.sw-messages > * {
  grid-column: 1;
  grid-row: 1;
}

/* Result label shown after game ends */
.intro-stopwatch__label {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(1rem, 1.6vw, 1.25rem);
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--text-2);
  line-height: 1.5;
  text-align: center;
  text-wrap: balance;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.6s ease 0.7s, transform 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.7s;
}
.intro-stopwatch.is-stopped .intro-stopwatch__label {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.intro-stopwatch__replay {
  color: var(--text);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  pointer-events: auto;
}
.sw-record {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(1rem, 1.6vw, 1.25rem);
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--text-2);
  line-height: 1.5;
  opacity: 0;
  text-align: center;
  transition: opacity 0.5s ease 0.2s;
}
.intro-stopwatch.is-active .sw-record { opacity: 1; }
/* On stop, the record line shares its grid cell with the result comment
   (which is now showing). Hide it cleanly so the two don't overlap; the
   user's final time gets appended to the comment text instead. */
.intro-stopwatch.is-stopped .sw-record { opacity: 0; pointer-events: none; }
.sw-record__user { display: none; }

@media (max-width: 768px) {
  .sw-record__line { display: block; }
}

/* Letter-by-letter entrance animation */
.intro-char {
  display: inline-block;
  opacity: 0;
  transform: translateX(-70px);
  transition: opacity 0.55s cubic-bezier(0.34, 1.56, 0.64, 1),
              transform 0.55s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.intro-char.is-in {
  opacity: 1;
  transform: translateX(0);
}
.intro-char--space {
  display: inline;
}
/* Word-level wrapper emitted by the canvas-animation IIFE around
   every run of non-space chars. Stays inline (no display change)
   so the canvas's measurement of the H1 bounding rect is
   unaffected; white-space: nowrap blocks the browser from
   line-breaking between the per-char inline-block spans inside a
   single word — fixes the "businesse / s" wrap that happened on
   mobile at the larger font. Wraps still work at spaces and `|`
   markers because those emit OUTSIDE the wrapper. */
.intro-word {
  white-space: nowrap;
}

/* --- source lines 5509-5696 --- */
/* ======================================================
   SITE FOOTER
   ====================================================== */
.site-footer {
  position: relative;  /* anchor for #footer-pills absolute positioning */
  color: var(--text);
  min-height: 100svh;
  height: 100svh;
  display: flex;
  flex-direction: column;
  padding: 48px 28px;
  overflow: visible;  /* allows scatter chars to fly freely */
}

.footer-inner {
  flex: 1;
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
  overflow: visible;
}

/* Contact form embedded in the footer — sits under "Let's build",
   centred horizontally, and on a z-index above the absolute-
   positioned .footer-pills layer. */
.footer-contact {
  position: relative;
  /* Sits on top of the bouncing pill layer (#footer-pills, z:10
     before our override below). */
  z-index: 50;
  width: 100%;
  display: flex;
  justify-content: center;
  /* Sits a comfortable distance below the "Let's build" wordmark —
     no flex auto-margin (it was creating a huge wordmark→form gap). */
  margin-top: 36px;
}
.footer-contact .contact-card {
  width: 100%;
  max-width: 560px;
  background: #fff;
  border-radius: var(--r-card);
  padding: 28px;
  box-sizing: border-box;
}
/* Pills sit BELOW the contact card so the form is readable on top. */
#footer-pills { z-index: 1 !important; }

/* Canvas — inserted by JS, absolute so it doesn't affect flex layout */
.footer-scatter-canvas {
  display: block;
  position: absolute;
  pointer-events: none;
}

.footer-giant {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: center;
  gap: 0 0.22em;
  line-height: 1;
  margin: 0 -28px;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 10.5vw;
  font-weight: 400;
  cursor: default;
  user-select: none;
  letter-spacing: -0.03em;
  color: var(--text);
  white-space: nowrap;
  /* JS controls opacity for assembled swap */
}

.footer-word-wrap {
  display: inline-block;
  overflow: hidden;
  line-height: 1.1;
}

.footer-word {
  display: inline-block;
  transform: translateY(110%);
  transition: transform 0.85s cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
}

.footer-word-wrap:nth-child(1) .footer-word { transition-delay: 0s; }
.footer-word-wrap:nth-child(2) .footer-word { transition-delay: 0.12s; }
.footer-word-wrap:nth-child(3) .footer-word { transition-delay: 0.24s; }

.site-footer.is-visible .footer-word { transform: translateY(0); }

.footer-bottom {
  position: absolute;
  top: 100px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: nowrap;
  white-space: nowrap;
}

.footer-nav { display: flex; gap: 24px; flex-wrap: nowrap; flex-direction: row; align-items: center; }

.footer-link {
  font-family: 'Inter', sans-serif;
  font-size: 0.85rem;
  color: var(--text-2);
  text-decoration: none;
  letter-spacing: 0.01em;
  opacity: 0;
  transform: translateY(-14px);
  transition: color 0.2s ease, opacity 0.4s ease, transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.footer-link:hover { color: var(--text); }

.site-footer.is-visible .footer-link { opacity: 1; transform: translateY(0); }
.site-footer.is-visible .footer-nav .footer-link:nth-child(1) { transition-delay: 0s; }
.site-footer.is-visible .footer-nav .footer-link:nth-child(2) { transition-delay: 0.07s; }
.site-footer.is-visible .footer-nav .footer-link:nth-child(3) { transition-delay: 0.14s; }
.site-footer.is-visible .footer-nav .footer-link:nth-child(4) { transition-delay: 0.21s; }
.site-footer.is-visible .footer-nav .footer-link:nth-child(5) { transition-delay: 0.28s; }
.site-footer.is-visible .footer-nav .footer-link:nth-child(6) { transition-delay: 0.35s; }
.site-footer.is-visible .footer-nav .footer-link:nth-child(7) { transition-delay: 0.42s; }
.site-footer.is-visible .footer-nav .footer-link:nth-child(8) { transition-delay: 0.49s; }
.site-footer.is-visible .footer-nav .footer-link:nth-child(9) { transition-delay: 0.56s; }

.footer-legal {
  position: fixed;
  bottom: 28px;
  left: 28px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  color: var(--text-3);
  line-height: 1;
  white-space: nowrap;
  z-index: 200;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s ease;
}
.footer-legal--visible {
  opacity: 1;
}
.footer-legal a,
.footer-legal__link {
  color: inherit;
  text-decoration: none;
  pointer-events: auto;
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.footer-legal a:hover,
.footer-legal__link:hover {
  color: var(--text);
  border-bottom-color: currentColor;
}

@media (max-width: 699px) {
  .site-footer { padding: 40px 20px; }
  /* Keep "Let's build" on ONE line on mobile — was column-
     stacking it. Font sized to fit both words side-by-side inside
     the 16 px gutter. */
  .footer-giant {
    flex-direction: row !important;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
    margin-left: -20px;
    margin-right: -20px;
    font-size: 14vw;
  }
  .footer-nav { display: none; }
  .footer-legal { display: none; }
  .footer-bottom { flex-direction: column; gap: 24px; align-items: center; }
}

@media (min-width: 900px) {
  .site-footer { padding: 48px 17.5vw; }
  .footer-giant { margin-left: -17.5vw; margin-right: -17.5vw; } /* escape side padding → full viewport width */
}

/* ========================================================================
   LAYER 10 · SCROLLBAR
   ======================================================================== */

/* --- source lines 5697-5703 --- */
/* ======================================================
   SCROLLBAR
   ====================================================== */
::-webkit-scrollbar { width: 5px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--surface); border-radius: 3px; }

/* ========================================================================
   LAYER 11 · TRANSFORM TOOL — frame resize handle + responsive column modes
   ======================================================================== */

/* --- source lines 5704-5814 --- */
/* ======================================================
   TRANSFORM TOOL — RESIZE HANDLE & GRID MODE
   ====================================================== */

/* The right-edge drag handle */
.frame-resize-handle {
  position: absolute;
  right: -17px;
  top: 50%;
  transform: translateY(-50%);
  width: 12px;
  height: 52px;
  background: #1A1A18;
  border-radius: 6px;
  cursor: ew-resize;
  opacity: 0;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  transition: opacity 0.25s var(--ease-out);
  z-index: 20;
}

/* Grip dots */
.frame-resize-handle span {
  display: block;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: rgba(255,255,255,0.5);
  flex-shrink: 0;
}

/* Col count label below the handle */
.frame-resize-handle::after {
  content: attr(data-cols) ' col';
  position: absolute;
  top: calc(100% + 7px);
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  font-family: 'Inter', -apple-system, sans-serif;
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--text-3);
  pointer-events: none;
}

/* Expanded pointer / cursor target around the handle (invisible padding) */
.frame-resize-handle::before {
  content: '';
  position: absolute;
  inset: -14px -16px;
  cursor: ew-resize;
}

/* Show handle only in transform mode */
body[data-tool="transform"] .frame-resize-handle {
  opacity: 1;
  pointer-events: all;
  cursor: ew-resize;
}

/* Frame gets a blue tint border in transform mode */
body[data-tool="transform"] .cards-frame {
  border-color: rgba(43, 111, 212, 0.35);
}

/* Highlight corner handles blue in transform mode */
body[data-tool="transform"] .cards-frame > .handle {
  background: #2B6FD4;
  opacity: 1 !important;
}

/* Grid mode: flex-wrap so cards flow at natural width */
.cards-frame.grid-mode .cards-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ccux-gap, 10px);
  align-content: flex-start;
}

/* Cards hold their natural measured width — set via JS as --ccux-card-w */
.cards-frame.grid-mode .card {
  flex: 0 0 var(--ccux-card-w, auto);
}

/* Flatten card rotations in grid mode */
.cards-frame.grid-mode .card:nth-child(1),
.cards-frame.grid-mode .card:nth-child(2),
.cards-frame.grid-mode .card:nth-child(3),
.cards-frame.grid-mode .card:nth-child(4) {
  transform: none !important;
  animation: none !important;
}

/* Restore hover in grid mode — must come AFTER nth-child rules */
.cards-frame.grid-mode .card:hover {
  transform: translateY(-6px) scale(1.02) !important;
  z-index: 5;
}

.cards-frame.grid-mode .card.active {
  transform: translateY(-4px) !important;
  z-index: 4;
}

/* --- source lines 5815-5889 --- */
/* ======================================================
   RESPONSIVE — auto 2-col / 1-col on narrow viewports
   Driven by body[data-responsive-cols] set via JS on resize
   ====================================================== */

/* Allow frame to fill available width (overrides JS maxWidth if transform active) */
body[data-responsive-cols] .cards-frame {
  max-width: 100%;
}

/* Enable wrapping */
body[data-responsive-cols] .cards-row {
  flex-wrap: wrap;
}

/* Flatten rotations — same treatment as grid-mode */
body[data-responsive-cols] .cards-row .card:nth-child(1),
body[data-responsive-cols] .cards-row .card:nth-child(2),
body[data-responsive-cols] .cards-row .card:nth-child(3),
body[data-responsive-cols] .cards-row .card:nth-child(4) {
  transform: none !important;
  animation: none !important;
}

/* Restore hover lift */
body[data-responsive-cols] .cards-row .card:hover {
  transform: translateY(-6px) scale(1.02) !important;
}

/* 2-col: each card fills half the row minus the gap */
body[data-responsive-cols="2"] .cards-row .card {
  flex: 1 1 calc(50% - 5px);
  max-width: calc(50% - 5px);
}

/* 1-col: single full-width card */
body[data-responsive-cols="1"] .cards-row .card {
  flex: 1 1 100%;
  max-width: 100%;
}

/* Mobile 2×2 grid */
@media (max-width: 600px) {
  .cards-frame {
    padding: 12px 10px 10px;
  }
  .cards-row {
    flex-wrap: wrap;
    gap: 8px;
  }
  .cards-row .card {
    flex: 1 1 calc(50% - 4px) !important;
    max-width: calc(50% - 4px) !important;
    min-width: 0 !important;
  }
  /* Larger media tile — less margin, keep landscape ratio */
  .cards-row .card .card-inner {
    margin: 10px 10px 6px;
    aspect-ratio: 4/3;
  }
  /* Label smaller to save space */
  .cards-row .card .card-label {
    font-size: min(11cqi, 1.8rem);
    padding: 4px 10px 12px 10px;
  }
  /* Flatten rotations on mobile */
  .cards-row .card:nth-child(1),
  .cards-row .card:nth-child(2),
  .cards-row .card:nth-child(3),
  .cards-row .card:nth-child(4) {
    transform: none !important;
    animation: none !important;
  }
}

/* ========================================================================
   LAYER 12 · CANVAS OVERLAY — full-screen spatial view opened from a discipline card
   ======================================================================== */

/* --- source lines 5890-5977 --- */
/* ======================================================
   CANVAS VIEW (card-click full-screen, free-form spatial)
   ====================================================== */

/* Hero text exits left when canvas opens */
.hero-text {
  transition: transform 0.45s var(--ease-out), opacity 0.4s var(--ease-out);
}

body[data-card] .hero-text {
  transform: translateX(-52px);
  opacity: 0;
  pointer-events: none;
}

/* When a canvas (apps / websites / brand) is open, the home hero
   elements — giant H1 intro text, discipline pills, and the
   process/discipline picker — must NOT appear behind / over the
   canvas content. */
body[data-card] .intro-stage,
body[data-card] .intro-giant,
body[data-card] .intro-chips,
body[data-card] .process-hed-row,
body[data-card] .process-chips,
body[data-card] #process-panel {
  display: none !important;
}

/* Cards frame: disable pointer events when canvas is open */
.cards-frame {
  transition: border-color 0.25s var(--ease-out),
              transform 0.5s var(--ease-out),
              opacity 0.45s var(--ease-out);
}

body[data-card] .cards-frame {
  width: max-content;
  z-index: 100;        /* below canvas overlay (z:150) — hidden behind it */
  pointer-events: none;
  opacity: 0;
}

/* Mini thumbnail strip — text only (hide Lottie image area) */
body[data-card] .cards-frame .card .card-inner {
  display: none;
}

/* Push label text toward the top; double the font so it reads at mini scale */
body[data-card] .cards-frame .card .card-label {
  padding: 18px 16px 14px;
  font-size: clamp(3.0rem, 4.2vw, 4.0rem);
}

/* Smooth spring transition for individual cards (fan + hover scale via JS) */
body[data-card] .cards-frame .card {
  width: 380px;
  min-width: 380px;
  flex-shrink: 0;
  padding-bottom: 150px;
  animation: none;
  transition: transform 0.38s var(--ease-spring);
}

/* Suppress box-shadow on fanned cards — JS controls transform entirely */
body[data-card] .cards-frame .card:hover {
  box-shadow: none;

}

/* Hide the currently-open card from the mini thumbnail strip */
body[data-card="apps"]     .cards-frame .card--apps,
body[data-card="websites"] .cards-frame .card--websites,
body[data-card="brand"]    .cards-frame .card--brand,
body[data-card="ai"]       .cards-frame .card--ai {
  display: none;
}

/* Back button: hidden on home, visible when canvas is open */
.nav-back { display: none; }
body[data-card] .nav-back { display: flex; }

/* Transform button: hidden everywhere (removed from the canvas toolbar). */
.nav-transform { display: none !important; }
@media (max-width: 699px) {
  /* Sticky-note tool removed on mobile — too fiddly for touch. */
  .bottom-nav .nav-icon[data-tool="sticky"] { display: none; }
}

/* --- source lines 5978-6034 --- */
/* ===== Canvas overlay ===== */
@keyframes canvas-expand {
  from {
    clip-path: inset(15% round 20px);
    opacity: 0.4;
  }
  to {
    clip-path: inset(0% round 0px);
    opacity: 1;
  }
}

.canvas-overlay {
  position: fixed;
  inset: 0;
  z-index: 150;
  /* Per-card colour set below; dot grid via background-image */
  background-color: var(--bg);
  /* Layer 1: very faint dot grid — matches home page pattern */
  background-image: radial-gradient(circle, rgba(0,0,0,0.18) 1px, transparent 1px);
  background-size: 28px 28px;
  overflow: auto;
  opacity: 0;
  pointer-events: none;
}

body[data-card] .canvas-overlay {
  opacity: 1;
  pointer-events: all;
  overscroll-behavior: contain; /* stops scroll bleeding through to page body */
}

.canvas-overlay.is-entering {
  animation: canvas-expand 0.52s cubic-bezier(0.16, 1, 0.3, 1) both;
}

/* Full-page cover for cross-page navigation (Experience card) */
.canvas-nav-cover {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background-color: var(--bg);
  clip-path: inset(15% round 20px);
  opacity: 0.4;
  pointer-events: none;
  transition: clip-path 0.52s cubic-bezier(0.16, 1, 0.3, 1),
              opacity   0.52s cubic-bezier(0.16, 1, 0.3, 1);
}

.canvas-nav-cover.is-active {
  clip-path: inset(0% round 0px);
  opacity: 1;
  pointer-events: all;
}

/* Per-card background tint removed — all pages match home screen background */

/* --- source lines 6035-6072 --- */
/* ===== Close button — fixed top-right, OUTSIDE overlay element ===== */
.canvas-back {
  position: fixed;
  top: 24px;
  right: 28px;
  z-index: 160;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1.5px solid rgba(0,0,0,0.15);
  background: rgba(255,255,255,0.75);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  cursor: pointer;
  color: var(--text);
  opacity: 0;
  pointer-events: none;
  transition: background 0.2s, border-color 0.2s,
              transform 0.3s var(--ease-out), opacity 0.3s var(--ease-out);
}

body[data-card] .canvas-back {
  opacity: 1;
  pointer-events: all;
}

.canvas-back:hover {
  background: rgba(255,255,255,0.95);
  border-color: rgba(0,0,0,0.25);
  transform: rotate(90deg);
}
body[data-view="deck"] .canvas-back:hover {
  transform: translateY(-3px);
}

/* --- source lines 6073-6095 --- */
/* ===== Spatial canvas container =====
   --ca-anchor lets each tile express its position relative to canvas-space's
   centre instead of its top-left corner — so the cluster stays centred as
   the canvas resizes. (We deliberately avoid container-type here because it
   would create a containing block for fixed descendants like .canvas-cluster
   and break their viewport-fixed positioning.) */
.canvas-space {
  position: relative;
  min-height: max(100vh, 900px);
  min-width: max(110vw, 1200px);
  padding: 0 40px 80px;
  margin-top: 5vh;
  --ca-anchor: calc(50% - 960px); /* 960 = half the design reference width */
}
/* Per-canvas min-height so absolute .ca tiles placed deep in the layout
   actually push the canvas-page-intro section below them instead of being
   covered by it (absolute children don't grow their parent's height by
   default). Bump these whenever a tile's `top` value approaches the limit. */
body[data-card="apps"]     .canvas-space { min-height: 3850px; }
body[data-card="websites"] .canvas-space { min-height: 2000px; }
body[data-card="brand"]    .canvas-space { min-height: 2200px; }

/* --- source lines 6096-6116 --- */
/* ===== Identity chip — top-left — hidden ===== */
.canvas-identity {
  display: none;
}

.canvas-chip {
  display: inline-flex;
  align-items: center;
  padding: 5px 16px;
  border-radius: 100px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.95rem;
  font-weight: 400;
  letter-spacing: 0.01em;
}

body[data-card="apps"]     .canvas-chip { background: var(--apps-in);  color: #ffffff; }
body[data-card="websites"] .canvas-chip { background: var(--web-in);   color: #0d0d0d; }
body[data-card="brand"]    .canvas-chip { background: var(--brand-in); color: #0d0d0d; }
body[data-card="ai"]       .canvas-chip { background: var(--ai-in);    color: #ffffff; }

/* --- source lines 6117-6134 --- */
/* ===== pretext flowing text — Layer 1 (below .ca thumbs) ===== */
/* Rendered by renderCanvasTextFlow() using @chenglou/pretext.
   Lines are absolutely-positioned <div>s inside canvas-space.
   opacity transitions in when a canvas opens. */
.canvas-text-flow {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  user-select: none;
  z-index: 100;        /* must exceed canvas-page-intro sticky stacking */
  opacity: 0;
  transition: opacity 0.5s var(--ease-out) 0.2s;
}
body[data-card] .canvas-text-flow {
  opacity: 1;
}

/* --- source lines 6135-6263 --- */
/* ===== Floating decorative artefacts — Layer 2 ===== */
.ca {
  position: absolute;
  border-radius: 14px;
  overflow: hidden; /* clips image to container — enables corner-crop sizing */
  pointer-events: all;
  cursor: grab;
  z-index: 12; /* above canvas-page-intro (z-index: 10) so thumbs aren't clipped by its background */
  user-select: none;
}
.ca:active { cursor: grabbing; }

.ca img,
.ca video {
  width: 375px;  /* fixed full-phone width — container crops it */
  height: auto;
  display: block;
  pointer-events: none;
  -webkit-user-drag: none;
  user-select: none;
}

/* ── Hover badge — title + arrow in a single pill at top-right of the
   tile, matching the homepage zoom-canvas (.wz-tile) style. The badge
   uses the parent .ca's data-title attribute for the label. The legacy
   .ca-hint and .ca-title elements are hidden so they don't compete. ── */
.ca-hint,
.ca-title { display: none !important; }

.ca::after {
  content: attr(data-title);
  position: absolute;
  top: 8px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 32px 0 12px;
  background: #fff
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M7 17L17 7'/><path d='M7 7h10v10'/></svg>")
    no-repeat right 10px center;
  border-radius: 100px;
  font-family: 'Inter', -apple-system, sans-serif;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: #111;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(-4px);
  transform-origin: top right;
  transition: opacity 0.2s var(--ease-out), transform 0.2s var(--ease-out);
  pointer-events: none;
  box-shadow: 0 2px 10px rgba(0,0,0,0.16);
  z-index: 5;
}
.ca:hover::after {
  opacity: 1;
  transform: translateY(0);
}

/* Only show artefacts for the active canvas */
.ca--apps, .ca--websites, .ca--brand { display: none; }
body[data-card="apps"]     .ca--apps     { display: block; }
body[data-card="websites"] .ca--websites { display: block; }
body[data-card="brand"]    .ca--brand    { display: block; }

/* All canvas artefacts — 375px base width (some are cropped narrower below) */
.ca-1,.ca-2,.ca-3,.ca-4,.ca-5,.ca-6,.ca-7,.ca-8,.ca-9,.ca-10,.ca-16,
.ca-11,.ca-12,.ca-13,.ca-14,.ca-15,.ca-17,
.ca-21,.ca-22,.ca-23,.ca-24,.ca-25 { width: 375px; }

/* ── Corner-crop size variation (0–40% narrower than 375px) ──────────────
   Image is fixed at 375px inside — container masks from one side.
   Default: shows left portion of image (right side cropped off).
   "img { margin-left:auto }" flips to show right portion (left side cropped).  */

/* Apps */
.ca-2  { width: 280px; }   /* 75% — crop from right */
.ca-3  { width: 310px; }   /* 83% — crop from right */
.ca-4  { width: 345px; }   /* 92% — subtle crop */
.ca-5  { width: 230px; }   /* 61% — crop from left (shows right side of screen) */
.ca-6  { width: 295px; }   /* 79% — crop from right */
.ca-7  { width: 260px; }   /* 69% — crop from left (shows right side of screen) */

/* Websites */
.ca-12 { width: 285px; }   /* 76% — crop from left (shows right side) */
.ca-13 { width: 320px; }   /* 85% — crop from right */

/* Brand */
.ca-21 { width: 320px; }   /* 85% — crop from right */
.ca-23 { width: 250px; }   /* 67% — crop from left (shows right side) */

/* Right-aligned images — shows right portion of the phone screen */
.ca-5 img, .ca-7 img, .ca-12 img, .ca-23 img { margin-left: auto; }

/* ── Canvas thumbnail positions — desktop layout (baked from user drag session) ── */

/* ── Apps canvas — left uses calc(var(--ca-anchor) + Xpx) so the cluster
      stays centred as the canvas-space width changes. ── */
.ca-1  { left: calc(var(--ca-anchor) + 1194px); top: 13px;   width: 240px; }  /* Tab App */
.ca-1 video { width: 240px; height: 336px; object-fit: cover; }
.ca-2  { left: calc(var(--ca-anchor) + 267px);  top: 563px;  }  /* Unscripted — left 5% */
.ca-3  { left: calc(var(--ca-anchor) + 241px);  top: 1404px; }  /* Daikin — 50vh below Properti */
.ca-4  { left: calc(var(--ca-anchor) + 1419px); top: 439px;  }  /* Corin — left 10%       */
.ca-5  { left: calc(var(--ca-anchor) + 241px);  top: 954px;  }  /* Properti — left 10%  */
.ca-6  { left: calc(var(--ca-anchor) + 483px);  top: 51px;   }  /* RFS                  */
.ca-7  { left: calc(var(--ca-anchor) + 32px);   top: 3103px; }  /* Woolworths — left 24% */
.ca-8  { left: calc(var(--ca-anchor) + 51px);   top: 2053px; }  /* Hummingbot — left 10% more */
.ca-9  { left: calc(var(--ca-anchor) + 1400px); top: 1230px; }  /* Auspost    */
.ca-10 { left: calc(var(--ca-anchor) + 1562px); top: 1830px; width: 300px; } /* CBRE */
.ca-16 { left: calc(var(--ca-anchor) + 1500px); top: 2490px; }  /* Wilsons    */

/* ── Websites canvas ── */
.ca-11 { left: calc(var(--ca-anchor) + 1420px); top: 218px;  width: 226px; height: 140px; } /* Uncle Tobys — cropped to landscape rectangle */
.ca-11 video { width: 226px; height: 140px; object-fit: cover; }
.ca-12 { left: calc(var(--ca-anchor) + 1347px); top: 723px;  }  /* Jimmy Cricket — right 10% more */
.ca-13 { left: calc(var(--ca-anchor) + 249px);  top: 270px;  }  /* Zhik */
.ca-14 { left: calc(var(--ca-anchor) + 137px);  top: 1093px; }  /* Magic Bra — left 8% */
.ca-15 { left: calc(var(--ca-anchor) + 1536px); top: 1280px; }  /* CoreLogic — swapped with Ezidebit */
.ca-17 { left: calc(var(--ca-anchor) + 718px);  top: 22px;   }  /* Ezidebit — swapped with CoreLogic */

/* ── Brand canvas ── */
.ca-21 { left: calc(var(--ca-anchor) + 660px);  top: 0px;    }  /* Johnson Brand — up 15% (clamped to 0) */
.ca-22 { left: calc(var(--ca-anchor) + 1375px); top: 465px;  }  /* Supapix — down 5%                     */
.ca-23 { left: calc(var(--ca-anchor) + 255px);  top: 760px;  }  /* Kenko                                 */
.ca-24 { left: calc(var(--ca-anchor) + 1375px); top: 1080px; }  /* Sony Music — left 15%                 */
.ca-25 { left: calc(var(--ca-anchor) + 30px);   top: 1455px; }  /* 3 Bees Honey             */

/* --- source lines 6264-6286 --- */
/* ===== View toggle buttons ===== */
.canvas-view-toggle {
  display: none;
  gap: 6px;
  align-items: center;
}
body[data-card] .canvas-view-toggle { display: flex; }

.view-btn {
  width: 34px; height: 34px;
  border-radius: 10px;
  border: 1.5px solid rgba(0,0,0,0.12);
  background: rgba(255,255,255,0.5);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; color: rgba(0,0,0,0.4);
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.view-btn.active { background: rgba(255,255,255,0.9); color: rgba(0,0,0,0.75); border-color: rgba(0,0,0,0.35); border-width: 2px; }
body[data-card="apps"]     .view-btn.active { background: rgba(255,255,255,0.9); color: var(--apps-in);  border-color: var(--apps-in);  border-width: 2px; }
body[data-card="websites"] .view-btn.active { background: rgba(255,255,255,0.9); color: var(--web-in);   border-color: var(--web-in);   border-width: 2px; }
body[data-card="brand"]    .view-btn.active { background: rgba(255,255,255,0.9); color: #0d0d0d;         border-color: rgba(0,0,0,0.35); border-width: 2px; }
body[data-card="ai"]       .view-btn.active { background: rgba(255,255,255,0.9); color: var(--ai-in);    border-color: var(--ai-in);    border-width: 2px; }

/* --- source lines 6287-6307 --- */
/* ===== Deck view container — absolute inside canvas-space, scrolls with content ===== */
.canvas-deck {
  position: absolute;
  /* top set dynamically by JS (cluster bottom + gap in canvas coords) */
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  perspective: 420px;
  perspective-origin: 50% -20%;
  display: none;
  width: 520px;
  height: 360px;
}
body[data-view="deck"] .canvas-deck { display: block; }
/* Hide scatter artefacts in deck mode */
body[data-view="deck"] .ca--apps,
body[data-view="deck"] .ca--websites,
body[data-view="deck"] .ca--brand { display: none !important; }
/* Clamp canvas-space so extra absolute content can't extend the scroll area */
body[data-view="deck"] .canvas-space { overflow: hidden; }

/* --- source lines 6310-6451 --- */
/* ===== Canvas page intro — apps text + accordion ===== */
/* Breaks out of the wide canvas-space just like canvas-bottom */
.canvas-page-intro {
  position: sticky;
  left: 0;
  z-index: 10;
  width: 100vw;
  display: flex;
  flex-direction: column;
  align-items: center;
  background: var(--bg);
  background-image: radial-gradient(circle, rgba(0,0,0,0.18) 1px, transparent 1px);
  background-size: 28px 28px;
  padding: 60px 0 60px;
  /* Default — overridden per canvas below so the FAQ/contact/footer
     section starts ~120px below the visible top section (cluster +
     first about-block at top:50vh of canvas-space). */
  margin-top: 0;
}
/* Pull canvas-page-intro up so it sits 120px below the about-block
   instead of starting at canvas-space's bottom edge.
   Math: target_top = canvas-space.top (5vh) + 50vh (cluster) + 230px
                       + ~200px (about-block height) + 120px (gap)
                     = 55vh + 550px
   margin-top = target_top − (canvas-space.top + canvas-space.min-height)
              = (55vh + 550) − (5vh + min-height)
              = 50vh + 550 − min-height                                   */
body[data-card="apps"]     .canvas-page-intro { margin-top: calc(50vh + 550px - 3850px); } /* min-height 3850 */
body[data-card="websites"] .canvas-page-intro { margin-top: calc(50vh + 550px - 2000px); } /* min-height 2000 */
body[data-card="brand"]    .canvas-page-intro { margin-top: calc(50vh + 550px - 2200px); } /* min-height 2200 */
/* First about-block: position absolutely inside canvas-space so it sits
   ~150px below the cluster, in the same scroll context — both scroll with
   the page. The actual element lives in canvas-page-intro for SEO/HTML
   flow; openCanvas() relocates it into canvas-space when the canvas opens
   and restores it on close. */
.about-block--canvas-anchor {
  position: absolute !important;
  top: calc(50vh + 230px) !important; /* cluster at 50vh — clear it + 150px gap */
  left: 50% !important;
  right: auto !important;
  transform: translateX(-50%);
  margin: 0 !important;
  padding: 0 !important;
  z-index: 11;
  width: min(640px, 90vw);
  max-width: none;
  box-sizing: border-box;
  text-align: left; /* keep body copy left-aligned, not centred */
}
.about-block--canvas-anchor > .about-body { text-align: left; }

/* Hidden unless the matching canvas is open */
.canvas-page-intro--apps     { display: none; }
.canvas-page-intro--websites { display: none; }
.canvas-page-intro--brand    { display: none; }

body[data-card="apps"]     .canvas-page-intro--apps     { display: block; }
body[data-card="websites"] .canvas-page-intro--websites { display: block; }
body[data-card="brand"]    .canvas-page-intro--brand    { display: block; }

/* Match the 540px contact card width */
.canvas-page-intro .about-block {
  width: 100%;
  max-width: 540px;
  padding-top: 40px;
  padding-left: 28px;
  padding-right: 28px;
  box-sizing: border-box;
}

.canvas-page-intro .about-title {
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  margin-bottom: 20px;
}

.canvas-page-intro .faq-title {
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  margin-bottom: 28px;
}

.canvas-page-intro .faq-section {
  width: 100%;
  max-width: 540px;
  padding: 40px 28px 60px;
  box-sizing: border-box;
}

/* Canvas FAQ pills — full width, smaller text, wrapping */
.canvas-page-intro .faq-item {
  width: 100%;
}
.canvas-page-intro .faq-item:hover,
.canvas-page-intro .faq-item:has(.faq-q[aria-expanded="true"]) {
  width: 100%;
}
.canvas-page-intro .faq-q {
  font-size: 1.18rem;
  white-space: normal;
  align-items: flex-start;
}
.canvas-page-intro .faq-q__text {
  white-space: normal;
}

/* The body paragraphs are now rendered by pretext as absolutely-positioned
   lines overlaid on the about-block. Keep visibility:hidden so the block
   retains its space for layout (letting us measure its position), while the
   original static <p> text stays invisible — only the pretext text is shown. */
.canvas-page-intro .about-block { visibility: hidden; }

/* Sticky left:0 ensures it's always flush with the viewport left edge
   regardless of the 2400px horizontal canvas scroll above it */
.canvas-bottom {
  position: sticky;
  left: 0;
  width: 100vw;
  display: flex;
  flex-direction: column;
  align-items: center;
  background: var(--bg);
  background-image: radial-gradient(circle, rgba(0,0,0,0.18) 1px, transparent 1px);
  background-size: 28px 28px;
  padding-top: 100px;
}

.canvas-bottom .contact {
  width: 100%;
  max-width: 540px;
  padding: 0;
}

/* Canvas footer occupies full width — matches main footer layout */
.canvas-site-footer {
  width: 100%;
}

/* canvas footer inherits footer-bottom position:absolute from .site-footer —
   no overrides needed; nav floats above "Create the future." just like homepage */

/* footer-giant inherits the same negative side margins as the main footer
   so the text escapes the padding and spans the full viewport width. */

/* --- source lines 6452-6515 --- */
/* ===== Deck cards ===== */
.deck-card {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  aspect-ratio: 3 / 2;
  border-radius: 16px;
  overflow: hidden;
  cursor: pointer;
  transform-origin: center bottom;
  transition: transform 0.35s cubic-bezier(0.16,1,0.3,1), opacity 0.3s ease;
  will-change: transform;
}
.deck-card img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}
.deck-card[data-deck-pos="0"] { transform: translateZ(0px)    translateY(0px);    z-index: 5; }
.deck-card[data-deck-pos="1"] { transform: translateZ(-70px)  translateY(-20px);  z-index: 4; opacity: 0.90; }
.deck-card[data-deck-pos="2"] { transform: translateZ(-140px) translateY(-36px); z-index: 3; opacity: 0.78; }
.deck-card[data-deck-pos="3"] { transform: translateZ(-210px) translateY(-50px); z-index: 2; opacity: 0.62; }
.deck-card[data-deck-pos="4"] { transform: translateZ(-280px) translateY(-60px); z-index: 1; opacity: 0.44; }
.deck-card[data-deck-pos="5"],
.deck-card[data-deck-pos="6"],
.deck-card[data-deck-pos="7"],
.deck-card[data-deck-pos="8"] { opacity: 0; pointer-events: none; transform: translateZ(-300px) translateY(-65px); z-index: 0; }
.deck-card[data-deck-pos="0"]:hover { transform: translateZ(0px) translateY(-18px); }
/* Hover arrow — top-right of front card */
.deck-card::after {
  content: '↗';
  position: absolute;
  top: 12px;
  right: 14px;
  width: 32px;
  height: 32px;
  line-height: 32px;
  text-align: center;
  background: rgba(255,255,255,0.88);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  border-radius: 8px;
  font-size: 15px;
  color: rgba(0,0,0,0.72);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.2s ease, transform 0.2s ease;
  pointer-events: none;
}
.deck-card[data-deck-pos="0"]:hover::after {
  opacity: 1;
  transform: translateY(0);
}
.deck-card--exit {
  transform-origin: top center !important;
  transform: rotateX(80deg) translateZ(160px) !important;
  opacity: 0 !important;
  pointer-events: none;
  transition: transform 0.5s cubic-bezier(0.55, 0.06, 0.68, 0.19), opacity 0.38s ease 0.08s !important;
}

/* --- source lines 6516-6607 --- */
/* ===== Central content cluster — Layer 3 (fully opaque, highest contrast) ===== */
.canvas-cluster {
  position: absolute;
  top: 50vh;       /* viewport-height aware so it appears in the visible centre at scrollTop:0 */
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 20px;
}

/* When a canvas is open: keep the cluster centred in the viewable area at
   scrollTop:0 but let it scroll up with the content as the user pans. */
body[data-card] .canvas-cluster {
  position: absolute;
  top: 50vh;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 200;
  pointer-events: all;
}

/* Horizontal cluster row: [card-col] [description] [device] */
.canvas-cluster-row {
  display: flex;
  align-items: center;
  gap: 36px;
}

/* Hidden — card kept in DOM for JS compatibility only */
.canvas-card-col {
  display: none;
}

/* Footer wordmark hidden — the fixed .logo element carries the identity on all screens */
.canvas-cluster-label {
  display: none;
}

/* ── Canvas card — identical to the home-screen card ── */
.canvas-card.card {
  /* width/min-width set dynamically by JS to match home card's actual layout width */
  flex-shrink: 0;
  transform: none;   /* Cancel nth-child rotations — specificity wins by position */
  animation: none;   /* Cancel card-in-N entrance animation */
  pointer-events: none; /* display only — not clickable inside the canvas overlay */
  cursor: default;
}

.canvas-card.card .card-inner {
  margin: 20px;
}

.canvas-card.card .card-label {
  padding: 4px 20% 16px 20px;
}

/* Simple hover — no rotation, just lift */

/* ── Description text — large, centred, section-coloured ── */
.canvas-desc {
  width: clamp(320px, 52vw, 620px);
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  font-weight: 400;
  line-height: 1.4;
  text-align: center;
  color: rgba(0,0,0,0.65);
}
/* Word wrappers — keep whole words together while chars animate freely */
.canvas-desc .word {
  display: inline-block;
  white-space: nowrap;
}
body[data-card="apps"]     .canvas-desc { color: var(--apps-out); }
body[data-card="websites"] .canvas-desc { color: var(--web-out); }
body[data-card="brand"]    .canvas-desc { color: var(--brand-out); }
body[data-card="ai"]       .canvas-desc { color: var(--ai-out); }

/* ── Phone / device placeholder ── */
.canvas-device-ph {
  width: 110px;
  height: 220px;
  border-radius: 24px;
  background: rgba(0,0,0,0.12);
  border: 1px solid rgba(0,0,0,0.07);
  box-shadow: 0 15px 40px rgba(0,0,0,0.12);
  flex-shrink: 0;
}

/* ========================================================================
   LAYER 12b · RESTORED FROM THE "BLOG LISTING" RANGE (source L6736-6768)
   ------------------------------------------------------------------------
   The extraction pass removed source lines 6608-6793 wholesale as "/blog
   listing page". That range is NOT purely blog CSS: it also contains two
   homepage mobile rules, and dropping them made the page 179px taller
   than the live page at 390px (the Trusted-By heading kept its box).
   Verified against the live page: at 390px the live
   `.trusted-section .trusted-hed` computes to `display: none`.
   Restored verbatim, at the source position, so cascade order is preserved.
   ======================================================================== */

/* --- source lines 6745-6749 --- */
@media (max-width: 699px) {
  .about-curve-svg { display: none; }
  /* The `.trusted-section .trusted-hed { display: none }` rule that lived here
     is deliberately gone. It mirrored the live reference page, where this
     heading was purely decorative and could be dropped on phones. Ours now
     carries real copy — "Experience built inside real businesses." plus the
     lede and clarification line — so hiding it would leave two orphaned
     paragraphs above the marquee on every phone. Kept as a note rather than
     silently deleted, since the comment above explains why it was restored. */
}

/* ========================================================================
   LAYER 13 · SCREENSAVER
   ======================================================================== */

/* --- source lines 6938-6991 --- */
/* ===== SCREENSAVER ===== */
#screensaver {
  position: fixed; inset: 0;
  z-index: 9000;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
}
#screensaver.ss-active { opacity: 1; }

#ss-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
}

#ss-cursor {
  position: absolute;
  width: 24px; height: 24px;
  pointer-events: none;
  transform: translate(-4px, -20px);
  filter: drop-shadow(0 1px 3px rgba(0,0,0,0.3));
  opacity: 0;
  transition: opacity 0.3s;
}
#screensaver.ss-active #ss-cursor { opacity: 1; }

.ss-sticky {
  position: fixed;
  width: 164px;
  min-height: 164px;
  background: #FFF9B1;
  border-radius: 2px;
  padding: 8px;
  box-shadow: 2px 4px 14px rgba(0,0,0,0.16), 0 1px 3px rgba(0,0,0,0.08);
  pointer-events: none;
  opacity: 0;
  transform: translateY(10px) rotate(var(--ss-rot, -3deg));
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.ss-sticky-text {
  display: block;
  padding: 6px 2px 2px;
  font-family: 'Inter', -apple-system, sans-serif;
  font-size: 0.8rem;
  line-height: 1.55;
  color: #3a3000;
  white-space: pre-line;
}
.ss-sticky.ss-sticky--visible {
  opacity: 1;
  transform: translateY(0) rotate(var(--ss-rot, -3deg));
}

/* ========================================================================
   LAYER 14 · FOLIO LIGHTBOX — full-screen project viewer
   ======================================================================== */

/* --- source lines 6992-7961 --- */
/* ======================================================
   FOLIO LIGHTBOX
   ====================================================== */
.folio-lb {
  position: fixed;
  inset: 0;
  z-index: 9500;
  pointer-events: none;
  visibility: hidden;  /* JS sets style.visibility directly for timing control */
}

/* Full-screen background — contains the pixel-dissolve canvas injected by JS */
.folio-lb__bg {
  position: absolute;
  inset: 0;
  opacity: 0.99;
  cursor: default;
  pointer-events: auto;
  overflow: hidden;
}

/* Logo — mirrors the scrolled main logo: same position, same scale, white */
.folio-lb__logo {
  position: fixed;
  top: 40px;
  left: var(--logo-left, 28px);
  z-index: 2;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(1.3rem, 2vw, 1.8rem);
  font-weight: 400;
  letter-spacing: -0.02em;
  color: #fff;
  text-decoration: none;
  opacity: 0;
  transform: scale(0.6) translateY(10px);
  transform-origin: top left;
  transition: opacity 0.24s ease 0.3s,
              transform 0.28s cubic-bezier(0.16, 1, 0.3, 1) 0.3s,
              color 0.15s ease;
  pointer-events: auto;
}
.folio-lb.is-open .folio-lb__logo { opacity: 1; transform: scale(0.6) translateY(0); }
.folio-lb__logo:hover { color: #fff; }
@media (max-width: 699px) {
  .folio-lb__logo { left: 20px !important; top: 28px; }
}
@media (min-width: 900px) {
  .folio-lb__logo { top: 48px; }
}

/* Title — glass pill, centred at top, matches work-thumb label style */
/* Top bar — holds category filter pill + project title pill */
.folio-lb__top-bar {
  position: fixed;
  top: 40px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 8px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s ease 0.34s;
}
.folio-lb.is-open .folio-lb__top-bar { opacity: 1; pointer-events: auto; }
@media (min-width: 900px) { .folio-lb__top-bar { top: 48px; } }
@media (max-width: 699px) {
  .folio-lb__top-bar {
    top: 64px;
    left: 20px;
    transform: none;
    justify-content: flex-start;
  }
}

/* Pill wrapper */
.folio-lb__pill-wrap { position: relative; }

/* Title / filter button — glass pill */
.folio-lb__title {
  display: flex;
  align-items: center;
  gap: 7px;
  color: #fff;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  background: rgba(0, 0, 0, 0.48);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border-radius: 20px;
  padding: 8px 14px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s ease;
}
.folio-lb__title:hover { background: rgba(0, 0, 0, 0.62); }

.folio-lb__title-caret {
  color: rgba(255,255,255,0.55);
  transition: transform 0.22s ease, color 0.15s ease;
}
.folio-lb__title[aria-expanded="true"] .folio-lb__title-caret {
  transform: rotate(180deg);
  color: rgba(255,255,255,0.9);
}

/* Dropdown menu */
.folio-lb__menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  margin: 0;
  padding: 6px;
  background: rgba(10, 10, 10, 0.82);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 14px;
  min-width: 150px;
  /* Cap to viewport so it never spills off-screen, but no scroll bar.
     Items flow into multiple columns when the list is taller than the cap. */
  max-height: calc(100vh - 120px);
  overflow: hidden;
  list-style: none;
  z-index: 100;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-6px);
  transition: opacity 0.18s ease, transform 0.22s cubic-bezier(0.16, 1, 0.3, 1);
  /* Project dropdown only — the title menu has many items.
     Use CSS multi-column so items break into columns when there are too many to fit
     in a single column at the current viewport height. */
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-content: flex-start;
  column-gap: 6px;
}
/* Filter menu (small list of 4) stays single-column */
#folio-lb-filter-menu {
  flex-wrap: nowrap;
  max-height: none;
}
.folio-lb__pill-wrap.menu-open .folio-lb__menu {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

/* Menu items */
.folio-lb__menu-item {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.6);
  padding: 8px 12px;
  border-radius: 8px;
  cursor: pointer;
  white-space: nowrap;
  list-style: none;
  transition: background 0.12s ease, color 0.12s ease;
}
.folio-lb__menu-item:hover { background: rgba(255,255,255,0.1); color: #fff; }
.folio-lb__menu-item--active { background: rgba(255,255,255,0.14); color: #fff; }

/* Description */
.folio-lb__desc {
  position: fixed;
  top: 88px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  color: rgba(255,255,255,0.65);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  letter-spacing: 0.01em;
  line-height: 1.5;
  text-align: center;
  max-width: min(560px, calc(100vw - 120px));
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease 0.2s;
}
.folio-lb.is-open .folio-lb__desc { opacity: 1; }
@media (max-width: 699px) { .folio-lb__desc { top: 72px; font-size: 0.68rem; } }
@media (max-width: 899px) { .folio-lb__desc { display: none; } }

/* Close button — top right */
.folio-lb__close {
  position: absolute;
  top: 18px;
  right: 22px;
  z-index: 2;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.48);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: none;
  color: rgba(255, 255, 255, 0.8);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transform: scale(0.75);
  transition: opacity 0.2s ease 0.32s,
              transform 0.24s cubic-bezier(0.34, 1.56, 0.64, 1) 0.32s,
              background 0.15s ease;
}
.folio-lb.is-open .folio-lb__close { opacity: 1; transform: scale(1); }
.folio-lb__close:hover { background: rgba(0, 0, 0, 0.62); }

/* Horizontal image carousel */
.folio-lb__carousel {
  position: absolute;
  top: 68px;
  bottom: 72px;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  gap: 4px;
  padding-left: 80px;
  padding-right: 80px;
  /* opacity driven by JS for FLIP reveal */
}
.folio-lb__carousel::-webkit-scrollbar { display: none; }

.folio-lb__slide {
  flex: 0 0 auto;
  min-width: min(255px, 85vw); /* prevents 0-width before image loads */
  height: min(425px, 59.5vh);
  border-radius: 14px;
  overflow: hidden;
  transform-origin: center center;
  will-change: transform, opacity;
  cursor: grab;
}
.folio-lb__carousel.is-dragging .folio-lb__slide { cursor: grabbing; }
.folio-lb__carousel.is-dragging { cursor: grabbing; }
.folio-lb__slide img,
.folio-lb__slide video {
  display: block;
  height: 100%;
  width: auto;
  max-width: 85vw;
  border-radius: inherit;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}

/* ── Project title slides ─────────────────────────────────────────────── */
.folio-lb__slide--title {
  background: var(--flb-color);
  width: min(380px, 85vw);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  padding: 175px 28px 28px;
  box-sizing: border-box;
  flex-shrink: 0;
  overflow: hidden;
  gap: 10px;
}
@media (min-width: 900px) {
  .folio-lb__slide--title { width: min(520px, 85vw); }
}
.lb-title-text {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.15;
  color: rgba(255, 255, 255, 0.85);
  overflow: hidden;
  word-break: break-word;
}
.lb-title-char {
  display: inline-block;
  opacity: 0;
}
/* Mobile: skip the WAAPI per-char reveal — IntersectionObserver inside the
   vertically-scrolling carousel doesn't always fire reliably on the first
   slide, so we just keep titles visible. */
@media (max-width: 899px) {
  .lb-title-char { opacity: 1; }
}
.lb-title-tagline {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.01em;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.5);
  /* Sits 50px below the title — was 100px, felt detached on both desktop and mobile */
  margin-top: 50px;
  opacity: 0;
  transition: opacity 0.4s ease 0.5s;
}
.folio-lb.is-open .lb-title-tagline { opacity: 1; }

/* Description — desktop hides this (uses external panel); mobile shows on
   the title slide. Re-ordered with flex `order` so the company description
   appears directly UNDER the title, with the short tagline pushed below. */
.lb-title-desc { display: none; }
@media (max-width: 899px) {
  .lb-title-desc {
    display: block;
    font-family: 'IBM Plex Mono', monospace;
    font-size: 0.72rem;
    font-weight: 400;
    letter-spacing: 0.01em;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.5);
    margin-top: 50px;        /* sit right under the title */
    opacity: 0;
    transition: opacity 0.4s ease 0.5s;
    order: 1;
  }
  .lb-title-tagline {
    margin-top: 6px;          /* now sits under the desc instead */
    transition: opacity 0.4s ease 0.55s;
    order: 2;
  }
  .folio-lb.is-open .lb-title-desc { opacity: 1; }
}

/* Prev / Next project nav — sides */
.folio-lb__nav {
  position: fixed;
  bottom: 20px;
  z-index: 2;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: rgba(255, 255, 255, 0.8);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.2s ease 0.36s, background 0.15s ease;
}
.folio-lb.is-open .folio-lb__nav { opacity: 1; }
.folio-lb__nav:hover { background: rgba(255, 255, 255, 0.18); }
.folio-lb__nav--prev { right: 70px; }
.folio-lb__nav--next { right: 20px; }

/* Mobile: stack prev/next vertically on the right edge, mid-screen, and
   rotate the chevrons 90° so they point up/down. Pause is hidden. */
@media (max-width: 899px) {
  .folio-lb__nav--prev {
    right: 16px;
    bottom: auto;
    top: calc(50% - 52px);
  }
  .folio-lb__nav--next {
    right: 16px;
    bottom: auto;
    top: calc(50% + 10px);
  }
  .folio-lb__nav--prev svg,
  .folio-lb__nav--next svg { transform: rotate(90deg); }
  .folio-lb__nav--pause { display: none !important; }
}

@media (min-width: 900px) {
  .folio-lb__hint { display: none !important; }
  .folio-lb__nav {
    bottom: 140px;
    right: auto;
  }
  .folio-lb__nav--prev  { left: calc(50% - 92px); }
  .folio-lb__nav--pause { left: calc(50% - 21px); }
  .folio-lb__nav--next  { left: calc(50% + 50px); }
}

/* Scroll hint at bottom — matches homepage #scroll-hint layout, white on dark */
.folio-lb__hint {
  position: absolute;
  bottom: max(92px, calc(80px + env(safe-area-inset-bottom)));
  left: 50%;
  transform: translateX(-50%) translateY(10px);
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  pointer-events: none;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.55s ease 0.5s, transform 0.55s cubic-bezier(0.16, 1, 0.3, 1) 0.5s;
}
.folio-lb.is-open .folio-lb__hint {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.folio-lb__hint-chevron {
  color: rgba(255, 255, 255, 0.55);
  animation: sh-bounce 1.5s ease-in-out infinite;
}
.folio-lb__hint-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.55);
  margin: 0;
  text-transform: lowercase;
}

/* Slide swipe-reveal — left-to-right clip wipe on carousel open */
@keyframes folio-slide-reveal {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0% 0 0); }
}
.folio-slide-reveal {
  animation: folio-slide-reveal 0.28s cubic-bezier(0.16, 1, 0.3, 1) both;
}

/* FLIP clone — created by JS, sits above lightbox during animation */
.folio-flip-clone {
  position: fixed;
  pointer-events: none;
  z-index: 9600;
  will-change: transform;
  transform-origin: top left;
  overflow: hidden;
  border-radius: 14px;
}
.folio-flip-clone img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* ══════════════════════════════════════════════════════
   PRICING BARS
   ══════════════════════════════════════════════════════ */

.pb-section {
  /* Left-align the whole pricing block to the 15vw + 100 px column
     used by every other section H2. */
  padding: 100px 28px 120px calc(15vw + 100px);
  max-width: none;
  margin: 0;
}

@media (min-width: 900px) {
  .pb-section { padding: 100px 28px 120px calc(15vw + 100px); max-width: none; margin: 0; }
}

@media (max-width: 768px) {
  .pb-section { padding: 64px 20px 80px; }
}

.pb-title {
  /* Match the "More about process" heading (.trusted-hed--plain):
     same Helvetica clamp, same letter-spacing / line-height, same
     10vw left margin. */
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(0.79rem, 3.1vw, 3.06rem);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.02;
  color: var(--text);
  text-align: left;
  max-width: min(100%, calc(90vw - 28px));
  margin: 0 28px 60px 0;
}
@media (max-width: 699px) {
  .pb-title {
    font-size: clamp(0.72rem, 3.96vw, 1.62rem);
    margin: 0 16px 32px 0;
  }
}

.pb-sub {
  font-size: 1rem;
  color: rgba(0,0,0,0.42);
  margin: 0 0 44px;
  max-width: 50ch;
  line-height: 1.6;
}

.pb-controls {
  display: flex;
  align-items: center;
  gap: 20px;
  /* Left-aligned to the pb-title (no centring, no max-width). */
  margin: 0 0 36px 0;
  max-width: none;
  flex-wrap: wrap;
  justify-content: flex-start;
}

.pb-filters {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.pb-filter {
  padding: 7px 16px;
  border: none;
  border-radius: 100px;
  background: #ffffff;
  font-size: 0.875rem;
  font-family: inherit;
  cursor: pointer;
  color: inherit;
  transition: background 0.18s, color 0.18s;
}

.pb-filter:hover { background: #f4f3ee; }

.pb-filter--active {
  background: #111;
  border-color: #111;
  color: #fff;
}

/* Mobile — shrink pills slightly so all four (App / Brand / Strategy / Web) sit on one line */
@media (max-width: 768px) {
  .pb-filters { flex-wrap: nowrap; gap: 5px; margin-bottom: 28px; }
  .pb-filter {
    font-size: 0.78rem;
    padding: 6px 11px;
    white-space: nowrap;
  }
}

.pb-tier-row { margin-left: 16px; }

/* ── Groups ── */
.pb-group { display: none; }
.pb-group--active {
  display: flex;
  flex-direction: column;
  /* Even vertical spacing between the pricing cards. */
  gap: 20px;
  align-items: flex-start;
}
.pb-group--active > .pb-bar {
  margin: 0 !important; /* let `gap` control spacing — no stray margins */
}
/* When the collapsible System bar is hidden, remove it from the
   flex flow entirely so the surrounding 20 px gap doesn't double up
   (was producing uneven 12 / 28 / 20 px spacing). */
.pb-group--active > .pb-bar--collapsible[aria-hidden="true"] {
  display: none !important;
}
/* Desktop: zigzag the bars — 1st right, 2nd left, 3rd right — so the
   variable-width pills feel staggered rather than just centred or stacked.
   Mobile keeps flex-start since bars are forced to width:100% and any
   alignment trick is moot at full width. */
@media (min-width: 769px) {
  /* Left-align the cards to the pb-title's left edge (no zigzag,
     no centred column). */
  .pb-group--active { align-items: flex-start; }
  .pb-group--active > .pb-bar { transform: none; }
  .pb-group--active > .pb-bar:hover,
  .pb-group--active > .pb-bar.is-open { transform: none; }
}

/* ── Individual bar — the bar IS the coloured card ── */
.pb-bar {
  width: var(--bar-w);
  min-width: 220px;
  /* Match the .contact-card ("Need a hand?") corner radius. */
  border-radius: var(--r-card);
  overflow: hidden;
  cursor: pointer;
  --bar-w: 48%;
  text-align: left;
  transition: width 0.65s cubic-bezier(0.16, 1, 0.3, 1),
              transform 0.55s cubic-bezier(0.16, 1, 0.3, 1),
              border-radius 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}

/* White card variant — overrides every coloured .pb-bar--* background
   and forces text/icons to dark for legibility. Cards are left-aligned
   rectangles, corner-matched to the Need a hand? form. */
.pb-bar,
.pb-bar--design,
.pb-bar--system,
.pb-bar--build,
.pb-bar--combo {
  background: #ffffff !important;
  color: #111111 !important;
  border: 1px solid rgba(0, 0, 0, 0.06);
}
.pb-bar .pb-bar__name,
.pb-bar .pb-bar__tier,
.pb-bar .pb-bar__starting,
.pb-bar .pb-bar__disclaimer,
.pb-bar .pb-bar__price,
.pb-bar .pb-bar__price::after,
.pb-bar .pb-bar__desc,
.pb-bar .pb-bar__list li,
.pb-bar .pb-bar__list li::before {
  color: #111111 !important;
}
.pb-bar .pb-bar__btn {
  background: rgba(0, 0, 0, 0.08) !important;
  color: #111111 !important;
}
.pb-bar:hover .pb-bar__btn,
.pb-bar.is-open .pb-bar__btn {
  background: rgba(0, 0, 0, 0.14) !important;
}
.pb-bar .pb-bar__head,
.pb-bar .pb-bar__body,
.pb-bar .pb-bar__info {
  text-align: left;
}

.pb-bar--design { background: #FFD905; color: #111; }
.pb-bar--system { background: #1A1A18; color: #F4F3EE; } /* digital design system */
.pb-bar--build  { background: #0E4C4B; color: #fff; }   /* matches .card--ai (Experience) green */
.pb-bar--build .pb-bar__name,
.pb-bar--build .pb-bar__tier,
.pb-bar--build .pb-bar__disclaimer,
.pb-bar--build .pb-bar__price { color: #fff; opacity: 1; }
.pb-bar--build .pb-bar__price::after { color: #fff; opacity: 1; }
.pb-bar--system .pb-bar__name,
.pb-bar--system .pb-bar__tier,
.pb-bar--system .pb-bar__disclaimer,
.pb-bar--system .pb-bar__price { color: #F4F3EE; opacity: 1; }
.pb-bar--system .pb-bar__price::after { color: #F4F3EE; opacity: 1; }
.pb-bar--system .pb-bar__desc,
.pb-bar--system .pb-bar__list li { color: #F4F3EE; opacity: 1; }
.pb-bar--system .pb-bar__list li::before { color: #F4F3EE; opacity: 1; }
.pb-bar--system:hover .pb-bar__disclaimer,
.pb-bar--system.is-open .pb-bar__disclaimer { opacity: 1; }
.pb-bar--system .pb-bar__btn { background: rgba(255,255,255,0.18); }
.pb-bar--system:hover .pb-bar__btn { background: rgba(255,255,255,0.28); }
.pb-bar--system.is-open .pb-bar__btn { background: rgba(255,255,255,0.28); }
/* Override the generic hover opacity so the disclaimer stays full white */
.pb-bar--build:hover .pb-bar__disclaimer,
.pb-bar--build.is-open .pb-bar__disclaimer { opacity: 1; }
/* Body copy inside the expanded orange bar — full white, no dimming */
.pb-bar--build .pb-bar__desc,
.pb-bar--build .pb-bar__list li { color: #fff; opacity: 1; }
.pb-bar--build .pb-bar__list li::before { color: #fff; opacity: 1; }
.pb-bar--combo  { background: #3B5BFF; color: #fff; }
/* Combo (blue) bar: bump up the secondary text opacities so the small
   labels don't read as washed-out grey against the saturated blue. */
.pb-bar--combo .pb-bar__name,
.pb-bar--combo .pb-bar__tier,
.pb-bar--combo .pb-bar__disclaimer { color: #fff; opacity: 1; }
.pb-bar--combo .pb-bar__price,
.pb-bar--combo .pb-bar__price::after { color: #fff; opacity: 1; }

.pb-bar:hover,
.pb-bar.is-open {
  /* Cap the open/hover width to the same right-edge margin used
     by every other section (matches .pb-section's right inset). */
  width: 100%;
  max-width: calc(100vw - (15vw + 100px) - 5vw);
  border-radius: 41px;
}

/* Mobile — always full width regardless of slider value */
@media (max-width: 768px) {
  .pb-bar { width: 100% !important; position: relative; }
  /* Horizontal: name | price | btn — all on one line. */
  .pb-bar__head {
    flex-direction: row;
    align-items: center;
    gap: 10px;
    padding: 22px 18px;
  }
  .pb-bar__info { flex: 1 1 auto; min-width: 0; }
  .pb-bar__name { font-size: 1.1rem; }
  .pb-bar__price {
    align-self: center;
    flex: 0 0 auto;
    font-size: clamp(1.5rem, 8.5vw, 2rem);
    text-align: right;
  }
  .pb-bar__price::after { font-size: 0.55rem; margin-top: 6px; }
  /* Expand button sits inline, immediately to the right of the price. */
  .pb-bar > .pb-bar__head > .pb-bar__btn,
  .pb-bar > .pb-bar__btn {
    position: static;
    flex: 0 0 auto;
    margin-left: 4px;
  }
  /* On mobile, rotate the ↗ arrow so it points DOWN by default and
     flips UP when the bar is open (standard accordion affordance). */
  .pb-bar .pb-bar__btn { transform: rotate(135deg); }
  .pb-bar:hover .pb-bar__btn { transform: rotate(135deg); }
  .pb-bar.is-open .pb-bar__btn { transform: rotate(315deg); }
}

/* ── Header row ── */
.pb-bar__head {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 44px 28px;
  color: inherit;
  user-select: none;
}

.pb-bar__info {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.pb-bar__name {
  /* +20% over the previous 1.31rem */
  font-size: 1.572rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  white-space: normal;
  overflow-wrap: break-word;
}

/* Tier row: tier label + "STARTING" + disclaimer on one line */
.pb-bar__tier-row {
  display: flex;
  align-items: center;
  gap: 7px;
  overflow: hidden;
}

.pb-bar__tier {
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  opacity: 0.45;
  flex-shrink: 0;
}

/* "Starting" label moved under the price (see .pb-bar__price::after).
   The original inline element in the tier-row stays in markup for accessibility
   but is hidden visually. */
.pb-bar__starting { display: none; }

.pb-bar__disclaimer {
  font-size: 0.62rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0.02em;
  opacity: 0;
  max-width: 0;
  white-space: nowrap;
  overflow: hidden;
  flex-shrink: 0;
  transition: opacity 0.35s ease, max-width 0.55s cubic-bezier(0.16, 1, 0.3, 1);
}

.pb-bar__disclaimer::before {
  content: '·';
  margin-right: 7px;
}

.pb-bar:hover .pb-bar__disclaimer,
.pb-bar.is-open .pb-bar__disclaimer {
  opacity: 0.4;
  max-width: 260px;
}

/* Price */
.pb-bar__price {
  font-size: clamp(2.4rem, 4.5vw, 3rem);
  font-weight: 400;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex-shrink: 0;
  line-height: 1;
  text-align: right;
}
/* "Starting" sublabel sits directly under the price */
.pb-bar__price::after {
  content: 'Starting';
  display: block;
  margin-top: 8px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.45;
}

/* Expand button */
.pb-bar__btn {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba(0,0,0,0.08);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  transition: background 0.2s, transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}

.pb-bar:hover .pb-bar__btn { background: rgba(0,0,0,0.13); transform: rotate(180deg); }
.pb-bar.is-open .pb-bar__btn { transform: rotate(45deg); background: rgba(0,0,0,0.13); }
/* Open state should always win over hover so the arrow visibly toggles */
.pb-bar.is-open:hover .pb-bar__btn { transform: rotate(45deg); }

.pb-bar--combo .pb-bar__btn { background: rgba(0,0,0,0.18); }
.pb-bar--combo:hover .pb-bar__btn,
.pb-bar--combo.is-open .pb-bar__btn { background: rgba(0,0,0,0.28); }

/* ── Expanded body ── */
.pb-bar__body {
  max-height: 0;
  overflow: hidden;
  padding: 0 28px;
  transition: max-height 0.52s cubic-bezier(0.16, 1, 0.3, 1),
              padding-bottom 0.4s ease;
}

.pb-bar:hover .pb-bar__body,
.pb-bar.is-open .pb-bar__body {
  max-height: 560px;
  padding-bottom: 86px;
}

.pb-bar__body::before {
  content: '';
  display: block;
  height: 1px;
  background: rgba(0,0,0,0.10);
  margin-bottom: 18px;
}

.pb-bar--combo .pb-bar__body::before { background: rgba(255,255,255,0.18); }

.pb-bar__desc {
  margin: 0 0 18px;
  font-size: 0.92rem;
  line-height: 1.68;
  opacity: 0.62;
  max-width: 72ch;
}

.pb-bar__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px 36px;
}

@media (max-width: 560px) {
  .pb-bar__list { grid-template-columns: 1fr; }
}

.pb-bar__list li {
  font-size: 0.875rem;
  opacity: 0.7;
  display: flex;
  align-items: baseline;
  gap: 7px;
}

.pb-bar__list li::before {
  content: '↗';
  font-size: 0.68rem;
  opacity: 0.5;
  flex-shrink: 0;
}

/* ── "More about X process" footer ── */
/* Left-aligned with the body text and pushed down with extra top space so it
   reads as a clear footer call-to-action rather than tucked next to the price. */
.pb-bar__footer {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  padding-top: 40px;
  margin-top: auto;
}

.pb-bar__more-text {
  font-size: 0.78rem;
  opacity: 0.45;
  white-space: nowrap;
  color: inherit;
}

.pb-bar__more-btn {
  display: inline-flex;
  align-items: center;
  background: #111;
  color: #fff !important;
  border: none;
  border-radius: 20px;
  padding: 7px 18px;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  flex-shrink: 0;
  transition: background 0.2s ease;
}

.pb-bar__more-btn:hover { background: #333; }

/* ── Static bars — no width transition ── */
.pb-bar--static { transition: none; }

/* ── Scroll lock — suppress hover interactions for 1s after scroll ── */
.pb-section.is-scroll-locked .pb-bar { pointer-events: none; }

/* ── Vertical carousel for tablet portrait + mobile ─────────────────── */
@media (max-width: 899px) {
  .folio-lb__carousel {
    top: 0;
    bottom: 0;
    flex-direction: column;
    align-items: stretch;
    overflow-x: hidden;
    overflow-y: auto;
    padding: 110px 16px calc(100dvh - 160px) 16px;
    gap: 8px;
  }
  .folio-lb__slide {
    width: 100%;
    min-width: unset;
    height: auto;
  }
  .folio-lb__slide img,
  .folio-lb__slide video {
    width: 100%;
    height: auto;
    max-width: unset;
    max-height: 70vh;
  }
  .folio-lb__slide--title {
    width: 100%;
    min-width: unset;
    height: auto;
    min-height: 280px;
    padding: 175px 28px 28px;
  }
  /* Stack words on separate lines so multi-word titles never wrap mid-word */
  .folio-lb__slide--title .lb-title-word { display: block; }
  .folio-lb__slide--title .lb-title-space { display: none; }
}

/* ========================================================================
   LAYER 15 · WORK ZOOM — scroll-pinned zoom-out parallax stage (canvas view of the folio)
   ======================================================================== */

/* --- source lines 7962-8255 --- */
/* ============================================================
   WORK ZOOM — scroll-pinned zoom-out parallax (desktop default)
   ============================================================ */

/* Section provides the scroll runway. Sticky child pins the viewport.
   No background — the body's scroll-driven cream→yellow gradient shows
   through, so there's no sharp colour boundary when sticky releases. */
.work-zoom {
  position: relative;
  height: 480vh;            /* runway = ~3.8 viewports of scroll — long, slow zoom */
  margin-top: -120px;       /* tuck under previous section so it reads as one flow */
  z-index: 1;
}

.work-zoom__sticky {
  position: sticky;
  top: 0;
  width: 100%;
  height: 100vh;
  overflow: hidden;
  /* Caption + controls vertically centred in the sticky viewport so
     the title stops at mid-screen as the user scrolls through the
     runway. Parallax stage is absolute-positioned behind. */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
}

.work-zoom__stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Stage no longer scales — each tile animates its own entry offset
     via --ox / --oy (set by JS per scroll frame). */
}

/* The virtual world canvas. Sized to fill the viewport exactly at
   scale 1 (the FINAL state). At scale 2.5 only the centre ~40% of
   the canvas is visible — everything else is off-screen until the
   camera zooms out. Using vw/vh keeps tile positions (% based) at
   true viewport positions when the camera reaches scale 1. */
.work-zoom__canvas {
  position: relative;
  width: 100vw;
  height: 100vh;
  flex-shrink: 0;
}

/* Each tile's inline left/top is its FINAL CENTRE on the canvas. JS
   drives a "camera pulling back" entry: at enter-start the tile is
   OFF-SCREEN (offset by data-from-x/y in vw/vh) and LARGE (scale
   ~1.8) — feels close to the camera. By enter-end the tile has slid
   to its final position and shrunk to its final scale (1). */
.wz-tile {
  position: absolute;
  border-radius: 12px;
  /* overflow:visible so the hover badge can spill past the tile's
     edge — the image/video below clips itself via its own
     border-radius so the rounded corners still show. */
  overflow: visible;
  background: var(--surface);
  text-decoration: none;
  cursor: pointer;
  transform:
    translate(-50%, -50%)
    translate(var(--ox, 0vw), var(--oy, 0vh))
    scale(var(--sc, 1.8));
  transform-origin: center center;
  /* Hidden before its entry window starts so the page doesn't open
     with all 22 tiles visible at large scale. JS sets --op = 1 once
     the tile reaches its entry-start. */
  opacity: var(--op, 0);
}
.wz-tile:hover {
  transform:
    translate(-50%, -50%)
    translate(var(--ox, 0vw), var(--oy, 0vh))
    scale(var(--sc, 1.8))
    translateY(-4px);
  transition: transform 0.25s var(--ease-out);
}

/* Hover badge — pill in the tile's top-right with project name + ↗ arrow.
   The label comes from the tile's data-label (set in JS from the slug).
   The badge counter-scales the tile's perspective transform so it
   always renders at the SAME viewport-pixel size regardless of how
   big or small the tile is in the camera move. transform-origin
   top-right anchors it to the tile's corner. */
.wz-tile::after {
  content: attr(data-label);
  position: absolute;
  top: 8px;
  right: 8px;
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 32px 0 12px;
  background: #fff url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><path d='M7 17L17 7'/><path d='M7 7h10v10'/></svg>") no-repeat right 10px center;
  border-radius: 100px;
  font-family: 'Inter', -apple-system, sans-serif;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: #111;
  white-space: nowrap;
  opacity: 0;
  transform: scale(calc(1 / var(--sc, 1)));
  transform-origin: top right;
  transition: opacity 0.2s var(--ease-out);
  pointer-events: none;
}
.wz-tile:hover::after { opacity: 1; }

.wz-tile img,
.wz-tile video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  /* Now that .wz-tile is overflow:visible, the rounded corners need
     to live on the media itself. */
  border-radius: 12px;
}

/* Caption + controls are flex children of the sticky column, so they
   stay 24px apart regardless of which view is active. */
.work-zoom__caption {
  position: relative;
  font-family: 'Inter', sans-serif;
  font-size: clamp(2rem, 4vw, 3.4rem);
  font-weight: 400;
  letter-spacing: -0.025em;
  line-height: 1.15;
  color: var(--text);
  text-align: center;
  z-index: 10;
  pointer-events: none;
  max-width: min(820px, 90vw);
  margin: 0;
  padding: 0;
}

/* Word-by-word entrance — same gentle ease as the hero <h1>
   ("App, web, brand and build expert"). No bounce; pure ease-out. */
.wz-caption-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}
.wz-caption-word.is-in {
  opacity: 1;
  transform: translateY(0);
}

/* Unified controls below the caption.
   - In canvas/zoom view: only the toggle is in flow → bar collapses to
     the toggle's width → translateX(-50%) lands the toggle dead-centre.
   - In tiles/rows view: filters expand from max-width 0 to natural width
     (with 16px left margin). The bar grows; translateX(-50%) keeps it
     centred so the toggle smoothly shifts left to make space, and the
     filters fade-in-up beside it. */
.work-zoom__controls {
  position: relative;
  z-index: 10;
  display: flex;
  align-items: center;
  pointer-events: auto;
  opacity: 0;
  /* Fade in early so the controls begin appearing while the caption is
     still finishing its word-stagger. */
  transition: opacity 0.5s ease;
}
.work-zoom__sticky.controls-ready .work-zoom__controls { opacity: 1; }

/* Reset the legacy margin-top that .work-view-toggle (16px) and
   .work-filters (4px) carry from the work-panel layout — inside
   work-zoom__controls we want both children flush so flex
   align-items:center keeps them on the same baseline. */
.work-zoom__controls .work-view-toggle,
.work-zoom__controls .work-filters {
  margin-top: 0;
}

/* Filters hidden by default — collapsed to width 0 with no left margin
   so they take no space (toggle is alone, centred). flex-wrap:nowrap
   keeps the buttons on a single row even when max-width:0 clips them
   horizontally, so the wrapper's height stays 32px rather than ballooning
   to 4×stacked-button-heights. */
.work-zoom__controls .work-filters[data-target="zoom"] {
  max-width: 0;
  margin-left: 0;
  overflow: hidden;
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  white-space: nowrap;
  flex-wrap: nowrap;
  transition: max-width 0.5s ease, margin-left 0.5s ease,
              opacity 0.4s ease 0.1s, transform 0.4s ease 0.1s;
}
.work-zoom[data-view="tiles"] .work-zoom__controls .work-filters[data-target="zoom"],
.work-zoom[data-view="rows"]  .work-zoom__controls .work-filters[data-target="zoom"] {
  max-width: 500px;
  margin-left: 16px;
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* In list/tile mode caption + controls scroll WITH the rest of the page
   — no sticky pinning, no 480vh runway. Title sits above the filter
   bar, filter bar above the grid, all in normal document flow. */
.work-zoom[data-view="rows"],
.work-zoom[data-view="tiles"] {
  height: auto;
}
.work-zoom[data-view="rows"]  .work-zoom__sticky,
.work-zoom[data-view="tiles"] .work-zoom__sticky {
  position: relative;
  height: auto;
  /* In list/tile mode the section becomes flow content. Top padding of
     ~50vh keeps the title at roughly the same mid-screen position the
     user sees in canvas view (where sticky pins it at viewport centre). */
  padding: 50vh 28px 28px;
  flex-direction: column;
  justify-content: flex-start;
  gap: 24px;
}
.work-zoom[data-view="rows"]  .work-zoom__caption,
.work-zoom[data-view="tiles"] .work-zoom__caption {
  position: relative;
  top: auto;
  left: auto;
  transform: none;
  margin: 0 auto;
  display: block;
}
.work-zoom[data-view="rows"]  .work-zoom__controls,
.work-zoom[data-view="tiles"] .work-zoom__controls {
  position: relative;
  top: auto;
  left: auto;
  transform: none;
  margin: 0 auto;
}
/* Hide the parallax stage in list/tile modes — its place is taken by
   the grid hosted directly below. */
.work-zoom[data-view="rows"]  .work-zoom__stage,
.work-zoom[data-view="tiles"] .work-zoom__stage {
  display: none;
}
/* Grid host — sits below the (non-sticky) caption+controls block in
   the page DOM and scrolls together with them. Centred horizontally
   so the grid block lines up under the centred caption + filters.
   100px of breathing room above the grid so the tiles/rows don't sit
   tight against the toggle controls. */
.work-zoom__grid-host {
  position: relative;
  z-index: 1;
  /* Shifted 100 px to the right of its centred position. */
  padding: 100px 28px 80px 128px;
  max-width: 1280px;
  margin: 0 auto;
}
.work-zoom__grid-host .work-panel__grid {
  margin-left: auto;
  margin-right: auto;
}
/* In rows view the grid declares one 700px-wide column inside a wide
   grid container — that lines the rows up to the LEFT of the host.
   Centre the column track horizontally so rows sit in the middle. */
.work-zoom__grid-host .work-panel__grid:not(.work-panel__grid--tiles) {
  justify-content: center;
}
.work-zoom[data-view="zoom"] .work-zoom__grid-host { display: none; }
.work-panel:not(.has-grid) { display: none; }

/* Mobile: keep .work-zoom visible (rows view stacks at <980 px via the
   bottom of this stylesheet). The .work-panel is left empty after the
   grid is moved into work-zoom__grid-host on load, so hide it. */
@media (max-width: 899px) {
  .work-panel { display: none !important; }
}
/* Desktop: zoom view sits ABOVE the standard tile/list grid; users can
   continue scrolling past the zoom and see the same projects in the
   classic grid (with category filters + view-mode toggle). */

/* ========================================================================
   LAYER 16 · HIGH-SCORE PANEL + collapsible pb-bar sub-card
   ======================================================================== */

/* --- source lines 8256-8433 --- */
/* ============================================================
   HIGH SCORES PANEL
   Black floating card modeled on .contact-panel — sits above the
   bottom nav, holds the top-10 leaderboard. When the user qualifies
   for top 10, an inline form row at their position takes a name.
   ============================================================ */
.highscore-panel {
  position: fixed;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  bottom: calc(max(28px, 16px + env(safe-area-inset-bottom)) + 56px + 14px);
  width: min(calc(100vw - 32px), 480px);
  background: #1a1a18;
  border-radius: 14px;
  overflow: hidden;
  z-index: 9850;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease,
              transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
  box-shadow: 0 -4px 60px rgba(0,0,0,0.6),
              0 0 0 1px rgba(255,255,255,0.06) inset;
}
.highscore-panel.is-open {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
.highscore-panel__close {
  all: unset;
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 10;
  cursor: pointer;
  color: rgba(255,255,255,0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: rgba(255,255,255,0.06);
  transition: color 0.15s, background 0.15s;
}
.highscore-panel__close:hover {
  color: #fff;
  background: rgba(255,255,255,0.14);
}
.highscore-panel__inner {
  padding: 22px 24px 22px;
}
.highscore-panel__heading {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.9);
  margin: 0 0 14px;
}
.highscore-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.hs-row {
  display: grid;
  grid-template-columns: 28px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  border-radius: 8px;
  background: rgba(255,255,255,0.04);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 13px;
  color: rgba(255,255,255,0.85);
  min-height: 38px;
}
.hs-row:hover {
  background: rgba(255,255,255,0.07);
}
.hs-rank {
  font-size: 11px;
  color: rgba(255,255,255,0.45);
  text-align: right;
}
.hs-name {
  font-size: 13px;
  color: rgba(255,255,255,0.92);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hs-time {
  font-variant-numeric: tabular-nums;
  color: rgba(255,255,255,0.7);
}
/* New-entry row — highlights where the user just placed */
.hs-row--entry {
  background: rgba(255, 200, 80, 0.13);
  outline: 1px solid rgba(255, 200, 80, 0.35);
  grid-template-columns: 28px 1fr auto auto;
}
.hs-row--entry:hover { background: rgba(255, 200, 80, 0.18); }
.hs-row--entry .hs-rank { color: rgba(255, 200, 80, 0.95); font-weight: 700; }
.hs-input {
  all: unset;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 13px;
  color: #fff;
  background: rgba(255,255,255,0.1);
  border-radius: 6px;
  padding: 5px 9px;
  min-width: 0;
}
.hs-input::placeholder { color: rgba(255,255,255,0.4); }
.hs-input:focus { background: rgba(255,255,255,0.15); }
.hs-submit {
  all: unset;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #1a1a18;
  background: rgba(255, 200, 80, 0.95);
  padding: 7px 12px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s;
}
.hs-submit:hover { background: #ffd066; }
.hs-submit[disabled] { opacity: 0.45; cursor: not-allowed; }
.highscore-panel__error {
  margin: 10px 0 0;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  color: #ff8a8a;
  min-height: 14px;
}
.highscore-panel__error[aria-hidden="true"] { visibility: hidden; }
.highscore-list:empty::after {
  content: 'No scores yet — be the first.';
  display: block;
  padding: 16px 4px;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 12px;
  color: rgba(255,255,255,0.5);
  text-align: center;
}
.intro-stopwatch__highscores {
  margin-left: 10px;
}
@media (max-width: 480px) {
  .highscore-panel { width: calc(100vw - 24px); }
  .highscore-panel__inner { padding: 20px 18px; }
  .hs-row { font-size: 12px; padding: 8px; gap: 8px; }
  .hs-row--entry { grid-template-columns: 24px 1fr auto auto; }
}

/* Tagline that announces the user's placement above the list +
   form row inside the high-score panel. Sits between heading and
   list when present. */
.highscore-panel__tagline {
  margin: -8px 0 14px;
  font-family: 'Inter', sans-serif;
  font-size: 13.5px;
  line-height: 1.5;
  color: rgba(255,255,255,0.85);
}
.highscore-panel__tagline strong {
  color: rgba(255, 200, 80, 0.95);
  font-weight: 600;
}

/* --- source lines 8434-8504 --- */
/* ============================================================
   Collapsible "Design system" sub-card
   The system pill sits as a normal flex child of .pb-group, but
   when collapsed its height/opacity/margin animate to zero so the
   following Development pill slides up to fill the space. When
   revealed it animates back, pushing Development down — same
   transitions on enter and exit.
   ============================================================ */
.pb-bar--collapsible {
  /* The bar's coloured background, padding and border-radius live
     on .pb-bar already — we add a max-height/opacity envelope and
     the existing layout transitions take care of the rest. */
  max-height: 1200px;
  opacity: 1;
  transition: max-height 0.55s cubic-bezier(0.16, 1, 0.3, 1),
              opacity   0.35s ease,
              margin    0.55s cubic-bezier(0.16, 1, 0.3, 1),
              padding   0.55s cubic-bezier(0.16, 1, 0.3, 1),
              transform 0.55s cubic-bezier(0.16, 1, 0.3, 1);
  overflow: hidden;
}
.pb-bar--collapsible[aria-hidden="true"] {
  max-height: 0;
  opacity: 0;
  margin-top: 0;
  margin-bottom: 0;
  padding-top: 0;
  padding-bottom: 0;
  pointer-events: none;
  transform: translateY(-8px) scale(0.98);
}
@media (min-width: 769px) {
  .pb-bar--collapsible[aria-hidden="true"] {
    /* Match the zigzag's translateX so the entry slide reads as
       coming in from the same side it'll rest on. */
    transform: translateX(-15%) translateY(-8px) scale(0.98);
  }
}

/* Toggle button — sits at the bottom of the Design card body.
   Subtle outlined pill that picks up the parent card's text colour. */
.pb-bar__sub-toggle {
  all: unset;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 14px;
  padding: 8px 14px;
  border-radius: 100px;
  border: 1px solid currentColor;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0.85;
  transition: opacity 0.18s ease, background 0.18s ease, color 0.18s ease;
}
.pb-bar__sub-toggle:hover {
  opacity: 1;
  background: rgba(0,0,0,0.08);
}
.pb-bar--build .pb-bar__sub-toggle:hover,
.pb-bar--system .pb-bar__sub-toggle:hover { background: rgba(255,255,255,0.12); }
.pb-bar__sub-toggle-chev {
  transition: transform 0.3s ease;
}
.pb-bar__sub-toggle[aria-expanded="true"] .pb-bar__sub-toggle-chev {
  transform: rotate(180deg);
}

/* ========================================================================
   LAYER 17 · LATE OVERRIDES — ORDER-CRITICAL. These segments sit last in the shipped file on purpose; several rely on source order (and !important) to beat earlier rules. Do not hoist them.
   ======================================================================== */

/* --- source lines 8795-8974 --- */
/* ============================================================
   AU contact block — top-right twin of the .logo.
   Shown only on the homepage and only when the visitor's IP
   geolocates to Australia. Markup is identical on every cloned
   page (location keyword pages, etc.), but the JS gates display
   so it never appears outside `/`.
   ============================================================ */
.au-contact {
  position: fixed;
  top: 40px;
  /* Mirror the logo's left inset — pushed 15 vw further outward (toward
     the viewport's right edge) for the same outer-breathing-room. Same
     formula as .logo so the two stay symmetrical. */
  right: clamp(16px, 2vw, 36px);
  z-index: 9100;
  display: none;                       /* JS adds .is-visible for AU */
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: clamp(0.9rem, 1.15vw, 1.05rem);
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1.25;
  color: var(--text-2);
  text-align: right;
  user-select: none;
  transform-origin: top right;
  transition: transform 0.35s var(--ease-out);
}
.au-contact.is-visible { display: flex; }
.au-contact--scrolled  { transform: scale(0.9); }

.au-contact__link {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  white-space: nowrap;
  transition: color 0.18s ease;
}
.au-contact__link:hover { color: var(--text); }

@media (max-width: 699px) {
  /* #1 — more breathing room under the email row on mobile, plus
     a 16 px font floor so the hello / phone lines stay legible. */
  .au-contact      {
    top: 26px;
    right: 16px;
    gap: 14px;
    line-height: 1.3;
    font-size: 16px;
  }
  .au-contact--scrolled { transform: scale(0.85); }
}

/* ─────────────────────────────────────────────────────────
   MOBILE FIXES — multiple targeted overrides:
   #2 ensure H1 visible on first paint (Safari fallback).
   #3 H1 + pills lifted higher in the hero.
   #5 process-chips and white pills tightened up.
   #6 X / LinkedIn icons pinned top-right under the phone #.
   #7 project-card meta stacked Who → Summary → Services.
   ───────────────────────────────────────────────────────── */
@media (max-width: 699px) {
  /* #2 — JS adds .is-split to reveal the SplitType chars. On Safari
     iOS the splitter sometimes lags or fails until the user scrolls.
     Force visibility so the H1 paints even without the class. */
  .intro-giant { visibility: visible !important; }

  /* #3 — keep enough top breathing room so the H1 sits well below
     the top-right discovery-CTA + email/phone block (which stack to
     roughly 120 px on mobile). `max(22vh, 170px)` guarantees a 170 px
     floor on very short screens. */
  .intro-stage { padding-top: max(22vh, 170px) !important; }

  /* #5 — process picker chips sit ~24 px under the heading and
     align flush with the "M" of "More about process." (heading
     starts at viewport left + 28 px → so chips need margin-left 0
     and inherit the parent's column). Pills are forced to one
     line — "Product design and architecture" must not wrap. The
     companion `.process-hed { margin-bottom: 0 }` override below
     keeps the gap at the 24 px set here (otherwise the heading's
     existing margin-bottom from `.trusted-hed--plain` was adding
     extra space). */
  .process-hed { margin-bottom: 0 !important; }
  .process-chips {
    margin: 24px 16px 12px 0 !important;
    max-width: none !important;
  }
  .process-chips .intro-chip {
    white-space: nowrap !important;
    max-width: none !important;
    width: fit-content !important;
    /* Trim padding slightly so the longest label
       ("Product design and architecture") fits the 343 px column
       without overflowing the right edge. */
    padding: 11px 16px !important;
  }

  /* #6 — hide social icons entirely on mobile. The previous
     behaviour (pinning them under the au-contact phone line in the
     top-right) cluttered the limited screen real estate; users can
     still reach LinkedIn/X via the success-state copy in the
     contact form and via the AI menu. */
  .social-fixed {
    display: none !important;
    position: fixed !important;
    top: 96px !important;
    right: 16px !important;
    bottom: auto !important;
    left: auto !important;
    flex-direction: row !important;
    gap: 10px !important;
    z-index: 9100 !important;
  }

  /* #7 — project card meta stacks vertically. */
  .work-thumb__meta {
    display: flex !important;
    flex-direction: column !important;
    gap: 14px !important;
    padding: 0 16px 18px 0 !important;
  }
  .work-thumb__meta-row { min-width: 0 !important; }
}

/* "Copied" flash pill that briefly appears next to an au-contact link
   after a click. Confirms the address was placed on the clipboard even
   when the user's mailto:/tel: handler doesn't open. */
.au-contact__link { position: relative; }
.au-contact__flash {
  position: absolute;
  top: 50%;
  right: calc(100% + 8px);
  transform: translateY(-50%) translateX(4px);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
  background: #1A1A18;
  padding: 4px 8px;
  border-radius: 6px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s ease, transform 0.22s cubic-bezier(0.16, 1, 0.3, 1);
}
.au-contact__flash.is-visible {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
}

/* Send button shake — same animation as the robot-check label, so when
   a user clicks Send without ticking the checkbox both elements wobble
   together. Makes the failure mode impossible to miss. */
.form-submit--shake { animation: robot-shake 0.4s ease; }

/* Ask-AI periodic attention dance — same expand-to-show-label state as
   :hover, with a brief wiggle to draw the eye. JS adds .ask-ai-btn--dance
   every 25 s once the user has scrolled past the hero. */
.ask-ai-btn--dance {
  width: auto;
  padding-right: 18px;
  animation: ask-ai-wiggle 0.9s ease-in-out;
}
.ask-ai-btn--dance .ask-ai-btn__char {
  opacity: 1;
  transform: translateY(0);
  transition-delay: calc(var(--i, 0) * 24ms + 60ms);
}
@keyframes ask-ai-wiggle {
  0%, 100% { transform: translateY(-2px) rotate(0deg); }
  20%      { transform: translateY(-6px) rotate(-2.5deg); }
  40%      { transform: translateY(-3px) rotate( 2.5deg); }
  60%      { transform: translateY(-6px) rotate(-1.5deg); }
  80%      { transform: translateY(-2px) rotate( 1.5deg); }
}

/* --- source lines 9101-9145 --- */
/* ============================================================
   Homepage intro-giant (long phrase) — left-aligned, multi-line.
   Scoped via .intro-giant--multiline so location pages and any
   other .intro-giant uses keep the original single-line nowrap.
   ============================================================ */
.intro-giant.intro-giant--multiline {
  white-space: normal;
  text-align: left;
  /* Reduced 15 % from clamp(1.58rem, 6.19vw, 6.12rem). */
  font-size: clamp(1.343rem, 5.26vw, 5.2rem);
  line-height: 1.02;
  /* Pushed in 10vw from the left so the lockup sits in the right two-
     thirds of the viewport, leaving the left edge breathable. The
     `max(…, 170px)` floor guarantees enough clearance below the
     fixed top-left wordmark + top-right discovery
     pill stack on short laptops (MacBook Air etc.) where 12vh
     would otherwise resolve to <120 px and collide with them. */
  max-width: min(100%, calc(90vw - 28px));
  margin: max(170px, 18vh) 28px 0 10vw;
  padding: 0;
  /* Pills sit at z-index 500; the headline lives on top so it's never
     covered by an Eiffel beam or sun ray drifting behind. */
  position: relative;
  z-index: 700;
}
@media (max-width: 699px) {
  .intro-giant.intro-giant--multiline {
    /* Trimmed ~18 % from the original so the fifth intro chip
       ("AI automation") clears the floating bottom-nav on
       375 px phones. 10 % alone left it overlapping by 26 px.
       Was clamp(2.203rem, 12.11vw, 4.957rem). */
    font-size: clamp(1.807rem, 9.93vw, 4.065rem);
    /* Lifted ~20 % up from the original 80 px top margin so the
       AI automation chip clears the bottom nav on shorter
       phones (iPhone SE 375 × 667). */
    margin: -70px 16px 0;
    /* Keep words intact — no mid-word breaks. White-space normal
       still allows wrap at spaces, just never inside a word. */
    overflow-wrap: normal;
    word-break: keep-all;
    hyphens: none;
  }
}

/* --- source lines 9146-9648 --- */
/* ============================================================
   Intro chips — three big discipline filters below the headline.
   Click → relays to the matching .work-filter on the work-zoom toggle
   row (script.js wires this). Sits inside .intro-stage flow so it
   inherits the same 28 px left-edge alignment as the headline.
   ============================================================ */
.intro-chips {
  display: flex;
  flex-direction: column;
  align-items: flex-start;             /* left-aligned, content-width pills */
  gap: 10px;
  /* Same 10vw push as the headline so the chips sit in the same column. */
  margin: 44px 28px 0 10vw;
  max-width: min(100%, calc(90vw - 28px));
  position: relative;
  z-index: 700;                        /* above pills (z 500) */
}
.intro-chip { text-transform: none; }
.intro-chip::first-letter { text-transform: uppercase; }
.intro-chip {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.25;
  color: #1A1A18;
  background: #ffffff;
  border: none;
  border-radius: 100px;
  padding: 10px 12px 10px 22px;
  text-align: left;
  white-space: normal;                 /* allow wrap if a phrase is long */
  cursor: pointer;
  max-width: 100%;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease, transform 0.18s ease;
}
/* White circle + black down-arrow — always visible by default. */
.intro-chip::after {
  content: '';
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #ffffff
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231A1A18' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>")
    center / 12px no-repeat;
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.intro-chip:hover {
  background: #F4F3EE;                 /* cream — same as the body/intro bg */
  transform: translateY(-1px);
}
.intro-chip:hover::after {
  transform: translateY(1px);          /* gentle nudge on hover */
}
/* No selected state — chips stay white regardless of which filter
   is currently active in the work-zoom below. */
.intro-chip.is-active {
  background: #ffffff;
  color: #1A1A18;
}

/* ─────────────────────────────────────────────────────────
   Section pills — fixed left-rail extension. Appears once the
   work-zoom dot rail ends; pills stagger in from the right.
   Active section pill is black-on-white; others are white.
   ───────────────────────────────────────────────────────── */
.section-pills {
  position: fixed;
  /* Default: vertically centred on viewport. */
  top: 50%;
  left: 24px;
  transform: translateY(-50%);
  /* Sit above every page section (work-zoom sticky frame uses
     z-index up to ~100 in some states) so the floating Work filter
     dropdown can never get covered by content behind it. */
  z-index: 200;
  pointer-events: none;
  transition: top 0.25s ease, transform 0.25s ease;
}
/* When the Work pill is expanded (dots + filter visible), the list
   gets tall — anchor it 40 px below the logo so it can't push up
   over it. On very short viewports the tail bleeds off the bottom
   (load-bearing overflow). overflow stays visible so the Work
   filter dropdown — which flies to the right of the pill — isn't
   clipped. */
.section-pills.is-work-expanded {
  top: 120px;
  transform: none;
  max-height: none;
  overflow: visible;
}
.section-pills.is-work-expanded .section-pills__list {
  padding-bottom: 32px;
}

/* Condense on tight viewport heights so the expanded Work list
   still fits as much as possible before it has to bleed off the
   bottom of the screen. */
@media (max-height: 820px) {
  .section-pills__list { gap: 6px; }
  .section-pills__btn  { padding: 6px 14px; font-size: 12px; }
  .section-pills__dots { gap: 4px; margin-top: 6px; }
  .section-pills__dot { width: 5px; height: 5px; }
  .section-pills__dot-label { font-size: 10px; }
}
@media (max-height: 680px) {
  .section-pills__list { gap: 4px; }
  .section-pills__btn  { padding: 5px 12px; font-size: 11.5px; }
  .section-pills__dots { gap: 3px; }
}
.section-pills__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.section-pills__item {
  opacity: 0;
  transform: translateX(24px);
  pointer-events: none;
}
.section-pills.is-visible .section-pills__item {
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
  animation: section-pill-in 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
  animation-delay: calc(var(--idx, 0) * 60ms);
}
@keyframes section-pill-in {
  from { opacity: 0; transform: translateX(24px); }
  to   { opacity: 1; transform: translateX(0);   }
}
.section-pills__btn {
  display: inline-flex;
  align-items: center;
  /* Match the page background so the pills don't dominate; on hover
     they flip to white. Active section pill stays black-on-white. */
  background: #F4F3EE;
  color: #1A1A18;
  border: none;
  border-radius: 999px;
  padding: 8px 16px;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.2;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: none;
  transition: background 0.2s ease, color 0.2s ease, transform 0.2s ease;
}
.section-pills__btn:hover {
  transform: translateY(-1px);
  background: #ffffff;
}
.section-pills__btn.is-active {
  background: #111111;
  color: #ffffff;
}

/* Work pill is itself a dropdown — clicking it toggles a menu that
   floats to the right of the pill with the filter options. The pill
   shows a label + down-chevron; the chevron flips when the menu is
   open. The label updates to "Work — Product / UX / Brand" when a
   filter is picked. */
.section-pills__item[data-target="work-zoom"] { position: relative; }
.section-pills__btn[data-target="work-zoom"] {
  display: inline-flex !important;
  align-items: center !important;
  gap: 6px !important;
}
.section-pills__btn-chev {
  flex-shrink: 0;
  opacity: 0.7;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.section-pills__item.is-open .section-pills__btn-chev {
  transform: rotate(180deg);
  opacity: 1;
}
.section-pills__btn-label {
  white-space: nowrap;
}
.section-pills__filter-menu {
  list-style: none;
  margin: 0;
  padding: 6px;
  background: #ffffff;
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.12);
  display: none;
  position: absolute;
  top: 0;
  left: calc(100% + 8px);
  min-width: 130px;
  z-index: 9999;
}
.section-pills__item.is-open .section-pills__filter-menu { display: block; }
.section-pills__filter-menu li { margin: 0; padding: 0; }
.section-pills__filter-menu button {
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  padding: 8px 12px;
  border-radius: 8px;
  font-family: inherit;
  font-size: 12px;
  color: #1A1A18;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.section-pills__filter-menu button:hover { background: #F4F3EE; }
.section-pills__filter-menu button.is-active { background: #111; color: #fff; }

/* Per-project dot list — shown only while the user is in work-zoom. */
.section-pills__dots {
  list-style: none;
  /* Indent so the dot column aligns under the Work pill's text.
     A few px of left padding gives the active scaled dot room
     so it isn't clipped against the parent's edge. Extra top
     and bottom margin gives the rail breathing room from the
     Work pill above and the next section pill below. */
  margin: 18px 0 18px 18px;
  padding: 0 0 0 6px;
  display: none;
  flex-direction: column;
  gap: 6px;
  max-height: 50vh;
  overflow-y: auto;
  scrollbar-width: none;
}
.section-pills__dots::-webkit-scrollbar { display: none; }
.section-pills.is-work-expanded .section-pills__item[data-target="work-zoom"] .section-pills__dots {
  display: flex;
}
.section-pills__dot-item {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  color: var(--text-2);
}
.section-pills__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
  opacity: 0.45;
  transition: opacity 0.2s ease, background 0.2s ease, transform 0.2s ease;
}
.section-pills__dot-label {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 11px;
  letter-spacing: -0.005em;
  white-space: nowrap;
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity 0.2s ease, transform 0.2s ease, color 0.2s ease;
}
/* Hover preview — show the title next to the dot. */
.section-pills__dot-item:hover .section-pills__dot {
  opacity: 1;
}
.section-pills__dot-item:hover .section-pills__dot-label {
  opacity: 0.6;
  transform: translateX(0);
  color: var(--text);
}
/* Active state — dot goes solid black and project title appears
   beside it (no hover needed). */
.section-pills__dot-item.is-active .section-pills__dot {
  background: #111;
  opacity: 1;
  transform: scale(1.25);
}
.section-pills__dot-item.is-active .section-pills__dot-label {
  opacity: 1;
  transform: translateX(0);
  color: #111;
  font-weight: 500;
}

/* "More work" pill under the last dot — small white pill with
   matching type to the section pills. */
.section-pills__more {
  margin-top: 10px;
  list-style: none;
}
.section-pills__more button {
  background: #F4F3EE;
  color: #1A1A18;
  border: none;
  border-radius: 999px;
  padding: 6px 14px;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: background 0.2s ease;
}
.section-pills__more button:hover { background: #ffffff; }

/* Hide the old in-section rail dots and filter dropdown — the
   section-pills rail now owns that UI. */
body .work-rail-dots,
body .work-filter-dd {
  display: none !important;
}

@media (max-width: 768px) {
  .section-pills { display: none; }
}

/* "Coming soon" chip variant — hides the down-arrow badge and shows
   a small tooltip on hover from the data-coming-soon attribute.
   Right padding is bumped to mirror the left padding (22 px) since
   there's no arrow badge consuming the right-edge gap any more. */
.intro-chip--coming-soon {
  cursor: default;
  padding-right: 22px;
}
.intro-chip--coming-soon::after {
  display: none !important;
}
.intro-chip--coming-soon::before {
  content: attr(data-coming-soon);
  position: absolute;
  top: -34px;
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: #1A1A18;
  color: #fff;
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.02em;
  padding: 6px 12px;
  border-radius: 999px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.intro-chip--coming-soon:hover::before {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.intro-chip { position: relative; }   /* anchor for the absolute tooltip */

/* Permanent top-right discovery-call CTA — sits ABOVE the email +
   phone block, same small pill size as the previous scroll-CTA but
   always visible (no scroll trigger). */
.discovery-cta {
  position: fixed;
  top: 34px;          /* above the email/phone block (au-contact is at top: 70) */
  right: clamp(16px, 2vw, 36px);
  z-index: 9100;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: #111111;
  color: #ffffff;
  border: none;
  border-radius: 999px;
  padding: 9px 18px;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.2s ease, transform 0.18s ease;
}
.discovery-cta:hover {
  background: #000000;
  transform: translateY(-1px);
}
/* Push the email/phone block down to make room for the new CTA. */
.au-contact { top: 78px !important; }
@media (max-width: 699px) {
  /* Removed on mobile — the "Book free strategy session" pill in
     the top-right corner crowded the hello / phone block and
     read as oversized chrome on small screens. The CTA is still
     present in the page footer and via the hero intro chips. */
  .discovery-cta { display: none !important; }
  /* au-contact reclaims the top slot now that the CTA is gone. */
  .au-contact { top: 26px !important; }
}

/* Calendly lightbox — opens from the hero CTA pill. */
.calendly-lightbox {
  position: fixed;
  inset: 0;
  display: none;
  z-index: 10000;
}
.calendly-lightbox.is-open { display: block; }
.calendly-lightbox__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(17, 17, 17, 0.55);
  backdrop-filter: blur(4px);
  cursor: pointer;
}
.calendly-lightbox__card {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(1000px, 92vw);
  max-height: 92vh;
  background: #ffffff;
  border-radius: 18px;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.35);
  overflow: hidden;
  padding: 56px 12px 12px;
  box-sizing: border-box;
  animation: calendly-pop 0.25s cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes calendly-pop {
  from { opacity: 0; transform: translate(-50%, -48%) scale(0.97); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
.calendly-lightbox__close {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: #F4F3EE;
  color: #1A1A18;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
  transition: background 0.18s ease;
}
.calendly-lightbox__close:hover { background: #e8e6df; }
.calendly-lightbox .calendly-inline-widget {
  height: calc(92vh - 70px) !important;
  max-height: 800px;
}

/* CTA pill variant — same shape/size as the other intro chips, but
   black bg with white text. Arrow badge inverted to match. */
.intro-chip--cta {
  background: #111111 !important;
  color: #ffffff !important;
  text-decoration: none !important;
}
.intro-chip--cta:hover {
  background: #000000 !important;
  color: #ffffff !important;
}
/* Invert the down-arrow badge so it reads on the black pill. */
.intro-chip--cta::after {
  background: #ffffff
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231A1A18' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>")
    center / 12px no-repeat;
}
/* Hide it from the cloned .process-chips picker further down the page. */
.process-chips .intro-chip--cta { display: none !important; }

/* Hide the "coming soon" pills from the cloned process-chips
   picker further down the page. */
.process-chips .intro-chip--coming-soon {
  display: none !important;
}
@media (max-width: 699px) {
  .intro-chips { margin: 16px 16px 0; gap: 8px; }
  /* Mobile: hide the supporting lede + the top-right contact strip
     so the 5 intro chips clear the floating bottom-nav on shorter
     phones. Both still render on desktop / tablet. */
  .intro-supporting { display: none !important; }
  .au-contact, #au-contact { display: none !important; }
  /* Lifted intro-chip font from 13 px to 16 px so every pill on the
     home header reads at body-copy size. Padding bumped to keep the
     pill height proportional. */
  .intro-chip  { font-size: 16px; padding: 11px 18px; line-height: 1.3; }
  /* Industry sub-pills inherit the unified .faq-more-btn-style
     pill defined above (Inter sans-serif, 0.9rem, 100 px radius). */
}

/* Pill-game indicator — when the user clicks the toolbar Game icon, the
   body picks up data-pill-game="1" and the toolbar Game button shows as
   active. Used to skip the chrome interactions that don't apply mid-game. */
body[data-pill-game="1"] .nav-game-btn { background: var(--accent, #FF7A00); color: #fff; }

/* --- source lines 9649-9786 --- */
/* ============================================================
   Homepage folio restyle — browser-frame cards in a list view
   that creeps above the fold so visitors see work as they land.
   ============================================================ */

/* Hide the "Helping businesses ship better digital products" line
   — the folio reads cleaner without the meta heading on top. */
.work-zoom__caption,
.work-panel .about-title {
  display: none;
}

/* Pull the intro-stage so the first work card peeks up above the fold. */
.intro-stage {
  height: 88vh;
}

/* Browser-frame mockup styling for every .work-thumb.
   Outer: rounded white card (title bar built in via padding-top).
   Title sits top-left, three dots top-right, image fills below. */
.work-thumb {
  position: relative;
  display: block;
  background: #fff;
  border-radius: 18px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  /* Top: title bar; sides + bottom: white frame around the media so the
     image/video sits inside the "browser window" rather than bleeding
     to the edge. */
  padding: 52px 14px 14px;
  box-shadow: 0 1px 0 rgba(0,0,0,0.04);
  transition: transform 0.22s var(--ease-out), box-shadow 0.22s var(--ease-out);
}
.work-thumb:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 28px rgba(0,0,0,0.08);
}

/* Project title — top-left of the browser bar, Helvetica Neue + caps */
.work-thumb__label {
  position: absolute;
  top: 18px;
  left: 22px;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: #1A1A18;
  text-transform: uppercase;
  z-index: 2;
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-radius: 0;
  padding: 0;
  margin: 0;
}

/* Category — small "/App" tag next to the title */
.work-thumb__cat {
  position: absolute;
  top: 20px;
  right: 56px;               /* leave room for the dots */
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11.5px;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: #9C9990;
  z-index: 2;
  background: none;
  padding: 0;
  margin: 0;
  text-transform: lowercase;
}
.work-thumb__cat::before { content: '/'; margin-right: 1px; }

/* Three-dot menu — top right of the browser bar */
.work-thumb::after {
  content: '\22EF';           /* ⋯ */
  position: absolute;
  top: 14px;
  right: 22px;
  color: #C4C1B8;
  font-size: 22px;
  letter-spacing: 2px;
  font-weight: 600;
  z-index: 2;
}

/* Image / video sit inside the white browser-window frame. Rounded
   corners and width 100% of the padded content area so the white
   shows all the way around. Override the legacy absolute-positioned
   video overlay so it flows in-place inside the padded frame. */
.work-thumb img,
.work-thumb video,
.work-thumb .work-thumb__video {
  position: static;
  inset: auto;
  width: 100%;
  height: auto;
  max-height: none;
  aspect-ratio: 900 / 630;
  display: block;
  border-radius: 10px;
  background: #F4F3EE;
  object-fit: cover;
  opacity: 1;
}
/* When the autoplay video kicks in, stack it on top of the static img
   but keep it inside the same padded content box, not the full card. */
.work-thumb {
  /* Make the padded content area the positioning context. */
}
.work-thumb .work-thumb__video {
  position: absolute;
  top: 52px;
  left: 14px;
  right: 14px;
  bottom: auto;
  /* For replaced elements (video/img), width:auto means intrinsic-size,
     not "stretch between left+right". Force the width with calc so it
     actually matches the static <img>'s padded box. */
  width: calc(100% - 28px);
  height: auto;
  aspect-ratio: 900 / 630;
  /* Zoom video so its height fills the box — width gets cropped if the
     natural aspect is wider than 900/630. No letterbox gaps. */
  object-fit: cover;
  object-position: center;
  border-radius: 10px;
  background: #F4F3EE;
  opacity: 0;
  z-index: 1;
}
.work-thumb .work-thumb__video.is-playing { opacity: 1; }

/* --- source lines 9787-10387 --- */
/* ============================================================
   ROWS VIEW — list layout with sticky left rail of dots + filter.
   Cards become full-width browser-frame rows containing the
   thumbnail, project metadata and a gallery strip on the right.
   ============================================================ */
/* Grid layout — rail in column 1 (sticky), grid-host in column 2.
   The rail only enters the viewport when the user scrolls into the
   folio section, then sticks at top:110px under the logo. */
.work-zoom[data-view="rows"] {
  display: grid !important;
  grid-template-columns: 248px minmax(0, 1fr);
  padding: 200px 0 0 0 !important;
  margin: 0 !important;
  max-width: none !important;
}

/* Sticky left rail with filter + dots */
.work-zoom[data-view="rows"] .work-zoom__sticky {
  position: sticky !important;
  top: 110px !important;
  left: auto !important;
  align-self: start;
  width: 220px !important;
  height: auto !important;
  padding: 0 0 0 28px !important;
  margin: 0 !important;
  background: transparent !important;
  z-index: 50 !important;
  display: block !important;
  overflow: visible !important;
}
.work-filter-dd,
.work-filter-dd__menu {
  z-index: 200 !important;
}
.work-zoom[data-view="rows"] .work-zoom__controls {
  display: flex !important;
  flex-direction: column;
  align-items: flex-start;
  gap: 28px;
  padding: 0;
  background: transparent;
  opacity: 1 !important;       /* controls always visible in rows view */
  overflow: visible !important;
}

/* Hide the original filter button row in rows view — replaced by the
   dropdown widget below (.work-filter-dd). */
.work-zoom[data-view="rows"] .work-filters[data-target="zoom"] {
  display: none !important;
}

/* New filter dropdown widget — JS injects this into the rail above
   the project dots. */
.work-filter-dd {
  position: relative;
  width: 168px;
  height: 44px;
  background: #fff;
  border: 1px solid rgba(26,26,24,0.08);
  border-radius: 999px;
  padding: 0 6px 0 22px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  cursor: pointer;
  user-select: none;
}
.work-filter-dd__label {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.25;
  text-transform: none;
  color: #1A1A18;
}
.work-filter-dd__toggle {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: #1A1A18;
  color: #fff;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: transform 0.25s var(--ease-out);
}
.work-filter-dd__toggle svg { width: 14px; height: 14px; }
.work-filter-dd.is-open .work-filter-dd__toggle { transform: rotate(180deg); }

/* Dropdown menu — appears below the pill, absolute-positioned so it
   overlays the dots rail. */
.work-filter-dd__menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  width: 100%;
  background: #fff;
  border: 1px solid rgba(26,26,24,0.08);
  border-radius: 14px;
  padding: 6px;
  box-shadow: 0 12px 28px rgba(0,0,0,0.10);
  display: none;
  flex-direction: column;
  gap: 2px;
  z-index: 30;
}
.work-filter-dd.is-open .work-filter-dd__menu { display: flex; }
.work-filter-dd__menu button {
  width: 100%;
  text-align: left;
  padding: 10px 14px;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.25;
  text-transform: none;
  background: transparent;
  border: none;
  color: #1A1A18;
  cursor: pointer;
  border-radius: 100px;
}
.work-filter-dd__menu button:hover,
.work-filter-dd__menu button.is-active {
  background: #1A1A18;
  color: #fff;
}

/* Hide the view-toggle in rows view — rail is the navigation */
.work-zoom[data-view="rows"] .work-view-toggle[data-target="zoom"] { display: none !important; }

/* Dot navigation column */
.work-rail-dots {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 0 12px;
  list-style: none;
  margin: 0;
}
.work-rail-dots__item {
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  color: var(--text-2);
  transition: color 0.2s ease;
}
.work-rail-dots__item.is-hidden { display: none; }
.work-rail-dots__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(26,26,24,0.25);
  flex-shrink: 0;
  transition: background 0.2s ease, transform 0.2s ease;
}
.work-rail-dots__label {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: transparent;
  white-space: nowrap;
  transition: color 0.2s ease;
}
.work-rail-dots__item:hover .work-rail-dots__label,
.work-rail-dots__item.is-active .work-rail-dots__label {
  color: var(--text);
}
.work-rail-dots__item:hover .work-rail-dots__dot,
.work-rail-dots__item.is-active .work-rail-dots__dot {
  background: var(--text);
  transform: scale(1.4);
}

/* Grid host — sits in the second grid column. No internal padding so
   the cards inside bleed to the viewport's right edge. */
.work-zoom[data-view="rows"] .work-zoom__grid-host {
  width: 100% !important;
  max-width: none !important;
  /* Push 100 px right so all work-thumbs shift inward from the left
     viewport edge. */
  padding: 0 0 0 100px !important;
  margin: 0 !important;
  min-width: 0;
  box-sizing: border-box;
}
.work-zoom[data-view="rows"] .work-zoom__grid-host .work-panel__grid {
  margin: 0 !important;
  padding: 0 !important;
  width: 100% !important;
  max-width: none !important;
  justify-content: stretch !important;
  grid-template-columns: 1fr !important;     /* in case display:grid wins */
}
.work-zoom[data-view="rows"] .work-panel__grid {
  display: flex;
  flex-direction: column;
  gap: 128px;
  max-width: 100%;
  margin: 0;
  padding: 0;
}

/* Each project row — wide browser-frame card.
   Layout: title bar at top, then metadata strip (Who / Summary /
   Services) inside the white frame, then a masonry image row that
   bleeds past the viewport's right edge. */
.work-zoom[data-view="rows"] .work-thumb {
  display: block !important;
  width: 100% !important;
  max-width: none !important;
  padding: 56px 0 0 22px !important;
  margin: 0 !important;
  border-radius: 14px 0 0 14px !important;
  overflow: visible !important;
  position: relative;
  box-shadow: none !important;
}
/* Re-assert hidden filtered thumbs in rows view (must beat the
   display:block !important above). Covers BOTH the category
   filter (work-thumb--hidden) and the industry sub-filter
   (work-thumb--industry-hidden). */
.work-zoom[data-view="rows"] .work-thumb.work-thumb--hidden,
.work-zoom[data-view="rows"] .work-thumb.work-thumb--industry-hidden {
  display: none !important;
}
.work-zoom[data-view="rows"] .work-thumb:hover {
  box-shadow: none !important;
  transform: none !important;
}

/* Top metadata strip — Who / Summary / Services side-by-side, with
   right padding for the paired scroll-arrow buttons (44 + 12 + 44 + 28). */
.work-thumb__meta {
  display: grid;
  grid-template-columns: minmax(180px, 1fr) minmax(0, 1.4fr) minmax(180px, 1fr);
  gap: 24px;
  padding: 0 150px 22px 0;
  border-bottom: 1px solid rgba(26,26,24,0.06);
  margin-bottom: 18px;
}
.work-thumb__meta-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.work-thumb__meta-label {
  font-family: 'IBM Plex Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-2);
}
.work-thumb__meta-value {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.45;
  color: var(--text);
}
.work-thumb__pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.work-thumb__pill {
  display: inline-block;
  padding: 6px 12px;
  border-radius: 100px;
  border: 1px solid rgba(26,26,24,0.18);
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--text);
  background: transparent;
}

/* Masonry image strip — horizontal scroller that stays inside the
   white card. A right-arrow button (.work-thumb__scroll-right) sits
   floating on the right edge to advance the strip. */
.work-thumb__media {
  display: flex;
  gap: 14px;
  align-items: stretch;
  padding: 0 22px 22px 0;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
}
.work-thumb__media::-webkit-scrollbar { display: none; }

/* Paired scroll arrows — live in the white header area to the right
   of the Services column. Left arrow appears (fades in) once the
   strip has been scrolled away from its start. */
.work-thumb__scroll-left,
.work-thumb__scroll-right {
  position: absolute;
  top: 60px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: #1A1A18;
  color: #fff;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 5;
  transition: transform 0.2s ease, background 0.2s ease, opacity 0.2s ease;
}
.work-thumb__scroll-right { right: 28px; }
.work-thumb__scroll-left  { right: 84px; }    /* 28 + 44 + 12 gap */
.work-thumb__scroll-left:hover,
.work-thumb__scroll-right:hover { transform: scale(1.06); background: #2A2A28; }
.work-thumb__scroll-left svg,
.work-thumb__scroll-right svg { width: 18px; height: 18px; }
/* Hidden until the strip has been scrolled right at least once */
.work-thumb__scroll-left {
  opacity: 0;
  pointer-events: none;
}
.work-thumb.is-scrolled .work-thumb__scroll-left {
  opacity: 1;
  pointer-events: auto;
}
.work-zoom[data-view="rows"] .work-thumb > img,
.work-zoom[data-view="rows"] .work-thumb > .work-thumb__video,
.work-thumb__media > img,
.work-thumb__media > .work-thumb__video {
  position: static !important;
  inset: auto !important;
  top: auto !important;
  left: auto !important;
  right: auto !important;
  bottom: auto !important;
  margin: 0;
  height: 540px;
  width: auto;
  aspect-ratio: 900 / 630;
  border-radius: 10px;
  background: #F4F3EE;
  object-fit: cover;
  flex-shrink: 0;
}
.work-thumb__media > .work-thumb__video {
  height: 486px !important;
  width: auto !important;
  /* Use the image's intrinsic aspect — no cropping. */
  object-fit: contain !important;
  aspect-ratio: auto !important;
}
/* Supporting gallery shots — fill the row height (486 px); width
   stays at the image's natural aspect ratio (no cropping). */
.work-thumb__media .work-thumb__gallery-img,
.work-thumb__media > img {
  height: 486px !important;
  width: auto !important;
  max-width: none !important;
  min-width: 0 !important;
  /* Remove the inherited fixed aspect-ratio so each image is sized
     by its own intrinsic width × height. */
  aspect-ratio: auto !important;
  border-radius: 10px;
  object-fit: contain !important;
  background: #F4F3EE;
  flex-shrink: 0;
  align-self: flex-start;   /* defeat parent's align-items: stretch */
}
@media (max-width: 980px) {
  /* Mobile/tablet minimum 500 px image height per user direction —
     width stays natural (cropped/uncropped by aspect, no force
     fit). Was 320 px → 220 px which was undersizing the strip
     and squashing each image. */
  .work-thumb__media .work-thumb__gallery-img,
  .work-thumb__media > img,
  .work-thumb__media > .work-thumb__video {
    height: 500px !important;
    width: auto !important;
    max-width: none !important;
    min-width: 0 !important;
    aspect-ratio: auto !important;
  }
}

/* ────────────────────────────────────────────────────────────────
   Mobile-only collapsed project view — show just the title +
   image strip + expand toggle. Clicking the toggle reveals the
   Who / Summary / Services strip in place.
   ──────────────────────────────────────────────────────────── */
.work-thumb__expand {
  display: none;             /* shown on mobile via media query */
}
@media (max-width: 699px) {
  /* Collapse the meta strip by default; toggle reveals it. */
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__meta {
    display: none !important;
  }
  .work-zoom[data-view="rows"] .work-thumb.is-meta-open .work-thumb__meta {
    display: flex !important;
    flex-direction: column !important;
    gap: 14px !important;
    /* Left padding 18 px lines the meta rows up with the title label
       (which is `position: absolute; left: 22px` from the card edge
       — the card itself now has 4 px inner padding-left, so 18 px
       brings the WHO / SUMMARY / SERVICES copy flush with the H1). */
    padding: 0 16px 18px 18px !important;
    margin-top: 14px;
  }
  /* Hide the legacy "⋯" three-dot ellipsis pseudo-element that
     sat in the top-right of every card — visually cluttered the
     header and crowded the chevron. The expand toggle below
     reclaims that exact slot. */
  .work-zoom[data-view="rows"] .work-thumb::after {
    display: none !important;
    content: none !important;
  }
  /* Expand toggle — sits in the top-right corner where the ellipsis
     used to be. Aligned with the title row instead of below it. */
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__expand {
    display: inline-flex;
    position: absolute;
    top: 14px;
    right: 16px;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    align-items: center;
    justify-content: center;
    background: #ffffff;
    color: #1A1A18;
    border: 1.5px solid rgba(26,26,24,0.18);
    cursor: pointer;
    transition: transform 0.2s ease, background 0.2s ease;
    z-index: 6;
  }
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__expand svg {
    width: 12px;
    height: 12px;
    transition: transform 0.2s ease;
  }
  .work-zoom[data-view="rows"] .work-thumb.is-meta-open .work-thumb__expand svg {
    transform: rotate(180deg);
  }
  /* Hide the desktop right-edge scroll arrows on mobile — the
     image strip is swipeable and the arrows crowd the expand
     toggle. */
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__scroll-left,
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__scroll-right {
    display: none !important;
  }

  /* Project cards spaced 32 px apart — was 128 px on desktop,
     which felt cavernous on a phone. */
  .work-zoom[data-view="rows"] .work-panel__grid {
    gap: 32px !important;
  }

  /* Whole card behaves as the expand trigger — gives the user a
     forgiving touch target instead of forcing them to hit the
     small chevron precisely. */
  .work-zoom[data-view="rows"] .work-thumb {
    cursor: pointer;
  }

  /* ── Centred floating card ──
     Desktop intent has each project bleed off the right edge
     (border-radius: 14px 0 0 14px; padding: 56px 0 0 22px). On
     mobile the user wants the white card to sit floating with
     equal gutters left + right and the image grid inside also
     symmetric. */
  .work-zoom[data-view="rows"] .work-thumb {
    /* Symmetric horizontal padding so the title bar + meta
       strip + image grid all sit centred inside the card. Inner
       horizontal padding dropped 16 → 4 px so the screenshot fills
       more of the card width (images were cropping in too tight). */
    padding: 56px 4px 0 4px !important;
    /* `margin: 0 auto` + an explicit max-width gives a perfectly
       centred card regardless of what padding the grid host or
       its parent has applied — fixes the off-centre bug seen on
       iPhone 14 Pro Max Chrome inspector. */
    margin: 0 auto !important;
    width: calc(100vw - 32px) !important;
    max-width: calc(100vw - 32px) !important;
    /* Round all four corners now that the card doesn't bleed. */
    border-radius: 14px !important;
    box-sizing: border-box !important;
  }
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__media {
    /* Image grid sits in the same column as the meta — equal
       padding left + right inside the card. */
    padding: 0 0 18px 0 !important;
  }
  .work-zoom[data-view="rows"] .work-thumb.is-meta-open .work-thumb__meta {
    /* Left padding 18 px lines the meta rows up with the title
       label (`position: absolute; left: 22px` from the card edge,
       which now has 4 px inner padding-left — 4 + 18 = 22). */
    padding: 0 16px 18px 18px !important;
  }
}

/* Stacked mobile fallback */
@media (max-width: 980px) {
  .work-zoom[data-view="rows"] {
    grid-template-columns: 1fr;
    gap: 20px;
  }
  .work-zoom[data-view="rows"] .work-zoom__sticky {
    position: static !important;
    width: auto !important;
    padding: 0 16px !important;
    margin: 0 0 24px !important;
  }
  .work-zoom[data-view="rows"] .work-filters[data-target="zoom"] {
    flex-direction: row;
    flex-wrap: wrap;
  }
  .work-zoom[data-view="rows"] .work-filters[data-target="zoom"] button { width: auto; }
  .work-rail-dots { display: none; }
  .work-zoom[data-view="rows"] .work-thumb {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
  }
  .work-zoom[data-view="rows"] .work-thumb > img,
  .work-zoom[data-view="rows"] .work-thumb > .work-thumb__video {
    width: 100%;
  }
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__video { width: 100% !important; }
  .work-thumb__gallery { overflow-x: auto; padding-bottom: 4px; }
}

/* Tiles view — force 2 columns regardless of the legacy 3-col default */
.work-zoom[data-view="tiles"] .work-panel__grid,
.work-zoom[data-view="tiles"] .work-panel__grid--tiles {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
  max-width: 1300px;
  margin: 0 auto;
  padding: 0 28px;
}
@media (max-width: 699px) {
  /* Keep the rows-view card design (title, hero image, WHO / SUMMARY
     / SERVICES meta) but show only ONE image per project — hide the
     B/C gallery variants the rows-view JS lays out alongside A, then
     stretch the first variant to fill the entire media wrapper. */
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__media {
    display: block !important;
    grid-template-columns: none !important;
  }
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__gallery-img {
    width: 100% !important;
    height: 100% !important;
    object-fit: contain !important;
    object-position: center !important;
    display: block !important;
  }
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__gallery-img:not(:first-of-type) {
    display: none !important;
  }
  /* Wilsons Advisory: the A image (the chart) leaves dead space on
     the right side of the card. Show the B image instead (phone
     mockup) which fills the cell properly. */
  .work-zoom[data-view="rows"] .work-thumb[data-slug="wilsons"] .work-thumb__gallery-img:first-of-type {
    display: none !important;
  }
  .work-zoom[data-view="rows"] .work-thumb[data-slug="wilsons"] .work-thumb__gallery-img:nth-of-type(2) {
    display: block !important;
  }
  /* Video thumbs (Tab, Johnson, Uncle Tobys, etc.) — the inline
     <video class="work-thumb__video"> is the hero asset; the
     static gallery image is just a fallback poster. Hide ALL
     gallery images when a video is present so only the video
     plays in the card. */
  .work-zoom[data-view="rows"] .work-thumb[data-video] .work-thumb__gallery-img {
    display: none !important;
  }
  .work-zoom[data-view="rows"] .work-thumb[data-video] .work-thumb__video {
    width: 100% !important;
    height: 100% !important;
    /* Videos are wider than the card cell, so fill by HEIGHT first
       and let the sides crop instead of leaving letterbox bars. */
    object-fit: cover !important;
    object-position: center !important;
    display: block !important;
  }
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__scroll-left,
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__scroll-right {
    display: none !important;
  }
}

/* --- source lines 10388-11079 --- */
/* ============================================================
   ASK-AI BUTTON — top-right corner override (LAST so it wins
   against the earlier .ask-ai-btn rule).
   ============================================================ */
/* Ask-AI sits at the BOTTOM, immediately to the right of the
   bottom-nav black footer (matches the original .ask-ai-btn rule
   at line ~2492). */
.ask-ai-btn {
  position: fixed !important;
  top: auto !important;
  right: auto !important;
  left: calc(50% + var(--nav-half-width, 200px) + 14px) !important;
  bottom: max(28px, calc(16px + env(safe-area-inset-bottom))) !important;
  z-index: 9200 !important;
  flex-direction: row;
  justify-content: flex-start;
}
.ask-ai-btn .ask-ai-btn__icon {
  margin-left: calc((var(--nav-height, 44px) - 18px) / 2);
  margin-right: 0;
}
.ask-ai-btn:hover {
  padding-left: 0;
  padding-right: 22px;
  gap: 8px;
}
.ask-ai-btn:hover .ask-ai-btn__label {
  padding-left: 6px;
}

/* Contact returns to the top-right edge — AI sits directly under it. */
.au-contact {
  right: clamp(16px, 2vw, 36px) !important;
}
@media (max-width: 699px) {
  .au-contact {
    right: clamp(12px, 3vw, 24px) !important;
  }
}

/* ────────────────────────────────────────────────────────────────
   MOBILE-ONLY TWEAKS (matches the requests from 2026-06-02)
   ──────────────────────────────────────────────────────────────── */
/* Desktop default — hide the mobile-only chip label. */
.chip-text-mobile { display: none; }

@media (max-width: 699px) {
  /* #1  Chip text swap — "Product design and architecture" on mobile. */
  .chip-text-desktop { display: none; }
  .chip-text-mobile  { display: inline; }

  /* #2  Recently-completed project cards — grid host sits flush
     edge-to-edge on mobile so the .work-thumb inside can take the
     symmetric 16 px margin both sides and centre itself perfectly.
     Was margin-left: 12px (asymmetric, pushed cards off-centre to
     the left on iPhone 14 Pro Max Chrome inspector). */
  .work-panel__grid,
  .work-zoom[data-view="rows"] .work-zoom__grid-host {
    margin: 0 !important;
    padding: 0 !important;
  }
  /* Banner-to-first-thumb visible gap pinned to 40 px. The first
     .work-thumb carries a permanent `transform: scale(.94)
     translateY(9.4px)` (floating-card effect) which shifts its
     painted top down ~23 px below its layout box. We compensate
     by zeroing the zoom row-gap (was 20) and the host padding-top
     (was 40) and setting padding-top to 17 px (40 visual − 23
     transform). Order matters — must sit after the
     `.work-zoom__grid-host { padding: 0 }` reset above. */
  .work-zoom[data-view="rows"] {
    row-gap: 0 !important;
  }
  .work-zoom[data-view="rows"] .work-zoom__grid-host {
    padding-top: 17px !important;
  }
  .work-zoom[data-view="rows"] .work-zoom__sticky {
    margin: 0 !important;
    padding-bottom: 0 !important;
  }
  /* (Intentionally NOT zeroing .work-thumb:first-child padding-top
     here — that padding is internal to the teal card and reserves
     space for the title label above the browser-frame. Zeroing it
     caused the Wilsons Advisory chart to paint over its title. The
     banner→first-card gap is already pinned to 40 px via row-gap
     (0) + grid-host padding-top (17) above.) */
  /* No per-side margin override on .work-thumb here — the rows-
     view block below controls its centring. */

  /* #3  Ask Chris — drop the animation, just show the AI icon. */
  .ask-ai-btn {
    animation: none !important;
    transition: none !important;
  }
  .ask-ai-btn::before,
  .ask-ai-btn::after {
    display: none !important;        /* kill any decorative orbit / glow */
  }
  .ask-ai-btn__label,
  .ask-ai-btn .ai-chat-cursor {
    display: none !important;        /* hide the "Ask about Chris" text */
  }
  .ask-ai-btn {
    width: 44px !important;
    min-width: 44px !important;
    padding: 0 !important;
    border-radius: 50% !important;
  }

  /* #4  Remove pen + analytics from the footer bottom nav. */
  .bottom-nav .nav-icon[data-tool="pen"],
  .bottom-nav .nav-analytics-btn,
  .bottom-nav #nav-analytics-btn {
    display: none !important;
  }

  /* #5  Pill layer is allowed on mobile again — as STATIC ambient
         decoration only (the screensaver formation IIFE is short-
         circuited on mobile in script.js). Pills are zoned to the
         top of the viewport + the strip to the right of the H1 by
         the placement loop's mobile LEFT_LOCKUP rect. */

  /* #5b Hide the "scrooooll for the win" hint + chevron on mobile.
         The floating bottom-nav already implies scroll affordance,
         and the hint visually clashes with the AI automation chip. */
  #scroll-hint { display: none !important; }

  /* #5c Shrink the colour pills ~20 % on mobile so they fit into the
         narrow strip to the right of the H1 without clipping the
         headline. Font-size, padding and corner radius all scale. */
  #intro-pills .footer-pill {
    height: 24px !important;
    padding: 0 9px !important;
    font-size: 0.62rem !important;
    border-radius: 12px !important;
  }

  /* #6  (the old sticky "Book free strategy session" scroll-CTA was
         removed — the permanent discovery-cta button replaces it.) */

  /* #7  Stack the X (Twitter) button vertically under LinkedIn in
         the top-right corner. */
  .social-fixed {
    flex-direction: column !important;
    gap: 8px !important;
  }
}

/* Mobile videos — fill the container fully (cover-style). On the
   work-thumb masonry strip the desktop rule used object-fit: contain
   which left letterbox gaps; on mobile we want the video to fill
   the available width AND height of its slot, cropping the longer
   edge so the shortest edge always touches the box. */
/* ─────────────────────────────────────────────────────────
   Mobile masonry layout for rows-view project images.
   Replaces the horizontal-scroll strip with a 2-column grid
   that varies by image count. Width gets cropped (object-fit:
   cover) so each cell stays clean; height is determined by
   the row size + how many rows a cell spans.
   ────────────────────────────────────────────────────────── */
@media (max-width: 699px) {
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__media {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    grid-auto-rows: 220px;
    gap: 8px;
    overflow: hidden !important;
    padding: 0 16px 18px 16px !important;
  }
  /* Every gallery image fills its grid cell with a width crop —
     we keep the cell height and trim the sides if the image is
     wider than the cell. */
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__media > img,
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__media .work-thumb__gallery-img {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    height: 100% !important;
    aspect-ratio: auto !important;
    /* Use `contain` so the image fits the wider card without any
       crop (was `cover` which was trimming the edges that the user
       wants to see). */
    object-fit: contain !important;
    object-position: center !important;
    border-radius: 10px !important;
    align-self: stretch !important;
  }
  /* Videos: cover so they fill the cell (portrait clips like Uncle
     Tobys fill the full width and crop top/bottom rather than
     leaving letterbox bars to the side). */
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__media > .work-thumb__video {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    height: 100% !important;
    aspect-ratio: auto !important;
    object-fit: cover !important;
    object-position: center !important;
    border-radius: 10px !important;
    align-self: stretch !important;
  }

  /* ── 1 image — single hero cell, full width, double-height row. */
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__media:has(> :only-child) {
    grid-template-columns: 1fr;
  }
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__media:has(> :only-child) > :only-child {
    grid-row: span 2;
  }

  /* ── 2-image masonry ──
       2a: side-by-side pair (2 cells wide × 1 row high). Each cell
           occupies a single column of the base 2-col grid; the
           container shrinks to 1 row tall — no empty bottom area,
           no orphan cells. (2b stacked-row variant retired.) */
  .work-thumb__media[data-layout="2a"] > :nth-child(1) { grid-column: 1; grid-row: 1; }
  .work-thumb__media[data-layout="2a"] > :nth-child(2) { grid-column: 2; grid-row: 1; }

  /* Hard cap: never render more than 3 images in the masonry on
     mobile. JS already slices to 3, but this CSS-level safety net
     handles any stale enrichment that ran with a 4-image gallery
     before the cap-at-3 logic was deployed. */
  .work-zoom[data-view="rows"] .work-thumb .work-thumb__media > :nth-child(n+4) {
    display: none !important;
  }

  /* ── 3-image masonry — 4 random patterns (JS sets data-layout) ──
       3a: tall left   + 2 stacked right
       3b: tall right  + 2 stacked left
       3c: wide top    + 2 cells under
       3d: 2 cells top + wide row under                              */
  .work-thumb__media[data-layout="3a"] > :nth-child(1) { grid-row: span 2; grid-column: 1; }
  .work-thumb__media[data-layout="3a"] > :nth-child(2) { grid-column: 2; grid-row: 1; }
  .work-thumb__media[data-layout="3a"] > :nth-child(3) { grid-column: 2; grid-row: 2; }

  .work-thumb__media[data-layout="3b"] > :nth-child(1) { grid-column: 1; grid-row: 1; }
  .work-thumb__media[data-layout="3b"] > :nth-child(2) { grid-column: 1; grid-row: 2; }
  .work-thumb__media[data-layout="3b"] > :nth-child(3) { grid-row: span 2; grid-column: 2; }

  .work-thumb__media[data-layout="3c"] > :nth-child(1) { grid-column: span 2; grid-row: 1; }
  .work-thumb__media[data-layout="3c"] > :nth-child(2) { grid-column: 1; grid-row: 2; }
  .work-thumb__media[data-layout="3c"] > :nth-child(3) { grid-column: 2; grid-row: 2; }

  .work-thumb__media[data-layout="3d"] > :nth-child(1) { grid-column: 1; grid-row: 1; }
  .work-thumb__media[data-layout="3d"] > :nth-child(2) { grid-column: 2; grid-row: 1; }
  .work-thumb__media[data-layout="3d"] > :nth-child(3) { grid-column: span 2; grid-row: 2; }
}

/* Mobile testimonials — show only the first 5 (Sam Tyler is the
   last one displayed); hide everyone from 6 onward. */
@media (max-width: 699px) {
  .testimonial-card:nth-child(n + 6) {
    display: none !important;
  }
}

/* Mobile bio section — much smaller left inset (the desktop rule
   uses calc(15vw + 100px) which is ~156px on a phone). */
@media (max-width: 699px) {
  .work {
    padding-left: 16px !important;
    padding-right: 16px !important;
  }
  /* The H1 / chip / meta rows all break out to viewport-edge via
     calc()-based margins on desktop — cancel that on mobile so they
     hug the new 16px gutter. */
  .work .about-h1,
  .work .about-chip,
  .work .about-meta__rows {
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
  /* Avatar floats absolute on desktop; on mobile let it flow inline
     and stay within the bio column. */
  .work .about-block { padding-right: 0 !important; }
  .work .about-meta--with-card .about-meta__card {
    position: static !important;
    width: 100% !important;
    max-width: 320px !important;
    right: auto !important;
    top: auto !important;
  }
}

/* Mobile scroll-hint — drop "for the win" so it reads just "scroll". */
@media (max-width: 699px) {
  .scroll-hint-suffix { display: none !important; }
}

/* Campaign landing-page variants (/app-design, /enterprise-ux,
   /saas-ux, /cro-ux) — hide the discipline pill row under the H1
   so each page reads as a focused conversion lander, not a
   discipline picker. Toggled by the campaign-mode IIFE setting
   `html[data-campaign]`. */
html[data-campaign] .intro-chips { display: none !important; }

/* Cap campaign H1 width to ~60% viewport so long variants (e.g.
   "Website Design UX and Conversion Optimisation Specialist") fold
   into multiple lines instead of stretching across the page, and
   shorter variants (e.g. "Enterprise UX Consultant") still occupy
   a similar bounding box. The canvas-rendered animation reads
   this element's bounding rect for its layout, so the DOM width
   constraint cascades into the scatter. The companion packer in
   the campaign IIFE inserts `|` breaks tuned to this same target. */
@media (min-width: 700px) {
  html[data-campaign] .intro-giant.intro-giant--multiline {
    max-width: min(60vw, calc(90vw - 28px));
  }
}

/* ────────────────────────────────────────────────────────────────
   CAMPAIGN NAV PILLS — sit below the H1 on /app-design, /enterprise-
   ux, /saas-ux, /cro-ux in place of the discipline picker. Same
   shape vocabulary as .intro-chip (white pill, black text), each
   pill anchors to a homepage section.
   ──────────────────────────────────────────────────────────────── */
.campaign-pills {
  display: none;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  margin: 36px 28px 0 10vw;
  max-width: min(100%, calc(90vw - 28px));
  position: relative;
  z-index: 600;
}
/* Reveal only when the campaign-mode IIFE has set html[data-campaign]
   AND it's actually one of our four campaign routes (the script
   removes the `hidden` attribute, then we flip display via CSS). */
html[data-campaign] .campaign-pills:not([hidden]) {
  display: flex;
}
.campaign-pill {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.25;
  color: #1A1A18;
  background: #ffffff;
  border: none;
  border-radius: 100px;
  padding: 10px 22px;
  text-decoration: none;
  cursor: pointer;
  max-width: 100%;
  display: inline-flex;
  align-items: center;
  /* No `gap` — the literal space between the .cp-cat span and the
     text node ("Product Design Examples") already separates them.
     Adding flex gap on top doubled the visible spacing. The arrow
     badge gets its breathing room from its own margin-left below. */
  transition: background 0.18s ease, color 0.18s ease, transform 0.18s ease;
}
.campaign-pill:hover {
  background: #F4F3EE;
  transform: translateY(-1px);
}
/* Same badge as .intro-chip — white circle, black down-chevron,
   nudges down on hover. */
.campaign-pill::after {
  content: '';
  flex-shrink: 0;
  margin-left: 12px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #ffffff
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231A1A18' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>")
    center / 12px no-repeat;
  transition: transform 0.2s ease;
}
.campaign-pill:hover::after { transform: translateY(1px); }

@media (max-width: 699px) {
  .campaign-pills {
    margin: 24px 16px 0;
    gap: 8px;
  }
  .campaign-pill {
    font-size: 13px;
    padding: 9px 18px;
  }
  .campaign-pill::after { width: 22px; height: 22px; }
}

/* ────────────────────────────────────────────────────────────────
   SHORT-VIEWPORT FALLBACK — when the screen isn't tall enough to
   show every pill stacked vertically without overflow (MacBook Air
   13" ≈ 832 px logical height, 14" ≈ 900 px), reflow both the
   homepage discipline picker (.intro-chips) and the campaign nav
   (.campaign-pills) into a horizontal masonry: row + flex-wrap, so
   pills sit side-by-side and spill onto the next line. The H1 and
   sub-text retain their 60% column above; the pill row is allowed
   to use the same width to spread.
   Mobile (max-width:699px) keeps its existing column stack — the
   horizontal reflow only kicks in on desktop/laptop widths where
   it actually adds value.
   ──────────────────────────────────────────────────────────────── */
@media (min-width: 700px) and (max-height: 900px) {
  /* Reclaim vertical space: pull the H1 up so it sits ~50 px below
     the fixed top-left wordmark (which sits with a
     ~28 px top inset). This overrides the 170 px floor used for
     tall screens; on a 13" MacBook Air every saved pixel buys
     room for the proof line and the pill row below.
     Cap H1 max-width at 60% viewport on these screens too — the
     long-form campaign H1s (CRO especially) need the fold,
     and the homepage benefits from the tighter column. */
  .intro-giant.intro-giant--multiline {
    margin-top: 80px;
    /* Bumped 60 vw → 72 vw (~20 % wider) so the H1 folds at
       3-4 lines instead of 5 and stops clipping long words like
       "businesses" / "Websites". 28 px gutter unchanged. */
    max-width: min(72vw, calc(90vw - 28px));
  }

  .intro-chips,
  html[data-campaign] .campaign-pills:not([hidden]) {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 8px;
    /* Match the 60 vw cap on the H1 above so the pill row sits
       directly under the headline column. Pills wrap as needed. */
    max-width: min(60vw, calc(90vw - 28px));
  }
  /* Tighten chip/pill sizing slightly so 5-6 fit on one row at
     a typical MacBook Air width without immediately wrapping to
     two rows. */
  html[data-campaign] .campaign-pill {
    font-size: 14px;
    padding: 9px 18px;
  }
  html[data-campaign] .campaign-pill::after {
    margin-left: 10px;
    width: 22px;
    height: 22px;
  }
}

/* ────────────────────────────────────────────────────────────────
   MOBILE — double the size of every major H2 / H3 heading.
   Applies to the homepage and shared chrome (faq-title, about-
   title, trusted-hed, process-hed, thoughts-eyebrow, thought-
   title, work-title-banner__text, work-zoom__caption,
   pb-title). Uses `font-size` declared at 2× the existing
   mobile/desktop clamps. `!important` so this rule overrides any
   per-section mobile media queries earlier in the file.
   ──────────────────────────────────────────────────────────── */
@media (max-width: 699px) {
  /* H2-tier headings — consolidated to a single uniform size and
     a single left-edge (16 px gutter, no padding/margin offsets
     inherited from desktop). Covers every major page section:
       • work-title-banner__text  → "Recent completed projects"
       • process-hed              → "Process for [discipline]"
       • about-h1                 → "App, web, brand and build expert"
       • social-profiles-label    → "Let's connect"
       • faq-title                → "Frequently Asked Questions"
       • plus the other H2-tier section heds. */
  .faq-title,
  .about-title,
  .about-h1,
  .trusted-hed,
  .trusted-hed--plain,
  .process-hed,
  .thoughts-eyebrow,
  .work-title-banner__text,
  .pb-title,
  .testimonials-hed,
  .social-profiles-label,
  .contact-heading,
  section.faq-section > .faq-inner > .faq-title,
  .canvas-page-intro .about-title {
    /* Trimmed 30 % from the prior clamp(2.8rem, 11vw, 5rem). */
    font-size: clamp(1.96rem, 7.7vw, 3.5rem) !important;
    line-height: 1.05 !important;
    /* Hard reset all margins so each heading starts at the same
       16 px gutter from the left edge of the viewport. Beats the
       per-section calc()/vw left margins set on desktop. */
    margin-left: 16px !important;
    margin-right: 16px !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
    text-align: left !important;
    max-width: calc(100vw - 32px) !important;
  }
  /* H3-tier headings */
  .thought-title,
  .work-zoom__caption,
  .faq-q {
    font-size: clamp(1.6rem, 7vw, 2.6rem) !important;
    line-height: 1.2 !important;
  }
  /* Defensive: ensure the home H1 + process heading always render
     on mobile even if the canvas-animation IIFE never resolves
     fonts.ready (e.g. font load failure, JS error). Without this,
     the elements stay `visibility: hidden` until .is-split is
     added — which leaves a huge blank area on the page. */
  .intro-giant.intro-giant--multiline,
  .process-hed {
    visibility: visible !important;
  }
  /* Char-level safety net. Each .intro-char starts at opacity 0
     with translateX(-70px) and only becomes visible when JS adds
     `.is-in` to each span during the fly-in animation. If the
     animation loop never runs (fonts.ready stall, error, slow JS),
     every character stays at opacity 0 and the H1 reads as empty
     even with the container visible. On mobile we skip the
     animation entirely — chars render at their final position
     immediately. */
  .intro-char {
    opacity: 1 !important;
    transform: translateX(0) !important;
  }
  /* Process-hed text — the `.is-revealing` keyframe was getting
     stuck at its from-state (opacity 0 + translateY(28)) on mobile,
     so "More about process." rendered invisible inside its visible
     container. Skip the animation entirely on phones. */
  .process-hed__text {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }

  /* ── Process-panel accordion pills → match the main FAQ pills.
     Same yellow-circle arrow, same size and alignment, same full-
     width pill behaviour with text wrap on mobile. */
  .process-panel .faq-item {
    width: 100% !important;
    max-width: 100% !important;
    display: block !important;
  }
  .process-panel .faq-item:has(.faq-q[aria-expanded="true"]) {
    width: 100% !important;
  }
  .process-panel .faq-q {
    width: 100% !important;
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    padding: 18px 16px 18px 22px !important;
    gap: 12px !important;
    white-space: normal !important;
    font-size: 15.75px !important;
    font-weight: 500 !important;
    letter-spacing: -0.005em !important;
    line-height: 1.25 !important;
    min-height: 56px !important;
  }
  .process-panel .faq-q__text {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    overflow-wrap: break-word !important;
    white-space: normal !important;
    font-size: 15.75px !important;
    font-weight: 500 !important;
  }
  .process-panel .faq-icon {
    flex-shrink: 0 !important;
    width: 25px !important;
    height: 25px !important;
    background: #FFD600 !important;       /* yellow circle, matches FAQ */
    color: #1A1A18 !important;
  }
  .process-panel .faq-icon svg {
    width: 13px !important;
    height: 13px !important;
  }

  /* ── About section: image LEFT (full height of the meta block),
     Speciality + Experience rows to the RIGHT of it. */
  .work .about-meta--with-card {
    display: flex !important;
    flex-direction: row !important;
    align-items: stretch !important;
    gap: 14px !important;
  }
  .work .about-meta--with-card .about-meta__card {
    position: relative !important;
    flex: 0 0 auto !important;
    width: 38% !important;
    max-width: 160px !important;
    min-width: 110px !important;
    aspect-ratio: 3 / 4 !important;       /* taller / portrait */
    height: auto !important;
    margin: 0 !important;
  }
  .work .about-meta--with-card .about-meta__rows {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    display: flex !important;
    flex-direction: column !important;
    gap: 12px !important;
  }
  .work .about-meta--with-card .about-meta-item {
    max-width: 100% !important;
    width: 100% !important;
    white-space: normal !important;
    overflow-wrap: break-word !important;
  }

  /* ── About chip: single-line on mobile. Shrink the font enough
     that "20 years · Australia · Remote Global" fits in one row;
     the inline span keeps " · Remote Global" on the same line. */
  .about-chip {
    font-size: 0.78rem !important;
    padding: 6px 14px !important;
    white-space: nowrap !important;
  }
  .about-chip__break {
    display: inline !important;
  }

  /* ── About H1 ("App, web, brand and build expert"): cap to 70 %
     of the viewport so the line wraps with a couple of words on
     the second line instead of a single orphan/widow word. */
  .work .about-h1 {
    max-width: 70% !important;
    white-space: normal !important;
    word-break: normal !important;
    overflow-wrap: break-word !important;
  }
}

/* ────────────────────────────────────────────────────────────────
   MOBILE — fix runaway About image. Earlier rules set the
   .about-meta__card to `position: static` on mobile, which broke
   the positioned ancestor for its `position: absolute` IMG inside.
   The IMG then bubbled up to fill the viewport. Restoring
   `position: relative` plus a hard width/aspect-ratio gives us a
   small thumb that sits in line with the About content stack.
   ──────────────────────────────────────────────────────────── */
@media (max-width: 699px) {
  .work .about-meta--with-card .about-meta__card {
    position: relative !important;
    width: 140px !important;
    max-width: 140px !important;
    height: auto !important;
    aspect-ratio: 3 / 2 !important;
    margin: 8px 0 16px 0 !important;
  }
}

/* ────────────────────────────────────────────────────────────────
   MOBILE — Daikin (specific): right-align the 2nd gallery image so
   the cropped right edge sits flush. The image's left side has
   meaningful content; the right side is the part that should
   meet the cell edge cleanly when cover-cropped.
   ──────────────────────────────────────────────────────────── */
@media (max-width: 699px) {
  .work-zoom[data-view="rows"] .work-thumb[data-slug="daikin"] .work-thumb__media > :nth-child(2) {
    object-position: right center !important;
  }
}

/* ────────────────────────────────────────────────────────────────
   MOBILE FAQ pills — the desktop pill-sizing IIFE locks each
   .faq-item to a pixel width that was probed at the desktop
   font-size. On mobile (much larger font via the H3-tier rule
   earlier) the text overflows OR the pill has trailing whitespace.
   Override here:
     • pill takes full container width (consistent, predictable)
     • text wraps to multiple lines if needed
     • yellow arrow stays right-anchored, vertically centred,
       never shrinks
     • text vertically centred (was top-aligned)
   ──────────────────────────────────────────────────────────── */
@media (max-width: 699px) {
  .faq-section#faq .faq-item {
    width: 100% !important;
    max-width: 100% !important;
  }
  .faq-section#faq .faq-q {
    width: 100% !important;
    align-items: center !important;   /* vertical centre */
    white-space: normal !important;
    padding: 18px 16px 18px 22px !important;
    gap: 12px !important;
    justify-content: space-between !important;
  }
  .faq-section#faq .faq-q__text {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    overflow-wrap: break-word !important;
    word-break: normal !important;
    hyphens: none !important;
    white-space: normal !important;
  }
  .faq-section#faq .faq-icon {
    flex-shrink: 0 !important;        /* arrow never gets squashed */
  }
}

