/* =====================================================================
   CLAY SHAPE + ORIGINAL COLORS  (experimental / reversible)
   Loaded AFTER style.css. Keeps Clay's *shape & type* — rounded warm
   display (Inter 500 + negative tracking), generous radii, compact
   rounded-rect buttons — but restores ALL of the site's ORIGINAL colors
   (soft-blue canvas, blue brand, gradient boards, blue buttons, the
   original textured canvas). No color overrides here, only geometry/type.

   To REVERT: delete this file and remove its <link> from the *.html files.
   Originals (style.css/projects.js/main.js) are untouched.
   ===================================================================== */

/* ---- Satoshi (body + UI + ALL headings) — self-hosted, Fontshare ----
   These three faces are the ONLY fonts this file loads. 17 unused .woff2 files
   (Open Runde, General Sans, Fraunces, Cal Sans, Satoshi 900, Instrument Serif)
   and their @font-face blocks were removed; they are in .claude/perf-backup/.
   WARNING: the literal "Open Runde" in the --sans/--display/--serif chains below
   is INTENTIONAL. Satoshi is first and covers every glyph the site uses, so that
   slot is never reached — leaving the string is a no-op, but removing it would
   change behaviour for a visitor with Open Runde installed locally. ---- */
@font-face { font-family: "Satoshi"; font-weight: 400; font-style: normal; font-display: swap;
  src: url("../fonts/satoshi/satoshi-400.woff2") format("woff2"); }
@font-face { font-family: "Satoshi"; font-weight: 500; font-style: normal; font-display: swap;
  src: url("../fonts/satoshi/satoshi-500.woff2") format("woff2"); }
@font-face { font-family: "Satoshi"; font-weight: 700; font-style: normal; font-display: swap;
  src: url("../fonts/satoshi/satoshi-700.woff2") format("woff2"); }

/* ----------------------------- Tokens ----------------------------- */
:root {
  /* Satoshi everywhere — body, UI, AND non-hero headings */
  --sans:  "Satoshi", "Open Runde", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* non-hero headings + the name wordmark also use Satoshi */
  --display: "Satoshi", "Open Runde", system-ui, sans-serif;
  /* ---- ORIGINAL colors restored (same as the very start) ---- */
  --bg:           #ffffff;
  --bg-soft:      #f6f7f9;
  --surface:      #ffffff;
  --surface-2:    #f6f9ff;

  --ink:          #0c0d12;
  --ink-2:        #232934;
  --muted:        #3a4150;   /* darker body/secondary — was #5b6473 */
  --faint:        #5a6273;   /* darker meta/tertiary — was #98a1b2 */

  --brand:        #1c1c1c;
  --brand-ink:    #000000;
  --brand-tint:   #e7eefc;
  --brand-soft:   rgba(28, 28, 28, .10);

  --line:         rgba(12, 13, 18, .08);
  --line-2:       rgba(12, 13, 18, .14);
  --shadow-sm:    0 1px 2px rgba(13, 26, 64, .04), 0 2px 8px rgba(13, 26, 64, .04);
  --shadow-md:    0 8px 30px rgba(13, 26, 64, .08);
  --shadow-lg:    0 24px 60px rgba(13, 26, 64, .12);

  /* ---- KEEP Clay shape + type ---- */
  --serif: "Satoshi", "Open Runde", system-ui, -apple-system, sans-serif;
  --radius:    16px;   /* content cards */
  --radius-lg: 24px;   /* feature cards */
  --radius-sm: 12px;   /* buttons + inputs */
}

/* Remove the dotted grid texture on the canvas */
body::before { display: none !important; }

/* --------------------------- Typography --------------------------- */
/* Clay rounded display: Inter weight 500, upright, negative tracking */
.display, .cta-band__title {
  font-family: var(--display);
  font-style: normal;
  font-weight: 500;
  letter-spacing: -0.02em;
}
.hero__title {
  font-family: "Averia Serif Libre", var(--display);   /* Averia Serif Libre display face */
  font-size: clamp(1.8125rem, 1.22rem + 2.2vw, 2.625rem);   /* 29px mobile → 42px cap (reached @1022): the page's clear apex */
  font-weight: 700;                          /* bold cut gives the serif heading presence */
  color: #1c1c1c;                            /* softer grey instead of near-black */
  line-height: 1.16;
  letter-spacing: -0.005em;
  max-width: 28em;                           /* wide enough that the column, not this, drives wrapping → 2 lines */
  text-wrap: balance;
}

/* Orbit removed — shrink the photo so the headline is the focal point */
.hero__visual { width: auto; min-height: 0; margin-bottom: clamp(16px, 2.2vw, 26px); }
.hero__photo { width: clamp(92px, 11vw, 124px); outline-width: 6px; }
.hero__ring { width: clamp(170px, 19vw, 230px); }

/* =====================================================================
   SIGNATURE "APPEAR" ENTRANCE (reverse-engineered from kirayanti.space)
   blur(5px)+fade+rise -> settle, 0.6s, cubic-bezier(.44,0,.56,1), staggered.
   ===================================================================== */
:root { --ease-appear: cubic-bezier(.44, 0, .56, 1); }

/* Project cards come alive on scroll: the card blurs-up + rises, then its
   content (logo -> title -> summary -> meta -> button) staggers in. */
#work .study {
  opacity: .001; filter: blur(6px); transform: translateY(48px) scale(.985);
  transition: opacity .6s var(--ease-appear), filter .6s var(--ease-appear), transform .68s var(--ease-appear);
  will-change: transform, opacity, filter;
}
#work .study.is-in { opacity: 1; filter: blur(0); transform: none; }
/* "View all projects" button — reveals after the cards it follows */
#work .work-more.reveal { opacity: 0; transform: translateY(24px); transition: opacity 1.4s ease, transform 1.4s cubic-bezier(.22, 1, .36, 1); transition-delay: .35s !important; }
#work .work-more.reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  #work .work-more.reveal { transition: none; opacity: 1; transform: none; }
}
/* image zoom-settle: starts gently scaled-in, eases to 1 as the card reveals
   (clipped to its own frame so it can't bleed past the card edge) */
#work .study__media { overflow: hidden; }
#work .study .study__media { transform: scale(1.12); transition: transform 1s var(--ease-appear); }
#work .study.is-in .study__media { transform: scale(1); }
#work .study__brand, #work .study__title, #work .study__sum,
#work .study__meta, #work .study__btn,
#work .study__chips, #work .study__impact, #work .study__stats {
  opacity: .001; filter: blur(4px); transform: translateY(12px);
  transition: opacity .75s var(--ease-appear), filter .75s var(--ease-appear), transform .75s var(--ease-appear);
}
#work .study.is-in .study__brand { transition-delay: .20s; }
#work .study.is-in .study__title { transition-delay: .34s; }
#work .study.is-in .study__sum   { transition-delay: .48s; }
#work .study.is-in .study__chips { transition-delay: .48s; }
#work .study.is-in .study__meta  { transition-delay: .62s; }
#work .study.is-in .study__impact { transition-delay: .62s; }
#work .study.is-in .study__btn   { transition-delay: .76s; }
#work .study.is-in .study__stats { transition-delay: .76s; }
#work .study.is-in .study__brand, #work .study.is-in .study__title,
#work .study.is-in .study__sum, #work .study.is-in .study__meta,
#work .study.is-in .study__btn, #work .study.is-in .study__chips,
#work .study.is-in .study__impact, #work .study.is-in .study__stats { opacity: 1; filter: blur(0); transform: none; }

/* first featured card: animates like the rest, sequenced to land right after the
   hero cascade (hero logos rise at .70s) — card + inner stagger shifted by .45s */
#work .studies[data-featured-grid] .study:first-child { transition-delay: .45s !important; }   /* beats the inline reveal delay from main.js */
#work .studies[data-featured-grid] .study:first-child.is-in .study__media { transition-delay: .45s; }
#work .studies[data-featured-grid] .study:first-child.is-in .study__brand { transition-delay: .65s; }
#work .studies[data-featured-grid] .study:first-child.is-in .study__title { transition-delay: .79s; }
#work .studies[data-featured-grid] .study:first-child.is-in .study__sum,
#work .studies[data-featured-grid] .study:first-child.is-in .study__chips { transition-delay: .93s; }
#work .studies[data-featured-grid] .study:first-child.is-in .study__meta,
#work .studies[data-featured-grid] .study:first-child.is-in .study__impact { transition-delay: 1.07s; }
#work .studies[data-featured-grid] .study:first-child.is-in .study__btn,
#work .studies[data-featured-grid] .study:first-child.is-in .study__stats { transition-delay: 1.21s; }

@media (prefers-reduced-motion: reduce) {
  .hero__projects, #work .study,
  #work .study__brand, #work .study__title, #work .study__sum,
  #work .study__meta, #work .study__btn,
  #work .study__chips, #work .study__impact, #work .study__stats {
    opacity: 1 !important; filter: none !important; transform: none !important; transition: none !important;
  }
}

/* ---- Featured grid (homepage): a clean spaced list — no sticky stacking, so a
   hovered/elevated card never covers the others. ---- */
/* "View all projects" button matches the hero "Let's chat" sizing + grey */
#work .studies + div .btn { height: 44px; padding: 0 24px; font-size: 1.125rem; background: linear-gradient(135deg, #3a3a3a 0%, #1c1c1c 60%, #0e0e0e 100%); gap: 0; }
#work .studies + div .btn:hover { background: linear-gradient(135deg, #454545 0%, #232323 60%, #121212 100%); }
/* arrow reveals + slides in on hover, exactly like the "Let's chat" CTA */
#work .studies + div .btn .ar {
  width: 0; opacity: 0; margin-left: 0; transform: translateX(-6px); overflow: hidden;
  transition: width .35s var(--ease), opacity .25s ease, margin-left .35s var(--ease), transform .35s var(--ease);
}
#work .studies + div .btn:hover .ar { width: 15px; opacity: 1; margin-left: 7px; transform: translateX(0); }
#work .studies .study {
  /* soft depth so each card reads as its own layer */
  box-shadow: 0 2px 6px rgba(13,26,64,.05), 0 24px 50px -30px rgba(13,26,64,.32);
}
/* hover: a clean pop — cards no longer overlap, so nothing gets hidden */
#work .studies .study.is-in:hover {
  transform: translateY(-7px) scale(1.012);
  box-shadow: 0 6px 14px rgba(28,28,28,.07), 0 36px 66px -26px rgba(28,28,28,.45);
  transition: transform .32s var(--ease), box-shadow .32s var(--ease);
  z-index: 2;
}

/* ---- Closing footer: hero-style box (light, transparent, bordered) ----------
   Was the dark CTA panel; now matched to the hero container (.hero-box). Holds the
   headline, the email + Book-a-Call control, and the brand/copyright bar. */
.cta-foot { padding-bottom: clamp(40px, 6vw, 76px); }   /* lands 76 @1280 (even) */
.cta-final {
  position: relative; overflow: visible;
  border: 1px solid #e7eaf1;
  border-radius: 24px;   /* matched to the project cards */
  /* 4-pt snap: the plain clamp is the fallback, round() quantises to the grid */
  padding: clamp(32px, 3.3vw, 44px) clamp(24px, 5vw, 64px) clamp(24px, 2vw, 28px);
  padding: round(clamp(32px, 3.3vw, 44px), 4px) round(clamp(24px, 5vw, 64px), 4px) round(clamp(24px, 2vw, 28px), 4px);   /* 44 · 64 · 24 @1280 */
  text-align: center; color: var(--ink);
  background: transparent;
  box-shadow: 0 1px 2px rgba(13, 26, 64, .04), 0 18px 50px -28px rgba(13, 26, 64, .22);
}
/* content cascade: heading → subtitle → actions → links → footer bar (hero-style) */
.cta-final.reveal .cta-final__title,
.cta-final.reveal .cta-final__sub,
.cta-final.reveal .cta-final__form,
.cta-final.reveal .cta-final__links,
.cta-final.reveal .cta-final__foot {
  opacity: 0; transform: translateY(16px);
  transition: opacity .9s ease, transform .9s cubic-bezier(.22, 1, .36, 1);
}
.cta-final.reveal.is-in .cta-final__title,
.cta-final.reveal.is-in .cta-final__sub,
.cta-final.reveal.is-in .cta-final__form,
.cta-final.reveal.is-in .cta-final__links,
.cta-final.reveal.is-in .cta-final__foot { opacity: 1; transform: none; }
.cta-final.reveal.is-in .cta-final__title { transition-delay: .12s; }
.cta-final.reveal.is-in .cta-final__sub   { transition-delay: .36s; }
.cta-final.reveal.is-in .cta-final__form  { transition-delay: .60s; }
.cta-final.reveal.is-in .cta-final__links { transition-delay: .84s; }
.cta-final.reveal.is-in .cta-final__foot  { transition-delay: 1.08s; }
@media (prefers-reduced-motion: reduce) {
  .cta-final.reveal .cta-final__title, .cta-final.reveal .cta-final__sub, .cta-final.reveal .cta-final__form,
  .cta-final.reveal .cta-final__links, .cta-final.reveal .cta-final__foot { transition: none; opacity: 1; transform: none; }
}

.cta-final__title {
  margin: 0 auto; max-width: 22ch;
  font-family: "Averia Serif Libre", var(--display); font-weight: 700;   /* matches every section heading */
  font-size: clamp(1.625rem, 1.325rem + 1.16vw, 2.25rem); line-height: 1.16; letter-spacing: -0.01em;   /* 36px cap — shared section-heading step */
  color: #1c1c1c; text-wrap: balance;
}
.cta-final__sub {
  margin: 16px auto 0; max-width: 46ch;
  font-family: var(--sans); font-weight: 500;
  font-size: 1rem; line-height: 1.5;   /* 16px */
  color: var(--muted);
  text-wrap: balance;   /* even out the two lines — avoid a lone word on line 2 */
}
/* Book a Call → the site's prominent primary button (44px · 0 24px · 18px) */
.cta-final .btn { height: 44px; padding: 0 24px; font-size: 1.125rem; }

/* email + copy + Book-a-Call control (on the light footer) */
.cta-final__form {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: 12px; margin-top: 24px;   /* narrative → actions: the OUTER gap that opens the group */
}
.cta-mail {
  display: inline-flex; align-items: center; gap: 8px;
  background: #f1f1f2; border: 1px solid #e4e4e6; border-radius: var(--radius-sm);
  padding: 5px 5px 5px 14px; height: 44px;   /* same height as Book a Call, tighter */
}
.cta-mail__addr { color: var(--ink); font-weight: 500; font-size: 1rem; white-space: nowrap; }
.cta-mail__copy {
  height: 34px; padding: 0 12px; border-radius: var(--radius-sm); border: 1px solid #d5d7dd;   /* firmer edge so the control reads clickable */ cursor: pointer; flex: none;
  display: inline-flex; align-items: center; gap: 6px; background: #fff; color: var(--ink, #16181d);   /* was --faint: light grey on white read as a disabled control */
  font-family: var(--display); font-weight: 500; font-size: 0.875rem;
  transition: background .2s ease, color .2s ease;
}
/* hover: the same slide-up fill as the nav’s “Let’s chat” CTA. That one duplicates
   its label in ::before content; this cannot — the button has an icon and two
   swapping labels (Copy / Copied) — so the panel is a bare background behind the
   content instead, and the text simply inverts. Same motion, one source of truth. */
.cta-mail__copy { position: relative; overflow: hidden; isolation: isolate; }
.cta-mail__copy > * { position: relative; z-index: 2; }
.cta-mail__copy::before {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: var(--ink, #16181d); border-radius: inherit;
  transform: translateY(101%);
  transition: transform .7s cubic-bezier(.4, 0, .2, 1);
}
.cta-mail__copy:hover::before { transform: translateY(0); }
.cta-mail__copy:hover { color: #fff; border-color: var(--ink, #16181d); }
/* the confirmation is green on white — retract the panel so it stays legible
   while the pointer is still resting on the button after the click */
.cta-mail__copy.is-copied::before { transform: translateY(101%); }
.cta-mail__copy.is-copied:hover { color: #0f9d57; border-color: #bfe6cf; }
@media (prefers-reduced-motion: reduce) {
  .cta-mail__copy::before { transition: none; }
}
.cta-mail__copy svg { width: 15px; height: 15px; flex: none; }
.cta-mail__copy .ico-check { color: #0f9d57; }
.cta-mail__copy .ico-check, .cta-mail__copy .lbl-done { display: none; }
.cta-mail__copy.is-copied { color: #0f9d57; border-color: #bfe6cf; }
.cta-mail__copy.is-copied .ico-copy, .cta-mail__copy.is-copied .lbl-copy { display: none; }
.cta-mail__copy.is-copied .ico-check, .cta-mail__copy.is-copied .lbl-done { display: inline; }
/* full "Case studies" hover recipe: springy scale + gradient lift + glow, arrow reveals.
   Shared by Book a Call and the homepage "View all projects" button. */
.cta-book.btn,
#work .work-more .btn {
  gap: 0; transform-origin: center;
  transition: transform .4s cubic-bezier(.34, 1.56, .5, 1), box-shadow .35s ease, background .35s ease;
}
.cta-book.btn .ar,
#work .work-more .btn .ar {
  width: 0; opacity: 0; margin-left: 0; transform: translateX(-6px); overflow: hidden;
  transition: width .35s var(--ease), opacity .25s ease, margin-left .35s var(--ease), transform .35s var(--ease);
}
.cta-book.btn:hover,
.cta-book.btn:focus-visible,
#work .work-more .btn:hover,
#work .work-more .btn:focus-visible {
  background: linear-gradient(135deg, #454545 0%, #232323 60%, #121212 100%);
  transform: scale(1.06);
  box-shadow: 0 14px 28px -12px rgba(28, 28, 28, .7);
}
.cta-book.btn:hover .ar,
.cta-book.btn:focus-visible .ar,
#work .work-more .btn:hover .ar,
#work .work-more .btn:focus-visible .ar { width: 15px; opacity: 1; margin-left: 8px; transform: translateX(0); }
.cta-book.btn:active,
#work .work-more .btn:active { transform: scale(.99); }
@media (prefers-reduced-motion: reduce) {
  .cta-book.btn, .cta-book.btn .ar,
  #work .work-more .btn, #work .work-more .btn .ar { transition: none; }
  .cta-book.btn:hover, .cta-book.btn:focus-visible,
  #work .work-more .btn:hover, #work .work-more .btn:focus-visible { transform: none; }
}

/* secondary pill links — the site's card-CTA language: a quiet pill whose
   circular arrow chip fills ink on hover while the arrow flies out and a
   twin swoops back in (↗ for external, ↓ for the résumé download) */
.cta-final__links {
  display: flex; justify-content: center; align-items: center; gap: 12px;
  margin-top: 12px;   /* INNER gap — matches the 12px between the controls beside it,
                         so primary + secondary bind into one action group (24 out / 12 in) */
}
.cta-link {
  display: inline-flex; align-items: center; gap: 9px;
  height: 44px; padding: 0 5px 0 12px; border-radius: 999px;
  background: #fff; border: 1px solid #eef1f6;   /* softer than --line — reads secondary to Book a Call */
  font-family: var(--display); font-size: 1rem; font-weight: 500;   /* 16px */
  color: var(--ink, #0c0d12); text-decoration: none;
  transition: transform .35s cubic-bezier(.34, 1.56, .5, 1), box-shadow .3s ease, border-color .3s ease;
}
/* leading brand icon (LinkedIn glyph · résumé document) */
.cta-link__ico { display: inline-flex; flex: none; color: var(--ink, #0c0d12); }
.cta-link__ico svg { width: 16px; height: 16px; display: block; }
.cta-link:hover {
  transform: translateY(-2px);
  border-color: rgba(12, 13, 18, .22);
  box-shadow: 0 10px 22px -14px rgba(12, 13, 18, .4);
}
.cta-link:focus-visible { outline: 2px solid var(--ink, #0c0d12); outline-offset: 3px; }
.cta-link__chip {
  position: relative; overflow: hidden;
  width: 27px; height: 27px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  border: 1px solid rgba(12, 13, 18, .12); color: var(--ink, #0c0d12);
  transition: background .3s ease, border-color .3s ease, color .3s ease;
}
.cta-link:hover .cta-link__chip { background: #1c1c1c; border-color: #1c1c1c; color: #fff; }
.cta-link__chip svg {
  position: absolute; width: 13px; height: 13px;
  transition: transform .4s cubic-bezier(.34, 1.56, .5, 1);
}
/* external (↗): arrow exits top-right, its twin swoops in from bottom-left */
.cta-link--ext .cta-link__chip svg:nth-child(2) { transform: translate(-22px, 22px); }
.cta-link--ext:hover .cta-link__chip svg:first-child { transform: translate(22px, -22px); }
.cta-link--ext:hover .cta-link__chip svg:nth-child(2) { transform: translate(0, 0); }
/* download (↓): arrow drops out the bottom, its twin falls in from the top */
.cta-link--dl .cta-link__chip svg:nth-child(2) { transform: translateY(-30px); }
.cta-link--dl:hover .cta-link__chip svg:first-child { transform: translateY(30px); }
.cta-link--dl:hover .cta-link__chip svg:nth-child(2) { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .cta-link, .cta-link__chip svg { transition: none; }
  .cta-link--ext .cta-link__chip svg:nth-child(2),
  .cta-link--dl .cta-link__chip svg:nth-child(2) { display: none; }
  .cta-link--ext:hover .cta-link__chip svg:first-child,
  .cta-link--dl:hover .cta-link__chip svg:first-child { transform: none; }
}
.cta-final__avail {
  margin: 18px auto 0; max-width: 60ch;
  font-family: var(--sans); font-size: 0.8125rem; line-height: 1.5;
  color: rgba(71, 85, 105, 0.72);
}

/* ≤560px: email control and booking button stack; links stay evenly spaced */
@media (max-width: 560px) {
  .cta-final__form { flex-direction: column; }
  .cta-mail { width: 100%; max-width: 340px; justify-content: space-between; }
  .cta-book.btn { width: 100%; max-width: 340px; justify-content: center; }
  .cta-final__links { gap: 10px; flex-wrap: wrap; }
}

/* brand + copyright bar at the bottom of the footer */
.cta-final__foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 28px; padding-top: 24px;   /* 28 above the divider · 24 below */
  border-top: 1px solid #e7eaf1; text-align: left;
}
.cta-final__brand { display: flex; flex-direction: column; gap: 6px; }
/* footer-weight brand: a quiet sign-off, not a second navbar. The nav lockup is
   the loud one (28px mark · 18px name) — this steps down so it reads as a mark
   of authorship at the end of the page rather than a repeat of the header. */
.cta-final__brand .brand { gap: 8px; }
/* The nav mark is 28px and the SVG’s own rx=9 (of a 32 viewBox) resolves to
   ~7.9px — 28% of the box. Reusing --radius-sm (12px) here clipped a 22px box at
   55%, which read as a circle rather than the same squircle. 6px keeps the ratio. */
.cta-final__brand .brand__mark { width: 22px; height: 22px; border-radius: 6px; }
.cta-final__brand .brand__name { font-size: 0.875rem; color: var(--muted, #3a4150); }   /* 14px — on the small step, muted */
.cta-final__tag { margin: 0; color: var(--muted); font-size: 1rem; }
.cta-final__copy { margin: 0; color: var(--faint); font-size: 0.875rem; font-weight: 500; }
@media (max-width: 560px) {
  .cta-final__foot { justify-content: center; text-align: center; }
  .cta-final__brand { align-items: center; }
}

/* footer container: matched to the hero container (.hero-box) — transparent box,
   light border, soft two-layer shadow, same rounded corners */
.footer__card {
  background: transparent;
  border: 1px solid #e7eaf1;
  border-radius: 24px;   /* matched to the project cards */
  box-shadow: 0 1px 2px rgba(13, 26, 64, .04), 0 18px 50px -28px rgba(13, 26, 64, .22);
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
}

/* ---- Skills radar + impact stats + projects-per-year line chart --------------
   Hand-drawn inline SVG (no chart lib), themed: brand-blue radar/line, the theme
   green for the positive series + arrows, --line gridlines, Satoshi labels. */
.skills { display: flex; flex-direction: column; gap: clamp(36px, 5vw, 60px); }
.skills__top {
  display: grid; grid-template-columns: 1.12fr .88fr; gap: clamp(28px, 5vw, 64px);
  align-items: center;
}
@media (max-width: 880px) { .skills__top { grid-template-columns: 1fr; gap: clamp(28px, 6vw, 44px); } }

/* radar */
.skills__radar { margin: 0; align-self: center; width: 100%; max-width: 560px; }
.skills__radar .rdr { width: 100%; height: auto; display: block; overflow: visible; }
.rdr__ring  { fill: none; stroke: var(--line); stroke-width: 1; }
.rdr__ring:nth-of-type(2n) { fill: rgba(12, 13, 18, .018); }   /* faint alternating bands */
.rdr__spoke { stroke: var(--line); stroke-width: 1; }
.rdr__tick  { fill: #aab2bf; font: 600 11px var(--sans); }
.rdr__area  { fill: rgba(28, 28, 28, .15); stroke: var(--brand); stroke-width: 2.5; stroke-linejoin: round; }
.rdr__dot   { fill: var(--brand); }
.rdr__label { fill: var(--ink-2); font: 600 13px var(--sans); }

/* stats */
.skills__stats { display: flex; flex-direction: column; gap: clamp(24px, 3.2vw, 38px); }
@media (max-width: 880px) and (min-width: 561px) { .skills__stats { flex-direction: row; gap: clamp(32px, 6vw, 56px); } }
.stat-cell__top { display: flex; align-items: center; gap: 10px; }
.stat-cell__num { font-family: var(--display); font-weight: 600; font-size: clamp(2rem, 3.4vw, 2.875rem); letter-spacing: -.02em; color: var(--ink); line-height: 1; }
.stat-cell__arw { width: 26px; height: 26px; color: #0f9d57; flex: none; }
.stat-cell__arw svg { width: 100%; height: 100%; display: block; }
.stat-cell__txt { margin: 12px 0 0; max-width: 32ch; color: var(--ink-2); font-size: clamp(1rem, 1.3vw, 1.0625rem); line-height: 1.5; }

/* line chart */
.skills__chart { padding-top: clamp(28px, 3.4vw, 44px); border-top: 1px solid var(--line); }
.skills__chart-title { font-family: var(--display); font-weight: 600; font-size: clamp(1.25rem, 1.9vw, 1.5rem); letter-spacing: -.015em; color: var(--ink); margin: 0; }
.skills__legend { display: flex; flex-wrap: wrap; gap: 20px; margin: 16px 0 6px; }
.lc__leg { display: inline-flex; align-items: center; gap: 8px; font-size: .9375rem; font-weight: 500; color: var(--ink-2); }
.lc__leg i { width: 18px; height: 3px; border-radius: 2px; flex: none; }
.lc__leg--blue  i { background: var(--brand); }
.lc__leg--muted i { background: #b3bac6; }
.lc__leg--green i { background: #0f9d57; }
.skills__plot { margin: 0; }
.skills__plot .lc { width: 100%; height: auto; display: block; }
.lc__grid { stroke: var(--line); stroke-width: 1; }
.lc__yt, .lc__xt { fill: #aab2bf; font: 600 12px var(--sans); }
.lc__yt { text-anchor: end; }
.lc__xt { text-anchor: middle; }
.lc__line { fill: none; stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
.lc__line--blue  { stroke: var(--brand); stroke-width: 3; }
.lc__line--muted { stroke: #c2c8d2; }
.lc__line--green { stroke: #0f9d57; }
.skills__caption { margin: 18px 0 0; max-width: 72ch; color: var(--ink-2); font-size: clamp(.9375rem, 1.2vw, 1rem); line-height: 1.55; }

/* ---- Experience years bar ---- */
.reach-years { margin-top: clamp(30px, 3.6vw, 48px); padding-top: clamp(30px, 3.6vw, 48px); border-top: 1px solid var(--line); max-width: 780px; }
.reach-years__line { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; }
.reach-years__num { font-family: var(--display); font-weight: 600; font-size: clamp(1.625rem, 2.7vw, 2.25rem); letter-spacing: -.02em; color: var(--ink); line-height: 1.1; }
.reach-years__lbl { color: var(--ink-2); font-size: clamp(1rem, 1.3vw, 1.0625rem); }
.reach-years__bar { height: 6px; border-radius: 999px; background: #e9dfce; margin: 14px 0; overflow: hidden; }
.reach-years__fill { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--brand), #5c8def); }

/* ---- 25+ products + domains  |  Markets & Platforms donut ---- */
.reach-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 5vw, 64px); align-items: center;
  padding-top: clamp(20px, 2.4vw, 32px);
}
@media (max-width: 880px) { .reach-grid { grid-template-columns: 1fr; gap: clamp(28px, 6vw, 40px); } }

.reach-prod__num { font-family: var(--display); font-weight: 600; font-size: clamp(1.75rem, 3vw, 2.5rem); letter-spacing: -.02em; color: var(--ink); margin: 0; line-height: 1.05; }
.reach-prod__txt { color: var(--ink-2); font-size: clamp(1rem, 1.3vw, 1.0625rem); margin: 8px 0 0; max-width: 40ch; }
.reach-domains { list-style: none; margin: clamp(20px, 2.6vw, 30px) 0 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 14px 22px; }
.reach-domains__item { display: flex; align-items: center; gap: 9px; font-size: .9375rem; font-weight: 500; color: var(--ink-2); }
.reach-domains__ic { width: 18px; height: 18px; color: #9aa3b2; flex: none; }

/* bordered card to match the testimonial / process cards it now sits beside */
.reach-markets {
  display: flex; flex-direction: column;
  background: transparent;
  border: 1px solid #e7eaf1;
  box-shadow: 0 1px 2px rgba(28,28,28,.04), 0 10px 28px -22px rgba(28,28,28,.22);   /* shared container lift — same recipe as .exp-list */
  border-radius: var(--radius-lg, 24px);   /* on-system with every other card */
  padding: 6px clamp(24px, 2.4vw, 36px);   /* slim vertical rails — the donut fills the height */
  padding: 6px round(clamp(24px, 2.4vw, 36px), 4px);   /* 32 @1280 */
}
.reach-markets__title { font-family: var(--display); font-weight: 600; font-size: clamp(1.25rem, 1.9vw, 1.5rem); letter-spacing: -.015em; color: var(--ink); margin: 0 0 clamp(10px, 1.4vw, 16px); }
.reach-donut { margin: 0; flex: 1; display: grid; place-items: center; }   /* centre the donut in the card height */
.reach-donut .dn { width: 100%; max-width: clamp(330px, 38vw, 420px); height: auto; display: block; margin-inline: auto; overflow: visible; }   /* fills the same card height with slimmer rails */
.dn__lead   { fill: none; stroke: #c2c8d2; stroke-width: 1; }
.dn__lbl    { fill: var(--ink-2); font: 600 17px var(--sans); }
.dn__pct    { fill: #3a4150; font: 700 17px var(--sans); }      /* solid ink — segment colors washed the numbers out */
.dn__cen    { fill: var(--ink-2); font: 600 17px var(--sans); }   /* sized so "Desktop / Web 60%" clears the donut hole */
.dn__cenpct { fill: #3a4150; font-weight: 600; }

/* entrance motion: arcs draw in (staggered), labels + center fade up after */
.dn path { stroke-dasharray: 100; stroke-dashoffset: 100; transition: stroke-dashoffset .95s cubic-bezier(.42, 0, .2, 1); }
.dn.is-drawn path { stroke-dashoffset: 0; }
.dn .dn__lead, .dn .dn__lbl, .dn .dn__pct, .dn .dn__cen { opacity: 0; transition: opacity .5s ease; }
.dn.is-drawn .dn__lead, .dn.is-drawn .dn__lbl, .dn.is-drawn .dn__pct, .dn.is-drawn .dn__cen { opacity: 1; transition-delay: .55s; }
@media (prefers-reduced-motion: reduce) {
  .dn path { transition: none; stroke-dashoffset: 0; }
  .dn .dn__lead, .dn .dn__lbl, .dn .dn__pct, .dn .dn__cen { transition: none; opacity: 1; }
}

.h-1 { font-family: var(--display); font-size: clamp(1.5rem, 2.4vw, 1.75rem); font-weight: 500; letter-spacing: -0.02em; }  /* 28px */
.h-2 { font-family: var(--display); font-size: clamp(1.375rem, 2vw, 1.5rem); font-weight: 600; letter-spacing: -0.015em; }   /* 24px */
.h-3 { font-family: var(--display); font-size: 1.25rem; font-weight: 600; letter-spacing: -0.01em; }                          /* 20px */
.study__title { font-family: "Averia Serif Libre", var(--display); font-size: clamp(1.375rem, 2vw, 1.5rem); font-weight: 700; letter-spacing: -0.01em; }  /* 24px */
.board__title { font-family: var(--display); font-style: normal; font-size: 1.375rem; font-weight: 600; letter-spacing: -0.01em; }    /* 22px */
.cta-band__title { font-size: clamp(1.5rem, 2.2vw, 1.625rem); }                                       /* 26px */
.prose h2 { font-family: var(--display); font-style: normal; font-size: clamp(1.375rem, 2vw, 1.625rem); font-weight: 600; letter-spacing: -0.015em; }
.hero__lead-col .lead, .lead { font-size: 1rem; }                                                     /* 16px subhead */

/* The name wordmark — Fraunces italic, a signature feel */
.brand__name { font-family: "Averia Serif Libre", var(--display); font-style: normal; font-weight: 700; letter-spacing: 0; white-space: nowrap; }

/* Labels keep their original color, just switch mono → Inter */
.eyebrow { font-family: var(--serif); font-weight: 600; letter-spacing: .12em; }
.status  { font-family: var(--serif); letter-spacing: .10em; }
.serif-accent { font-style: normal; font-weight: 600; }

/* Logo mark before the wordmark in the nav. */
.brand { gap: 9px; }
.brand__mark {
  flex: none; display: block; width: 28px; height: 28px;
  border-radius: 8px; overflow: hidden; line-height: 0;
  box-shadow: 0 2px 6px rgba(13,26,64,.18);
  transition: transform .35s var(--ease, ease);
}
.brand__mark svg { width: 100%; height: 100%; display: block; }
.brand:hover .brand__mark { transform: rotate(-6deg); }   /* gentle tilt only — no scale, so the bar never looks taller */

/* logo mark = profile photo + rotating ring (replaces the "S" wordmark) */
.brand__mark.brand__mark--pfp {
  width: 46px; height: 46px; border-radius: 50%;
  background: transparent; box-shadow: none; overflow: visible; position: relative;
}
.brand__mark--pfp .brand__ring { position: absolute; inset: 0; width: 100%; height: 100%; display: block; overflow: visible; }
.brand__ring-band { fill: none; stroke: #1c1c1c; stroke-width: 20; }
.brand__ring-txt { fill: #fff; font-family: var(--display); font-weight: 700; font-size: 13.5px; letter-spacing: 1.5px; }
.brand__avatar {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 30px; height: 30px; border-radius: 50%; overflow: hidden;
}
.brand__avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.brand:hover .brand__mark--pfp { transform: scale(1.05); }   /* ring already spins — no tilt */

/* Profile cluster: avatar with a tooltip-style status bubble at its top-right. */
.hero__id {
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;                                   /* avatar → status (nets 32 to the pill) */
  margin-top: 16px;                            /* lead offset (card padding-top → avatar) */
  margin-bottom: 20px;                         /* status → heading */
}
/* ---- Tooltip component, centered below the avatar, pointing up at it ---- */
.hero__id .status-slot {
  position: relative; width: auto; margin: 0; white-space: nowrap;
}
/* bare availability line — no chip; the dot alone carries the "live" signal */
.hero__id .status-slot .status {
  position: relative;
  background: transparent;
  color: var(--ink, #0c0d12);
  border: none;
  border-radius: 0;
  margin: 0;
  padding: 0;
  font-size: clamp(0.8125rem, 1.25vw, 1rem); font-weight: 600; letter-spacing: normal;   /* 16px cap, reached exactly @1280 */
  box-shadow: none;
}

/* live dot: a steady core with a radar ring pinging outward from under it.
   The ring is a ::after so the core stays crisp while the ring scales. */
.hero__id .status-slot .status__dot {
  position: relative;
  width: 8px; height: 8px;
  background: #22c55e;
  box-shadow: 0 0 0 2px rgba(34, 197, 94, .16);
  animation: status-glow 2.4s ease-in-out infinite;
}
.hero__id .status-slot .status__dot::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 50%;
  background: #22c55e;
  animation: status-ping 2.4s cubic-bezier(0, 0, .2, 1) infinite;
}
@keyframes status-ping {
  0%        { transform: scale(1);   opacity: .5; }
  70%, 100% { transform: scale(3.4); opacity: 0; }
}
@keyframes status-glow {
  0%, 100% { box-shadow: 0 0 0 2px rgba(34, 197, 94, .16); }
  50%      { box-shadow: 0 0 0 4px rgba(34, 197, 94, .28); }
}
/* must match the selector specificity above, or the guard loses the cascade */
@media (prefers-reduced-motion: reduce) {
  .hero__id .status-slot .status__dot { animation: none; }
  .hero__id .status-slot .status__dot::after { animation: none; display: none; }
}

/* Small circular profile avatar, now sitting beside the chip. */
.hero__avatar {
  display: block; margin: 0; flex: none;
  position: relative;
  width: clamp(96px, 9vw, 112px); aspect-ratio: 1;
  border-radius: 50%; overflow: hidden;
  border: 3px solid rgba(234, 242, 255, .92);   /* very light blue ring */
  background: radial-gradient(circle at 50% 35%, #2c2f36, #0d0f13);
  box-shadow: 0 3px 10px -6px rgba(13,26,64,.16);   /* softer — no longer floats */
}
.hero__avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hero__avatar.is-empty::after { content: "S"; position: absolute; inset: 0; display: grid; place-items: center; color: #fff; font-family: var(--display); font-weight: 600; font-size: 1.25rem; }

/* hero avatar wrapper (the old rotating curved-text ring has been removed) */
.hero__pfp {
  position: relative;
  width: 80px; aspect-ratio: 1; margin: 0 auto;
}
.hero__pfp .hero__avatar {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 1;
  width: 100%;
}

/* ---- hero entrance: badge pops, then pill / heading / sub / CTAs / logos rise in (staggered) ---- */
@keyframes heroRise { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
@keyframes heroPop    { from { opacity: 0; transform: translateY(14px) scale(.7); } to { opacity: 1; transform: translateY(0) scale(1); } }
.hero__pfp             { animation: heroPop  .8s cubic-bezier(.34, 1.32, .5, 1) both; }   /* clear scale-up pop */
.hero__id .status-slot { animation: heroRise .6s  cubic-bezier(.22, 1, .36, 1) .18s both; }
.hero__title           { animation: heroRise .7s  cubic-bezier(.22, 1, .36, 1) .30s both; }
.hero__sub             { animation: heroRise .7s  cubic-bezier(.22, 1, .36, 1) .44s both; }
.hero__cta             { animation: heroRise .7s  cubic-bezier(.22, 1, .36, 1) .58s both; }
.trusted               { animation: heroRise .7s  cubic-bezier(.22, 1, .36, 1) .70s both; }
@media (prefers-reduced-motion: reduce) {
  .hero__pfp, .hero__id .status-slot, .hero__title, .hero__sub, .hero__cta, .trusted { animation: none; }
}

@media (max-width: 620px) {
  .brand { gap: 8px; }
}

/* ----------------------------- Buttons --------------------------- */
/* Anything clickable uses the General Sans display face (matches headings) */
.btn, .nav__links a, .study__btn, .link-arrow, .chip, .back-pill,
.fun__title, .footer__col a, .footer__copy + a, .footer a {
  font-family: var(--display);
}

/* Clay shape only (12px radius, compact heights). Colors come from
   the original style.css rules (blue). */
.btn {
  height: 34px; padding: 0 16px;
  border-radius: var(--radius-sm);
  font-size: 0.875rem; font-weight: 500;
  line-height: 1; gap: 6px;
}
.btn .ar { width: 14px; height: 14px; }

.brand__mark { border-radius: var(--radius-sm); font-style: normal; background: #000000; }   /* text-S mark = pure black */

/* Narrow the nav pill to match the projects width (840px) below.
   Three-zone header: brand (left) · nav links (centred) · CTA (right).
   nav__links is flattened with display:contents so its links + CTA place
   directly into this grid; the two 1fr edge columns keep the 4 links
   optically centred on the bar regardless of logo / CTA widths. */
.nav__inner {
  max-width: 760px; margin-inline: auto; width: 100%;
  display: grid;
  grid-template-columns: 1fr auto auto auto auto 1fr;
  align-items: center;
  /* solid dark bar — same firm tone scrolled or not */
  border-radius: var(--pill);   /* fully rounded pill ends */
  background: rgba(28, 28, 28, .94);
  backdrop-filter: blur(8px) saturate(140%);
  -webkit-backdrop-filter: blur(8px) saturate(140%);
  border-color: rgba(255, 255, 255, .10);
}
.nav__inner > .brand { justify-self: start; }
.nav__links { display: contents; }
.nav__links a.nav__cta { justify-self: end; }
.nav.is-stuck .nav__inner {
  background: rgba(28, 28, 28, .94);   /* unchanged on scroll — only the shadow firms up */
  border-color: rgba(255, 255, 255, .10);
  box-shadow: 0 8px 28px -14px rgba(0, 0, 0, .55);
}
/* Selection underline: the same feathered thread of light, now parked under the
   active nav link and sliding to the next one when the selection changes.
   Position and width come from --nav-ink-*, measured in main.js. */
.nav__inner { position: relative; }
.nav__inner::after {
  content: ""; position: absolute; left: 0; bottom: 4px;
  width: var(--nav-ink-w, 0px); height: 2px; border-radius: 2px;
  transform: translateX(var(--nav-ink-x, 0px));
  opacity: var(--nav-ink-o, 0);
  /* core matches the selected label exactly (#fff); only the ends feather out */
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0),
    #ffffff 25%,
    #ffffff 75%,
    rgba(255, 255, 255, 0));
  transition: transform .45s cubic-bezier(.22, 1, .36, 1),
              width     .45s cubic-bezier(.22, 1, .36, 1),
              opacity   .3s ease;
  pointer-events: none;
}
/* first paint places it without a slide in from x=0 */
.nav__inner.nav-ink-init::after { transition: none; }
@media (prefers-reduced-motion: reduce) {
  .nav__inner::after { transition: opacity .3s ease; }
}
/* the inline links collapse into the hamburger panel below 820px */
@media (max-width: 820px) {
  .nav__inner::after { display: none; }
}

/* ---- header motion: drop-in on load + hide-on-scroll-down / reveal-on-scroll-up ---- */
.nav { transition: transform .42s cubic-bezier(.22, 1, .36, 1); will-change: transform; }
.nav.nav--hidden { transform: translateY(calc(-100% - 80px)); }   /* slides the pill up off-screen */

@keyframes navDrop   { from { opacity: 0; transform: translateY(-120%); } to { opacity: 1; transform: translateY(0); } }
@keyframes navItemIn { from { opacity: 0; transform: translateY(-9px); }  to { opacity: 1; transform: translateY(0); } }
/* brand mark: springy bounce-in — pops past full size, squashes, then settles */
@keyframes brandPop {
  0%   { opacity: 0; transform: scale(0) rotate(-10deg); }
  55%  { opacity: 1; transform: scale(1.22) rotate(4deg); }
  75%  { transform: scale(.92) rotate(-1deg); }
  90%  { transform: scale(1.05); }
  100% { opacity: 1; transform: scale(1) rotate(0); }
}
.nav__inner { animation: navDrop .65s cubic-bezier(.22, 1, .36, 1) both; }
.nav__inner .brand { animation: navItemIn .5s ease .20s both; }
.nav__inner .brand__mark { animation: brandPop .75s cubic-bezier(.34, 1.56, .5, 1) .30s both; transform-origin: center; }
.nav__links a.nav__cta { animation: navItemIn .5s ease .40s both; }   /* only the CTA fades in; the text links stay static on load */
.nav__toggle { animation: navItemIn .5s ease .30s both; }
@media (prefers-reduced-motion: reduce) {
  .nav, .nav__inner, .nav__inner .brand, .nav__inner .brand__mark, .nav__inner .brand__name, .nav__links a, .nav__toggle { animation: none; transition: none; }
}

/* Resume CTA — outlined "ghost" button, rounded-rect corners (our button radius) */
.nav__links a.nav__cta {
  border-radius: var(--radius-sm);
  height: 38px; padding: 0 20px; gap: 6px;
  display: inline-flex; align-items: center; justify-content: center; white-space: nowrap;
  font-family: var(--sans); font-size: 1.125rem; font-weight: 500;
  background: #ffffff;
  color: #1a1a1c;
  border: 1px solid transparent;
  box-shadow: none;
  position: relative; overflow: hidden; isolation: isolate;   /* for the slide-up fill */
}
/* hover: a dark panel slides up from the bottom to cover it (ref clip) */
.nav__links a.nav__cta::before {
  content: "Let’s chat";
  position: absolute; inset: 0; z-index: 2;
  display: grid; place-items: center;
  background: #1c1c1c; color: #fff;
  border-radius: var(--radius-sm);
  font: inherit; letter-spacing: inherit; white-space: nowrap;
  transform: translateY(101%);
  transition: transform .7s cubic-bezier(.4, 0, .2, 1);
}
.nav__links a.nav__cta:hover::before { transform: translateY(0); }
.nav__links a.nav__cta:hover { background: #ffffff; color: #1a1a1c; box-shadow: 0 4px 14px -6px rgba(0,0,0,.5); }

/* Nav links: two-layer text flip (grey slides up & out, white rises in) */
.nav__links a:not(.nav__cta) {
  display: inline-flex; align-items: center;
  background: transparent; box-shadow: none; color: #b7b7bb;
}
.nav__links a:not(.nav__cta):hover,
.nav__links a:not(.nav__cta).is-active,
.nav__links a:not(.nav__cta).is-current {
  background: transparent; transform: none; box-shadow: none;
}
/* current section: the link's label simply rises to the brightest white */
.nav__links a:not(.nav__cta).is-current .nav__label::before,
.nav__links a:not(.nav__cta).is-active  .nav__label::before { color: #ffffff; }
/* the flip lives on the label so the icon stays put */
.nav__label {
  position: relative; overflow: hidden; display: inline-block;
  color: transparent;   /* real text only sizes the box; the two layers below are visible */
}
.nav__label::before,
.nav__label::after {
  content: attr(data-text);   /* per-link label so every nav item flips its own text */
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font: inherit; letter-spacing: inherit; white-space: nowrap;
  transition: transform .7s cubic-bezier(.4, 0, .2, 1);
}
.nav__label::after  { color: #b7b7bb; transform: translateY(0); }
.nav__label::before { color: #fff;    transform: translateY(120%); }
.nav__links a:not(.nav__cta):hover .nav__label::after,
.nav__links a:not(.nav__cta).is-active .nav__label::after,
.nav__links a:not(.nav__cta).is-current .nav__label::after { transform: translateY(-120%); }
.nav__links a:not(.nav__cta):hover .nav__label::before,
.nav__links a:not(.nav__cta).is-active .nav__label::before,
.nav__links a:not(.nav__cta).is-current .nav__label::before { transform: translateY(0); }
.nav__links a.nav__cta svg { width: 14px; height: 14px; }
/* dark-bar brand + hamburger go light */
.nav__inner .brand, .nav__inner .brand__name { color: #f3f3f4; }
.nav__toggle span { background: #d6d6da; }
/* collapse to a hamburger + dark dropdown before the 4-link inline nav can overflow
   the bar (~820px). Dark panel matches the bar so the light link text stays readable. */
@media (max-width: 820px) {
  /* revert the desktop three-zone grid → simple flex bar with dropdown */
  .nav__inner { display: flex; justify-content: space-between; }
  .nav__toggle { display: block; }
  .nav__links {
    display: flex;   /* restore box from desktop's display:contents so the dropdown renders */
    position: fixed; inset: 88px 16px auto; flex-direction: column; align-items: stretch;
    background: rgba(24, 24, 26, .98);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    border: 1px solid rgba(255, 255, 255, .12); border-radius: var(--radius);
    padding: 8px; gap: 2px;
    box-shadow: 0 20px 50px -22px rgba(0, 0, 0, .65);
    transform-origin: top; transform: scaleY(.9); opacity: 0;
    pointer-events: none; transition: opacity .25s, transform .25s;
  }
  .nav__links.is-open { opacity: 1; transform: none; pointer-events: auto; }
  .nav__links a:not(.nav__cta) { padding: 12px 16px; border-radius: var(--radius-sm); }
  .nav__links a.nav__cta { margin-top: 6px; justify-content: center; width: 100%; }
}
.study__btn {
  border-radius: var(--radius-sm);
  height: 34px; padding: 0 14px; font-size: 0.875rem;
}
.study__btn:hover { transform: none; }

.chip {
  height: 40px; padding: 0 20px;
  display: inline-flex; align-items: center;
  font-size: 1rem; font-weight: 500; letter-spacing: -0.01em;
  border-radius: 9999px;
}
/* Work page: centre the filter chips and tighten the gap below the header */
.section:has(.sec-head--filters) { padding-top: clamp(24px, 4vw, 56px); }

/* Every page that offers a way back opens at the SAME height. The pill is the
   first thing under the nav, so its top must not depend on what happens to
   follow it — and it did: the section clamp gave 51px on work.html, 115px on
   qualify/learnings/case-study and 26px on the four image-based studies (which
   set their own `.section` rule), so the button jumped by up to 90px between
   pages. This matches work.html's value; the 0,2,0 specificity of :has() is
   what lets it win over the case studies' own single-class overrides. */
.section:has(> .back-pill) { padding-top: clamp(24px, 4vw, 56px); }
.sec-head--filters { max-width: none; text-align: center; }
.sec-head--filters .filters { justify-content: center; }

/* Filter chips get the nav CTA’s hover: a dark panel slides up from the bottom
   and covers the chip, plus a spring zoom borrowed from .back-pill. The CTA can
   hard-code its label in CSS because there is only one of it — these five carry
   their word in data-label (set in main.js) so ::before can render attr(). */
.filters .chip {
  /* one step down from the base .chip (16px/40px): 14px on the site’s small step,
     34px tall and 16px side padding — the same measurements as .back-pill, which
     now sits directly above this row. */
  height: 34px; padding: 0 16px;
  font-size: 0.875rem;
  position: relative; overflow: hidden; isolation: isolate;
  transform-origin: center;
  transition: transform .4s cubic-bezier(.34, 1.56, .5, 1), box-shadow .35s ease,
              border-color .35s ease, background .25s ease, color .25s ease;
}
.filters .chip::before {
  content: attr(data-label);
  position: absolute; inset: 0; z-index: 2;
  display: grid; place-items: center;
  background: #1c1c1c; color: #fff;
  border-radius: inherit;
  font: inherit; letter-spacing: inherit; white-space: nowrap;
  transform: translateY(101%);
  transition: transform .7s cubic-bezier(.4, 0, .2, 1);
}
.filters .chip:hover::before,
.filters .chip:focus-visible::before { transform: translateY(0); }
.filters .chip:hover,
.filters .chip:focus-visible {
  transform: scale(1.06);
  border-color: rgba(12, 13, 18, .30);
  box-shadow: 0 14px 28px -14px rgba(28, 28, 28, .35);
}
.filters .chip:active { transform: scale(.99); }
/* the selected chip is already dark — no panel to slide, just the zoom */
.filters .chip.is-active::before { content: none; }
@media (prefers-reduced-motion: reduce) {
  .filters .chip, .filters .chip::before { transition: none; }
  .filters .chip:hover { transform: none; }
  .filters .chip:hover::before { transform: translateY(101%); }
}
.hero__tags li { border-radius: 9999px; font-size: 0.875rem; }
/* "Back to work" — outline recipe, at the BASE .btn size (34px / 14px).
   It's a secondary way out of the page, not a primary CTA, so it sits one
   size step below the 44px "Next case study" button at the foot. */
/* Back to work is the same ghost button as the hero résumé CTA, and behaves
   the same on hover: spring zoom, firmer edge, lifted shadow, and an arrow
   that is hidden at rest and slides in. Mirrored, because this arrow sits to
   the left of the label and points back. */
.back-pill {
  height: 34px; padding: 0 16px;
  display: inline-flex; align-items: center; gap: 0;
  font-size: 0.875rem; font-weight: 500;
  border-radius: var(--radius-sm);
  background: transparent; color: var(--ink, #0c0d12);
  border: 1px solid rgba(12,13,18,.30);
  box-shadow: none;
  transform-origin: center;
  transition: transform .4s cubic-bezier(.34, 1.56, .5, 1), box-shadow .35s ease, border-color .35s ease;
}
/* the arrow stays visible at rest — it is the affordance that says "back" —
   and only nudges on hover */
.back-pill .ar {
  flex: none; width: 14px; height: 14px; margin-right: 8px;
  transition: transform .35s var(--ease, ease);
}
.back-pill:hover,
.back-pill:focus-visible {
  transform: scale(1.06);
  color: var(--ink, #0c0d12);
  border-color: rgba(12,13,18,.48);
  box-shadow: 0 14px 28px -14px rgba(28, 28, 28, .35);
}
.back-pill:hover .ar,
.back-pill:focus-visible .ar { transform: translateX(-3px); }
.back-pill:active { transform: scale(.99); }
@media (prefers-reduced-motion: reduce) {
  .back-pill, .back-pill .ar { transition: none; }
  .back-pill:hover { transform: none; }
}

/* "Next case study" — homepage primary-button recipe ("View all projects"),
   scoped to the case-study footers so card "Explore" links stay text links */
.mt-l .link-arrow, .q-next .link-arrow {
  height: 44px; padding: 0 24px; gap: 0;
  display: inline-flex; align-items: center;
  font-size: 1.125rem; font-weight: 600; color: #fff;
  border-radius: var(--radius-sm);
  background: linear-gradient(135deg, #3a3a3a 0%, #1c1c1c 60%, #0e0e0e 100%);
}
.mt-l .link-arrow:hover, .q-next .link-arrow:hover { background: linear-gradient(135deg, #454545 0%, #232323 60%, #121212 100%); }
/* arrow reveals + slides in on hover, exactly like "View all projects" */
.mt-l .link-arrow .ar, .q-next .link-arrow .ar {
  width: 0; opacity: 0; margin-left: 0; transform: translateX(-6px); overflow: hidden;
  transition: width .35s var(--ease), opacity .25s ease, margin-left .35s var(--ease), transform .35s var(--ease);
}
.mt-l .link-arrow:hover .ar, .q-next .link-arrow:hover .ar { width: 15px; opacity: 1; margin-left: 7px; transform: translateX(0); }
.field input, .field textarea { border-radius: var(--radius-sm); }

/* Align neighbouring nav + link typography with the compact buttons */
.nav__links a:not(.nav__cta) { font-family: var(--sans); font-size: 1rem; font-weight: 500; padding: 8px 12px; gap: 6px; }   /* 16px, tighter so 4 links + Resume fit the bar */
.link-arrow { font-size: 0.875rem; }
/* hero CTAs — 18px text to match the header nav (Work / Resume), matching height */
.hero__cta .btn { height: 44px; font-size: 1.125rem; }

/* "Let's chat" hover: no colour change — it pops (springy scale + lift + glow) and reveals an arrow */
.cta-chat { gap: 0; background: linear-gradient(135deg, #3a3a3a 0%, #1c1c1c 60%, #0e0e0e 100%); transform-origin: center; transition: transform .4s cubic-bezier(.34, 1.56, .5, 1), box-shadow .35s ease; }   /* heading-grey gradient */
.cta-chat__ar {
  width: 0; opacity: 0; margin-left: 0;
  transform: translateX(-6px);
  transition: width .35s var(--ease, ease), opacity .25s, margin-left .35s var(--ease, ease), transform .35s var(--ease, ease);
}
.cta-chat:hover,
.cta-chat:focus-visible {
  background: linear-gradient(135deg, #454545 0%, #232323 60%, #121212 100%);   /* gradient lifts slightly on hover */
  transform: scale(1.06);   /* balanced zoom from the centre — no vertical bias */
  box-shadow: 0 14px 28px -12px rgba(28, 28, 28, .7);
}
.cta-chat:hover .cta-chat__ar,
.cta-chat:focus-visible .cta-chat__ar { width: 17px; opacity: 1; margin-left: 7px; transform: translateX(0); }
.cta-chat:active { transform: scale(.99); }
@media (prefers-reduced-motion: reduce) {
  .cta-chat, .cta-chat__ar { transition: none; }
  .cta-chat:hover { transform: none; }
}

.btn--outline { background: transparent; color: var(--ink); border: 1px solid rgba(12,13,18,.30); }   /* firmer than --line-2: the ghost CTA needs a readable edge */
.btn--outline:hover { background: transparent; color: var(--ink); border-color: rgba(12,13,18,.48); box-shadow: var(--shadow-sm); }

/* hero "Copy email" button — borderless; copies the address, swaps to a check + "Copied" */
.hero__copy { font-family: inherit; cursor: pointer; border: none; }
.hero__copy .ico-copy { transform-origin: center; transition: transform .7s cubic-bezier(.4, 0, .2, 1), color .3s var(--ease); }
.hero__copy:hover { background: transparent; box-shadow: none; transform: translateY(-1px); }

/* "Copy email" label: two-layer text flip like Work — ink slides up & out, blue rises in */
.hero__copy .lbl-copy {
  position: relative; overflow: hidden;
  display: inline-block; color: transparent;
  padding: 2px 0;   /* breathing room so each layer fully clears the box on flip */
}
.hero__copy .lbl-copy::before,
.hero__copy .lbl-copy::after {
  content: "Copy email";
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font: inherit; letter-spacing: inherit; white-space: nowrap;
  transition: transform .7s cubic-bezier(.4, 0, .2, 1);
}
.hero__copy .lbl-copy::after  { color: var(--ink, #0c0d12);   transform: translateY(0); }
.hero__copy .lbl-copy::before { color: #000; transform: translateY(120%); }
.hero__copy:hover .lbl-copy::after  { transform: translateY(-120%); }
.hero__copy:hover .lbl-copy::before { transform: translateY(0); }
.hero__copy:hover .ico-copy { transform: rotateX(-360deg) scale(1.06); color: #000; }   /* icon flips opposite to the label rise + turns pure black */
.hero__copy .ico-check, .hero__copy .lbl-done { display: none; }
.hero__copy .ico-check { color: #0f9d57; }
.hero__copy.is-copied { color: #0f9d57; border-color: #bfe6cf; }
.hero__copy.is-copied .ico-copy, .hero__copy.is-copied .lbl-copy { display: none; }
.hero__copy.is-copied .ico-check, .hero__copy.is-copied .lbl-done { display: inline; }
.hero__cta .link-arrow {
  height: 40px; padding: 0 18px;
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--brand, #1c1c1c);
  border-radius: var(--radius-sm, 12px);
  background: transparent; color: var(--brand, #1c1c1c);
  font-size: 1rem; font-weight: 600;
  transition: background .25s ease, color .25s ease, border-color .25s ease;
}
.hero__cta .link-arrow:hover { background: var(--brand-soft, rgba(23,24,28,.10)); }
.hero__cta .link-arrow .ar { width: 15px; height: 15px; }

/* ---- Typography floor = 14px: raise every 12px micro-label ---- */
.eyebrow, .status, .meta__k, .study__meta-k, .gcard__tag,
.work-item__cap .k, .contact-list .k, .cs-hero-media,
.hero__photo.is-empty::after, .portrait {
  font-size: 0.875rem;   /* 12px → 14px */
}

/* availability status — floating white pill */
.hero__lead-col .status { margin-top: clamp(24px, 3vw, 32px); margin-bottom: 0; }
.status, .hero__lead-col .status {
  font-family: var(--sans);
  font-size: clamp(0.875rem, 1.667vw, 1.5rem); font-weight: 600;   /* 24px at 1440 */
  text-transform: none; letter-spacing: -0.005em;
  gap: .5em;
  padding: 6px 14px 6px 11px;
  background: #fff;
  border: 1px solid rgba(13,26,64,.05);
  border-radius: var(--pill, 999px);
  box-shadow: 0 6px 20px -6px rgba(13,26,64,.16), 0 1px 2px rgba(13,26,64,.06);
  color: var(--ink, #0d1a40);
}
.status__label { white-space: nowrap; color: #0c0d12; }   /* matches the "View case study" ink */
/* larger dot with a soft halo ring — gentle breathing pulse */
.status .status__dot {
  width: 10px; height: 10px;
  background: #3fbf6b;
  box-shadow: 0 0 0 3px rgba(63,191,107,.18);
  animation: status-breathe 2.4s ease-in-out infinite;
}
@keyframes status-breathe {
  0%, 100% { transform: scale(1);    opacity: 1;   box-shadow: 0 0 0 4px rgba(63,191,107,.18); }
  50%      { transform: scale(.78);  opacity: .65; box-shadow: 0 0 0 6px rgba(63,191,107,.08); }
}
@media (prefers-reduced-motion: reduce) {
  .status .status__dot { animation: none; }
}
/* rotating last word — fades/swaps every 2s. Reserve the widest word's width
   (left-aligned) so the line length stays fixed and "Open to" never shifts. */
.status__txt {
  display: inline-block; text-align: left;
  transition: opacity .28s ease, transform .28s ease;
}
.status__txt.is-swapping { opacity: 0; transform: translateY(-3px); }

/* Plain meta labels — strip mono / uppercase / letter-spacing */
.study__meta-k {
  font-family: var(--sans);
  text-transform: none;
  letter-spacing: normal;
}

/* ---- Dario-style CTA: light card + big blue button w/ circular arrow ---- */
.cta-band {
  background: var(--bg-soft);
  color: var(--ink);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
}
.cta-band::before { display: none; }
.cta-band__title { color: var(--ink); }
.cta-band p { color: var(--muted); }

/* Dario-style tactile button — blue gradient + white frame + inset
   highlight + layered shadow + grain texture overlay */
.cta-band .btn--light {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  height: auto;
  color: #fff;
  padding: 14px 16px 14px 28px;
  font-size: 1.0625rem;                 /* 17px */
  font-weight: 600;
  gap: 16px;
  border: 4px solid #fff;               /* white outer frame */
  border-radius: 16px;
  background: linear-gradient(180deg, #4a86f5 0%, #1c1c1c 70%);
  box-shadow:
    inset 0 2px 0 0 rgba(255,255,255,.28),          /* glossy top edge */
    inset 0 0 0 1px rgba(13,26,64,.30),             /* inner border */
    0 0.5px 0.5px -0.7px rgba(13,26,64,.22),        /* layered soft shadow */
    0 1.8px 1.8px -1.3px rgba(13,26,64,.22),
    0 8px 12px -2px rgba(13,26,64,.30);
  transition: box-shadow .3s, transform .3s var(--ease, ease), filter .25s;
}
/* grain/noise texture overlaid on the gradient (inline SVG, no asset) */
.cta-band .btn--light::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 150px 150px;
  opacity: .16;
  mix-blend-mode: overlay;
  pointer-events: none;
  z-index: -1;                 /* above the gradient, below the text */
}
.cta-band .btn--light:hover {
  transform: translateY(-2px);
  filter: brightness(1.04);
  box-shadow:
    inset 0 2px 0 0 rgba(255,255,255,.30),
    inset 0 0 0 1px rgba(13,26,64,.30),
    0 1px 1px -0.7px rgba(13,26,64,.22),
    0 3px 3px -1.3px rgba(13,26,64,.22),
    0 14px 22px -4px rgba(13,26,64,.36);
}
/* arrow in a white circle (above the texture), slides on hover */
.cta-band .btn--light .ar {
  position: relative; z-index: 1;
  width: 32px; height: 32px;
  padding: 8px;
  box-sizing: border-box;
  background: #fff;
  color: var(--brand);
  border-radius: 50%;
  transition: transform .3s var(--ease, ease);
}
.cta-band .btn--light:hover .ar { transform: translateX(4px); }

/* ============================================================
   "THINGS I DO FOR FUN" — fanned card arc
   Cards start stacked/flat, then fan out into the arc when the
   section scrolls into view (.reveal -> .is-in). Hover straightens
   and lifts the hovered card. Swap each card's `background` for a
   photo: background:url(assets/img/fun/xx.jpg) center/cover.
   ============================================================ */
/* sit tight under the hero (pull up over the section gap) */
#fun.section--tight { margin-top: 0; padding-top: clamp(48px, 6vw, 88px); }
/* The fan is pulled up under the hero; its (transparent) container would
   otherwise sit over the hero CTA buttons and swallow their clicks. Lift the
   hero (and its CTA) above the fun section so the buttons stay clickable. */
.hero { position: relative; z-index: 2; padding-top: clamp(18px, 2.4vw, 28px); }

/* push the hero buttons down a touch, closer to the companies row */
.hero__lead-col .hero__cta { margin-top: 20px; }   /* sub → buttons (20) */
.trusted { margin-top: 16px; }

/* ---- Hero feature row: three icon + title + description items ---- */
/* professional, descriptive subheading — two lines */
.hero__sub {
  margin: 12px auto 0;                     /* H1 → sub (12) */
  max-width: 84ch;                                  /* wider so the first line carries more */
  font-family: var(--sans);
  font-size: clamp(0.75rem, 1.6vw, 1.125rem);   /* 18px cap (reached @1125) */
  font-weight: 500; line-height: 1.55; letter-spacing: -0.005em;
  color: var(--ink, #0c0d12); text-align: center; text-wrap: normal;   /* matched to the project-card points */
}
.hero__id { position: relative; }
.hero__facts {
  display: flex; justify-content: center;
  gap: clamp(14px, 2vw, 30px);
  margin: clamp(20px, 2.6vw, 30px) auto 0;
  width: min(880px, 100%); max-width: 880px; flex-wrap: wrap;
  text-align: left;
}
.fact {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 8px; flex: 1 1 240px; max-width: 290px;
}
/* descriptions stay on one line on desktop */
.fact__d { white-space: nowrap; }
.fact__ic {
  flex: none; width: 34px; height: 34px; border-radius: var(--radius-sm);
  display: grid; place-items: center;
  background: #fff; color: var(--brand, #1c1c1c);
}
.fact__ic svg { width: 18px; height: 18px; }
.fact__t {
  font-family: var(--sans); font-size: 1.25rem; font-weight: 500;
  color: var(--ink, #0c0d12); margin: 0 0 3px; letter-spacing: -0.01em;
}
.fact__d {
  font-family: var(--sans); font-size: 1.125rem; font-weight: 400;
  color: #1a1d26; margin: 0; line-height: 1.42;
}
@media (max-width: 760px) {
  /* tablet: keep the 3 facts wrapping tidily, no vertical stretch */
  .hero__facts { gap: 16px 18px; max-width: 480px; }
  .fact { flex: 1 1 180px; }
  .fact__d { white-space: normal; }   /* allow wrap when columns get narrow */
}
@media (max-width: 620px) {
  .hero__facts { flex-direction: column; align-items: center; max-width: 300px; gap: 18px; }
  .fact { flex: 0 0 auto; max-width: none; width: 100%; }
  .hero__title { font-size: clamp(1.75rem, 7.4vw, 2.375rem); }   /* 28px floor — hero stays the apex on small screens */
  .hero__id { margin-top: 4px; margin-bottom: clamp(12px, 3vw, 16px); }
  .hero__id { margin-bottom: round(clamp(12px, 3vw, 16px), 4px); }   /* 12 @390 */
  .hero__cta { flex-wrap: wrap; justify-content: center; }
}
/* phones (≤430px): compact hero type — heading 28px, sub 14px */
@media (max-width: 430px) {
  .hero-box { padding-left: 14px; padding-right: 14px; }
  .hero__title { font-size: 1.75rem; line-height: 1.2; }
  .hero__sub { font-size: 0.875rem; line-height: 1.5; }
  .status__label, .status__txt { font-size: 0.875rem; }   /* Open to … : 14px */
  .cta-chat__lbl, .hero__cta .hero__resume { font-size: 1rem; }   /* CTAs: 16px */
  .trusted .trusted__cap { font-size: 0.625rem; }                 /* Previously worked with: 10px */
}

/* ---- "Trusted by" social-proof row: overlapping logo cluster + caption ---- */
/* ---- "Previously worked with" — continuously scrolling logo marquee ---- */
.trusted {
  margin-top: 24px;   /* buttons → divider (centred in the 48 gap) */
  display: flex; flex-direction: column; align-items: center; gap: 16px; width: 100%;   /* caption → logos */
}
/* hairline divider — centred between the buttons and the caption */
.trusted::before {
  content: ""; display: block;
  width: min(100%, 620px); height: 1px;
  background: linear-gradient(90deg, transparent, rgba(13, 26, 64, .14) 50%, transparent);
  margin-bottom: 7px;   /* divider → caption = 7 + 16 gap + 1px ≈ 24, matching the 24 above */
}
.trusted__cap {
  font-family: var(--sans); font-size: 0.75rem; font-weight: 600;   /* 12px — locked to the caption step */
  letter-spacing: .05em; text-transform: uppercase;
  color: var(--faint, #5a6273); margin: 0;
}
.marquee {
  width: 100%; max-width: 580px; overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.marquee__track {
  display: flex; align-items: center; width: max-content;
  padding: 6px 0; margin: 0; list-style: none;
  will-change: transform; backface-visibility: hidden;
}
/* animation starts only once JS has measured the real set width (main.js sets
   --marquee-w / --marquee-dur). Driving it in px instead of -50% keeps the
   speed constant — a % translate re-resolves as the images load and made the
   scroll surge, stutter, and appear to restart. */
.marquee__track.is-ready { animation: marqueeScroll var(--marquee-dur, 26s) linear infinite; }
.marquee:hover .marquee__track { animation-play-state: paused; }
/* flat black-and-white wordmark logos (dummy companies) */
.marquee__logo {
  flex: none; display: inline-flex; align-items: center; gap: 8px;
  margin-right: clamp(36px, 6vw, 64px);   /* spacing lives inside each item so translateX(-50%) loops seamlessly (flex gap left the loop half-a-gap short → visible jump) */
  color: #aab0bb;                       /* muted grey at rest */
  transition: color .3s var(--ease, ease);
}
.marquee__logo:hover { color: #3a4150; }
.logo-mark { width: 30px; height: 30px; fill: currentColor; flex: none; display: block; }
.logo-wm {
  font-family: var(--sans); font-weight: 600; font-size: 1.3125rem;
  letter-spacing: -0.005em; color: rgba(12, 13, 18, 0.60); white-space: nowrap;
  transition: color .3s var(--ease, ease);
}
.marquee__logo:hover .logo-wm { color: rgba(12, 13, 18, 0.8); }
/* real company logos, rendered as uniform dark-grey silhouettes (white/colored originals normalize).
   Heights are tuned per logo so the wordmark cap-heights read the same optical size. */
.logo-img {
  height: 24px; width: auto; display: block; flex: none;
  filter: brightness(0); opacity: .80;
  transition: opacity .3s var(--ease, ease);
}
.logo-img--forbmax   { height: 18px; opacity: .64; }  /* heavy caps lockup — solid silhouette reads bolder than the rest, so it carries less ink */
.logo-img--veroke    { height: 18px; }  /* light rounded wordmark — a touch larger */
.logo-img--sparkleo  { height: 22px; }  /* lowercase wordmark with star */
.logo-img--tradin      { height: 17px; }  /* bold wordmark */
.logo-img--fundingpips { height: 17px; }  /* long wordmark — kept under the others, but was reading too small */
.logo-img--piqla       { height: 19px; opacity: .94; }  /* wordmark (badge cropped — it flattened under brightness(0)); thin strokes read fainter than the others at the shared .80, so it carries more ink */
.logo-img--qualiphy    { height: 19px; }  /* wordmark */
.marquee__logo:hover .logo-img { opacity: .92; }
.marquee__logo:hover .logo-img--piqla { opacity: 1; }  /* already above the base .92, so it needs its own hover step */
@keyframes marqueeScroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(-1 * var(--marquee-w, 50%)), 0, 0); }
}
@media (prefers-reduced-motion: reduce) { .marquee__track.is-ready { animation: none; } }

/* ---- Hero "box": bordered container, no background ---- */
.hero-box {
  position: relative;
  border: 1px solid #e7eaf1;
  border-radius: 24px;   /* matched to the project cards */
  background: transparent;
  box-shadow: 0 1px 2px rgba(13,26,64,.04), 0 18px 50px -28px rgba(13,26,64,.22);
  padding: clamp(16px, 3vw, 24px) clamp(24px, 5vw, 72px) clamp(24px, 3vw, 32px);   /* top 24 · bottom 32 */
  overflow: hidden;
}
.hero-box > * { position: relative; z-index: 1; }

@media (max-width: 620px) {
  .hero-box { padding: clamp(36px, 10vw, 56px) clamp(20px, 6vw, 28px); border-radius: 22px; }
  .hero-box { padding: round(clamp(36px, 10vw, 56px), 4px) round(clamp(20px, 6vw, 28px), 4px); }   /* 40 · 24 @390 */
}
.fun { text-align: center; }
/* ======================================================================
   HOW I WORK (auto-advancing process) + TESTIMONIAL carousel
   modelled on murynmukha.com — rose process wheel + blue testimonial
   ====================================================================== */
.approach-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(10px, 1vw, 12px); align-items: stretch;   /* lands 12 @1280 (even, on-grid) */
}
/* entrance: chart card rises first, review card follows (hero-style stagger) */
.approach-grid.reveal { opacity: 1; transform: none; transition: none; }
.approach-grid.reveal .reach-markets,
.approach-grid.reveal .tst {
  opacity: 0; transform: translateY(22px);
  transition: opacity .85s cubic-bezier(.22, 1, .36, 1), transform .85s cubic-bezier(.22, 1, .36, 1);
}
.approach-grid.reveal.is-in .reach-markets { opacity: 1; transform: none; transition-delay: .06s; }
.approach-grid.reveal.is-in .tst           { opacity: 1; transform: none; transition-delay: .30s; }
/* inner cascade: review header rises, then the quotes */
.approach-grid.reveal .tst__head,
.approach-grid.reveal .tst__body {
  opacity: 0; transform: translateY(10px);
  transition: opacity .7s ease, transform .7s cubic-bezier(.22, 1, .36, 1);
}
.approach-grid.reveal.is-in .tst__head { opacity: 1; transform: none; transition-delay: .56s; }
.approach-grid.reveal.is-in .tst__body { opacity: 1; transform: none; transition-delay: .76s; }
@media (prefers-reduced-motion: reduce) {
  .approach-grid.reveal .reach-markets, .approach-grid.reveal .tst,
  .approach-grid.reveal .tst__head, .approach-grid.reveal .tst__body { transition: none; opacity: 1; transform: none; }
}
@media (max-width: 880px) { .approach-grid { grid-template-columns: 1fr; } }

/* ---- LEFT: process ---- */
.proc {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: clamp(8px, 1.5vw, 22px);
  background: transparent;                        /* panel colour removed */
  border: 1px solid #e7eaf1;                      /* bordered box like the hero */
  box-shadow: 0 1px 2px rgba(13,26,64,.04), 0 18px 50px -28px rgba(13,26,64,.22);
  border-radius: clamp(28px, 3vw, 44px);
  padding: clamp(20px, 2.2vw, 28px) clamp(22px, 2.4vw, 34px);
  min-height: 0;
}
/* the wheel viewport — titles ride a rotating ring inside it */
.proc__list {
  list-style: none; margin: 0; padding: 0; flex: 0 0 auto; align-self: center;
  position: relative;
  --wheel-r: 130px;                              /* ring radius → keeps ~30px between titles at the full-ring angle */
  width: clamp(196px, 20vw, 244px);
  height: clamp(196px, 21vw, 232px);             /* shorter than the fan → outer titles clip at the corners */
}
/* the active-step arrow is FIXED at the column's left-centre (it never rotates) —
   the active title just rotates to horizontal beside it */
.proc__list::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 20px; height: 20px; background: #211b1c; z-index: 3; pointer-events: none;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center/contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E") center/contain no-repeat;
}
/* the arrow kicks toward the title each time the active step changes (click or auto-advance) */
.proc__list.is-tick::before { animation: procArrowKick .6s ease-out; }
@keyframes procArrowKick {
  0%   { transform: translateY(-50%) translateX(0); }
  38%  { transform: translateY(-50%) translateX(8px); }
  100% { transform: translateY(-50%) translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  .proc__list.is-tick::before { animation: none; }
}
/* Each title is a spoke on the ring: pivot at the column's LEFT-centre, pushed out to the
   right by the radius, rotated by --ang, and CENTRED on its spoke end (translate -50%,-50%)
   so the fan opens to the right and the titles lean the opposite way. */
.proc__item {
  position: absolute; left: 0; top: 50%; margin: 0;
  transform-origin: 0 0;
  transform: rotate(var(--ang, 0deg)) translateX(var(--wheel-r)) translate(-50%, -50%);
  white-space: nowrap; letter-spacing: -0.01em;
  font-family: var(--display); font-weight: 400; font-size: 1.25rem;   /* 20px Regular */
  color: #6b6666; opacity: .4;
  transition: transform .75s var(--ease, cubic-bezier(.34,.12,.2,1)),
              filter .55s ease, opacity .55s ease, color .5s ease;
  will-change: transform, filter, opacity;
}
.proc__item.is-active {
  color: #211b1c; opacity: 1; filter: none; font-weight: 600; z-index: 2;
}
.proc__label { white-space: nowrap; display: inline-block; }   /* inline-block so the push transform applies */
/* active title: the whole selected word is blue */
.proc__item.is-active .proc__label {
  color: #2f6ad0;
  -webkit-text-fill-color: #2f6ad0;
  background: none;
}
/* when a new title lands, the arrow's kick "shoves" it right then it settles back
   (peaks just after the arrow, so it reads as the arrow pushing the title) */
.proc__list.is-tick .proc__item.is-active .proc__label { animation: procTitlePush .6s ease-out; }
@keyframes procTitlePush {
  0%   { transform: translateX(0); }
  46%  { transform: translateX(5px); }
  100% { transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  .proc__list.is-tick .proc__item.is-active .proc__label { animation: none; }
}

/* light-blue description card — centred, with symmetric "echo" layers peeking above + below */
.proc__card {
  position: relative; flex: 1 1 auto; align-self: center; max-width: 280px;
  background: #e8f1ff; border-radius: 28px;
  padding: clamp(24px, 2.6vw, 34px) clamp(20px, 2vw, 26px);
  font-family: var(--sans); font-size: 1.125rem; font-weight: 500; line-height: 1.5; color: var(--ink, #0c0d12);
}
/* line icon above the description — swaps in sync with the words */
.proc__icon {
  display: block; width: 30px; height: 30px; margin-bottom: 16px; color: var(--brand);
  transition: opacity .22s ease, transform .4s cubic-bezier(.22,.61,.36,1), filter .22s ease;
}
.proc__icon svg { width: 100%; height: 100%; display: block; }
.proc__icon.is-swap  { opacity: 0; transform: translateY(-10px); filter: blur(2.5px); }
.proc__icon.is-enter { opacity: 0; transform: translateY(12px);  filter: blur(2.5px); transition: none; }
/* only the words animate on swap — they rise up + soft-blur out, the new line rises in from below */
.proc__d {
  display: block;
  transition: opacity .22s ease, transform .4s cubic-bezier(.22,.61,.36,1), filter .22s ease;
}
.proc__d.is-swap  { opacity: 0; transform: translateY(-10px); filter: blur(2.5px); }
.proc__d.is-enter { opacity: 0; transform: translateY(12px);  filter: blur(2.5px); transition: none; }
@media (prefers-reduced-motion: reduce) {
  .proc__d, .proc__d.is-swap, .proc__d.is-enter,
  .proc__icon, .proc__icon.is-swap, .proc__icon.is-enter { transition: none; filter: none; transform: none; }
}
/* the stacked echoes: narrower + taller than the card, centred, same hue fading back */
.proc__card::before, .proc__card::after {
  content: ""; position: absolute; left: 0; right: 0; border-radius: 22px;
  background: #dbe8ff;
}
.proc__card::before { left: 26px; right: 26px; top: -15px; bottom: -15px; z-index: -1; opacity: .5; }
.proc__card::after  { left: 48px; right: 48px; top: -29px; bottom: -29px; z-index: -2; opacity: .28; }

/* ---- RIGHT: testimonial ---- */
.tst {
  display: flex; flex-direction: column; gap: clamp(14px, 1.5vw, 18px);
  background: transparent; border-radius: var(--radius-lg, 24px);   /* on-system with every other card */
  border: 1px solid #e7eaf1;                                        /* bordered box like the hero */
  box-shadow: 0 1px 2px rgba(28,28,28,.04), 0 10px 28px -22px rgba(28,28,28,.22);   /* shared container lift — same recipe as .exp-list */
  padding: clamp(16px, 1.7vw, 24px) clamp(20px, 2.2vw, 28px);
  padding: round(clamp(16px, 1.7vw, 24px), 4px) round(clamp(20px, 2.2vw, 28px), 4px);   /* 20 · 28 @1280 */
  justify-content: center;
}
.tst__head { display: flex; align-items: center; gap: 12px; }
.tst__avatar {
  flex: none; width: 52px; height: 52px; border-radius: 50%;
  display: grid; place-items: center; overflow: hidden;
  background: radial-gradient(circle at 50% 35%, #3a3a3a, #1c1c1c);
  color: #fff; font-family: var(--sans); font-weight: 700; font-size: 1.0625rem;
  box-shadow: 0 2px 8px -3px rgba(13,26,64,.3);
}
.tst__avatar img { width: 100%; height: 100%; object-fit: cover; }
.tst__who { display: flex; flex-direction: column; line-height: 1.3; }
.tst__name { font-family: var(--sans); font-weight: 600; font-size: 1.125rem; color: var(--ink, #0c0d12); }   /* was #1c1517 — a stray reddish near-black */
.tst__role { font-family: var(--sans); font-weight: 500; font-size: 1rem; color: var(--faint, #5a6273); }
.tst__nav {
  margin-left: auto; display: flex; align-items: center; gap: 8px;
  padding: 4px 6px 4px 18px; background: #f6f7f9; border-radius: var(--radius-sm);   /* chip grey */
  overflow: visible;
}
.tst__btn {
  width: 44px; height: 44px; border-radius: var(--radius-sm); border: none; cursor: pointer;
  display: grid; place-items: center;
  transition: background .25s ease, color .25s ease, transform .25s ease;
}
.tst__btn[data-tst-prev] { background: transparent; box-shadow: none; color: #1c1c1c; }
.tst__btn[data-tst-next] {
  width: 44px; height: 44px; border-radius: var(--radius-sm); background: #fff; color: #1c1517;   /* matches the 44px button system */
  box-shadow: 0 2px 8px -2px rgba(13,26,64,.22);
}
.tst__btn:hover { background: var(--brand, #1c1c1c); color: #fff; transform: translateY(-1px); }
.tst__body { margin: 0; transition: opacity .4s ease, transform .4s ease; }
.tst__body.is-swap { opacity: 0; transform: translateY(8px); }
.tst__body p {
  font-family: var(--sans); font-size: 1.125rem; font-weight: 500; line-height: 1.5;   /* 18px */
  color: var(--ink, #0c0d12); margin: 0 0 10px;
}
.tst__body p:last-child { margin-bottom: 0; }

/* tablet (single grid column, so the process panel is full-width): keep the wheel
   and description side-by-side like desktop and let the card fill the wide row
   instead of being capped to its narrow desktop chip width */
@media (max-width: 880px) and (min-width: 621px) {
  .proc__card { max-width: none; }
}

/* phone: a symmetric STACK of 5 titles. The active title sits flat at the
   bottom-centre with a down-arrow; its two coming/going pairs climb the left and
   right sides, each pair LEVEL with each other (same height). Each side stays in a
   near-vertical column (by --sgn, not off × step) so the outer pair can't fly off
   the card — with a slight outward fan toward the corners. Description card below. */
@media (max-width: 620px) {
  .proc { min-height: 0; flex-direction: column; align-items: stretch; gap: clamp(18px, 4vw, 26px); }
  .proc__list {
    --step-x: clamp(68px, 18.5vw, 82px);  /* how far each side sits from centre — wide enough that a levelled pair clears in the middle */
    --fan: 3px;                            /* slight extra outward shift for the 2nd (outer) pair, toward the corners */
    --step-y: 30px;                        /* vertical gap between the stacked rows */
    --active-y: 88px;                      /* the active title's distance from the top of the wheel area */
    align-self: stretch; width: 100%;
    height: 132px;
    margin: -4px 0 0;
  }
  /* side = --sgn (−1 / 0 / +1); row height = --dist. A pair shares its dist, so it sits
     level; the active (sgn 0, dist 0) is centred at the bottom. */
  .proc__item {
    left: 50%; top: 0; transform-origin: 0 0;
    transform:
      translate( calc(var(--sgn, 0) * (var(--step-x) + (var(--dist, 0) - 1) * var(--fan))),
                 calc(var(--active-y) - var(--dist, 0) * var(--step-y)) )
      rotate( calc(var(--off, 0) * 2.5deg) )
      translate(-50%, -50%);
    font-size: clamp(1.0625rem, 4.4vw, 1.25rem);
  }
  /* the indicator moves to the bottom-centre, under the active title, pointing DOWN */
  .proc__list::before {
    left: 50%; top: auto; bottom: 8px; transform: translateX(-50%);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14M6 13l6 6 6-6'/%3E%3C/svg%3E") center/contain no-repeat;
            mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14M6 13l6 6 6-6'/%3E%3C/svg%3E") center/contain no-repeat;
  }
  .proc__list.is-tick::before { animation: procArrowKickDown .6s ease-out; }
  .proc__list.is-tick .proc__item.is-active .proc__label { animation: procTitlePushDown .6s ease-out; }
  .proc__card { max-width: none; align-self: stretch; }
}
/* vertical variants of the kick/push so they read with the down-pointing arrow */
@keyframes procArrowKickDown {
  0%   { transform: translateX(-50%) translateY(0); }
  38%  { transform: translateX(-50%) translateY(6px); }
  100% { transform: translateX(-50%) translateY(0); }
}
@keyframes procTitlePushDown {
  0%   { transform: translateY(0); }
  46%  { transform: translateY(4px); }
  100% { transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .proc__list.is-tick::before,
  .proc__list.is-tick .proc__item.is-active .proc__label { animation: none; }
}

/* container framing the straight, overlapping card row */
.fun__fan {
  display: flex; justify-content: center; align-items: center;
  width: fit-content; max-width: 100%;
  margin: 0 auto;
  padding: clamp(20px, 2.6vw, 36px) clamp(24px, 3vw, 44px);
  border: 1px solid var(--line);
  border-radius: clamp(20px, 2vw, 28px);
  background: var(--surface-2, #f6f9ff);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.fun__card {
  position: relative;
  flex: 0 0 auto;
  width: clamp(120px, 11.8vw, 172px);
  margin: 0 clamp(-34px, -2.8vw, -18px);   /* overlapping fan */
  border-radius: var(--radius-lg);         /* match project cards (24px) */
  border: 1px solid var(--line);           /* match project hairline */
  box-shadow: var(--shadow-sm);            /* match project shadow */
  background: var(--surface);              /* white card body */
  overflow: hidden;
  display: flex; flex-direction: column;
  transform-origin: bottom center;
  cursor: pointer;
  /* pre-reveal: rise + faded (no rotation — straight) */
  opacity: 0;
  transform: translateY(40px) scale(.94);
  transition: transform .6s var(--ease, cubic-bezier(.22,1,.36,1)),
              opacity .5s ease, box-shadow .3s;
  transition-delay: calc(var(--i, 0) * 0.07s);
}
/* later cards stack on top, so each card's left edge (its title) stays
   visible above its left neighbour */
.fun__card:nth-child(1){z-index:1} .fun__card:nth-child(2){z-index:2}
.fun__card:nth-child(3){z-index:3} .fun__card:nth-child(4){z-index:4}
.fun__card:nth-child(5){z-index:5} .fun__card:nth-child(6){z-index:6}
.fun__card:nth-child(7){z-index:7} .fun__card:nth-child(8){z-index:8}

/* revealed state — straight, overlapping (no rotation) */
.fun.is-in .fun__card {
  opacity: 1;
  transform: none;
}
/* hover: lift straight to the front */
.fun.is-in .fun__card:hover {
  transform: translateY(-16px) scale(1.08);
  z-index: 9;
  box-shadow: var(--shadow-lg);
}

/* gradient "media" top + white text body (like the project cards) */
.fun__media {
  display: block; width: 100%;
  aspect-ratio: 1 / 1;
  background-size: cover; background-position: center;
}
.fun__body {
  position: relative;
  padding: 11px 11px;
  background: var(--surface);
  text-align: left;
}
/* hairline divider, inset from the card edges so it breathes (not full-bleed) */
.fun__body::before {
  content: "";
  position: absolute; top: 0; left: 11px; right: 11px;
  height: 1px; background: var(--line);
}
.fun__text { min-width: 0; }
.fun__title {
  font-family: var(--display);
  font-size: 0.875rem; font-weight: 600;
  color: var(--ink); line-height: 1.2; letter-spacing: -0.01em;
}
.fun__sub {
  font-size: 0.875rem; color: var(--muted);   /* 14px floor */
  line-height: 1.3; margin-top: 2px;
}
/* clickable affordance — arrow in a circle at the card's top-right
   (over the media, where the fan spreads open so it's always visible) */
.fun__go {
  position: absolute; top: 9px; right: 9px; z-index: 3;
  width: 28px; height: 28px;
  border-radius: var(--radius-sm);    /* rounded square (matches the icon chip) */
  display: grid; place-items: center;
  background: #fff;
  color: var(--ink, #1a1a1a);         /* dark filled triangle */
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
  transition: transform .35s var(--ease, ease), background .3s, color .3s, border-color .3s;
}
.fun__card:hover .fun__go {
  background: var(--ink, #1a1a1a); color: #fff; border-color: transparent;
  transform: translate(3px, -3px);
}
/* Clear the lowest fanned cards (edge cards translate down ~80px and spill
   past the fan baseline) so the heading never sits under them */
.fun__head { margin-top: clamp(48px, 5vw, 72px); }
.fun__head .h-1 { margin-inline: auto; }
.fun__head .lead { margin-inline: auto; text-align: center; max-width: 42ch; margin-top: 12px; }

/* Featured projects: narrow the 3 cards to the hero-heading width so they
   read as a centered column rather than full-bleed, and make them compact
   (shorter, tighter type, smaller thumbnail). Fully responsive — see the
   breakpoint blocks below. */
/* Homepage: every section sits tight, matching the hero → first-project-card gap */
#work.section--tight, #snapshot.section--tight, #approach.section--tight,
#process.section--tight, #notes.section--tight, #stack.section--tight,
#experience.section--tight, #think.section--tight,
.cta-foot.section--tight { padding-top: clamp(16px, 2vw, 24px); }   /* footer joins the same stack rhythm */
/* nav scroll-targets: land the section so the PREVIOUS card's bottom edge sits
   on the nav's bottom line rather than 19px below it — a sliver of the card you
   just left reads as "the link did not scroll far enough".
   Flat 84px, not the old clamp(96px, 12vh, 124px): the nav's bottom is a fixed
   89px, so a viewport-height offset drifted — 7px of spill on an 800px screen,
   35px on a 1080px one. #notes is included because a section with no
   scroll-margin lands 65px UNDER the nav. */
#work, #experience, #process, #snapshot, #notes { scroll-margin-top: 40px; }
#work .studies { max-width: none; margin-inline: auto; gap: clamp(16px, 2.4vw, 18px); }
#work .study__body { padding: clamp(28px, 3.4vw, 48px); gap: 18px; }   /* base rhythm — header cluster */
#work .study__body { padding: round(clamp(28px, 3.4vw, 48px), 4px); }   /* 44 @1280 */
/* grouped rhythm: more air before the bullet block, most before the metrics footer */
#work .study__impact { margin-top: 12px; }
#work .study__stats  { margin-top: 20px; }
#work .study__brand { margin-bottom: 0; gap: 12px; }
/* domain label → current typeface (Satoshi), no longer Space Mono */
#work .study__domain { font-family: var(--sans); font-weight: 600; font-size: 1rem; letter-spacing: normal; text-transform: none; color: var(--ink); }   /* 16px — on the body step */
#work .study__title { font-size: clamp(1.5rem, 2.3vw, 1.75rem); line-height: 1.2; margin-bottom: 0; }  /* 24→28px, typeface unchanged */
#work .study__sum {
  font-size: 1.0625rem; line-height: 1.6; max-width: 48ch;     /* 17px */
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
#work .study__meta { margin: 28px 0 0; padding-top: 24px; gap: clamp(32px, 4.5vw, 64px); }
#work .study__meta-k { font-size: 0.875rem; }    /* 14px label */
#work .study__meta-v { font-size: 1.125rem; }    /* 18px */

/* skill/category chips under the title */
/* project letter badge → monochrome navy (echoes the header logo / buttons), so the card
   complements the dark theme; the colourful product screenshot still carries the colour.
   !important beats the inline per-project cover colour set in studyCard(). */
.study__logo--mark {
  background: #1c1c1c !important;
  color: #fff !important;
  box-shadow: 0 4px 12px -5px rgba(28, 28, 28, .55);
}
.study__chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; }   /* body gap owns the rhythm */
.study__chip {
  font-family: var(--sans); font-size: 0.875rem; font-weight: 500; color: #0c0d12;   /* 14px */
  letter-spacing: .02em;   /* slight breathing between characters */
  padding: 6px 14px; border: 1px solid var(--line); border-radius: 999px; background: #f6f7f9;
  white-space: nowrap;
}
/* Between the two-column card and the stacked one, the text column dips to
   ~395px while three chips need ~414px, which drops the last chip to a second
   row. Tightening the horizontal padding buys back the 24px and keeps the set
   on one line; the chips are still on the 4-pt grid. */
@media (max-width: 1100px) and (min-width: 621px) {
  .study__chip { padding: 6px 10px; }
  .study__chips { gap: 4px; }   /* at 960 the set overran its column by 0.3px */
}
/* impact rows — icon + sentence; one body size (16px), uniform weight.
   Uniform 20px icons keep every text edge on the same vertical line. */
.study__impact { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 16px; }
.study__impact-row {
  display: flex; align-items: flex-start; gap: 12px;
  font-family: var(--sans); font-size: 1rem; font-weight: 400; line-height: 1.5; color: #0c0d12;
}
.study__impact-ic { flex: none; width: 17px; height: 17px; margin-top: 3px; color: #767f8f; }   /* matched to the snapshot list icons (.snap-stat-list svg): 17px, #767f8f, stroke 1.7. The old comment claimed “same caption grey” but the value was near-black at a larger size, so the same 1.7 stroke read heavier here than in the About cards. */

/* impact parameters — three value/label stats */
.study__stats {
  list-style: none; margin: 0; padding: 0;
  display: flex; gap: clamp(20px, 2.5vw, 32px);   /* lands 32 @1280 (even) */
}
/* CTA — quiet text link at the right end of the brand row; the whole card is
   the click target, this is just the affordance (senior-portfolio pattern) */
.study__go {
  display: inline-flex; align-items: center; gap: 10px; margin-left: auto; margin-right: 24px;
  font-family: var(--sans); font-size: 1rem; font-weight: 500; white-space: nowrap;
  color: var(--ink, #16181d);
}
/* arrow lives in a circular chip that fills dark on card-hover */
.study__go-chip {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid var(--line-2, rgba(12, 13, 18, .18)); background: transparent;
  transition: background .3s var(--ease, ease), border-color .3s var(--ease, ease), transform .35s cubic-bezier(.34, 1.56, .5, 1);
}
.study__go-ar { width: 15px; height: 15px; flex: none; }
.study:hover .study__go-chip {
  background: var(--ink, #16181d); border-color: var(--ink, #16181d); color: #fff;
  transform: translateX(4px) scale(1.06);
}
@media (prefers-reduced-motion: reduce) {
  .study__go-chip { transition: none; }
  .study:hover .study__go-chip { transform: none; }
}
/* optional caption above the stat row — carries the same class so it inherits the
   #work reveal delays and margin-top, then overrides the flex/list presentation.
   Used when the numbers describe scope rather than outcome. */
.study__stats-lbl {
  display: block; font-family: var(--sans); font-size: 0.75rem; font-weight: 500;
  color: rgba(12, 13, 18, .52); text-transform: uppercase; letter-spacing: .09em;
}
.study__stats-lbl + .study__stats { margin-top: 10px; }
#work .study__stats-lbl + .study__stats { margin-top: 10px; }
.study__stat { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 8px; align-items: center; text-align: center; }   /* equal columns so a longer label wraps inside its own share instead of pushing the row wide */
.study__stat + .study__stat { border-left: 1px solid var(--line, #e7eaf1); padding-left: clamp(16px, 1.9vw, 24px); }   /* vertical breaker between metrics — trimmed so the bolder, wider-tracked labels still fit the column */
.study__stat-v {
  font-family: "Averia Serif Libre", var(--display); font-weight: 700; font-size: 1.625rem;   /* 26px */
  color: var(--ink, #16181d); letter-spacing: -0.01em; line-height: 1.1;
}
.study__stat-l {
  font-family: var(--sans); font-size: 0.75rem; font-weight: 500;
  color: #0c0d12; text-transform: uppercase; letter-spacing: .09em;
  text-wrap: balance; line-height: 1.35;   /* outcome labels are phrases, not single words — nowrap overran the column by ~109px */
}


/* screenshot stage — soft cool-grey backdrop behind the product shot, so the
   (mostly white) dashboards read as framed screens instead of melting into
   the white card. Shared by the homepage grid and the Work index. */
.study .study__media { background-color: #f6f7f9; }   /* stage grey — same fill as the process card's .flow-panel */
.study .study__media::before { content: none; }       /* drop the hairline divider between details and screen */

/* Desktop / tablet-landscape (two-column card): collapse the 320px media
   floor so the tightened body drives the (shorter) card height. */
@media (min-width: 901px) {
  #work .study { grid-template-columns: 568px minmax(0, 1fr); }   /* details 568 · media fills the rest */
  /* alternating zig-zag: mirror the columns AND pull the media ahead of the
     body. style.css uses `order: 2`, which is a no-op because the media is
     already the last DOM child — so every card rendered identically. */
  #work .study.is-flip { grid-template-columns: minmax(0, 1fr) 568px; }
  #work .study.is-flip .study__media { order: -1; }
  #work .study__media { min-height: clamp(360px, 27vw, 432px); padding: clamp(12px, 1.4vw, 24px); }
  #work .study__media { padding: round(clamp(12px, 1.4vw, 24px), 4px); }   /* 16 @1280 — the stage was 40, which shrank the screenshot to the point the UI could not be read */
}

/* ≤900px — card stacks (thumbnail on top). Keep the thumbnail a calm,
   fixed-ratio band instead of the default 220px so it scales with width. */
@media (max-width: 900px) {
  #work .study__media { min-height: 0; aspect-ratio: 16 / 10; }
  /* `.study__media` sets `background-origin: content-box` so "padding insets the
     screen so it never touches the edges" — but the only padding rule lived in
     the ≥901px block, so below it the screenshot ran the full width of the stage
     and its square corners sat over the card's rounded ones. Same inset as
     desktop, scaled for the narrower card. */
  #work .study__media { padding: clamp(12px, 3vw, 16px); }
  /* the stats row's nowrap labels set a ~470px min-content that inflated the
     stacked card's single track past the phone width, pushing the title,
     chips, and stats off the right edge. Cap the track and let labels wrap. */
  .study { grid-template-columns: minmax(0, 1fr); }
  .study__body { min-width: 0; }
  .study__stat-l { white-space: normal; }
}

/* ≤620px — single narrow column, content already centers (style.css). Trim
   the thumbnail band a touch and let the summary breathe to ~3 lines. */
@media (max-width: 620px) {
  #work .study__media { aspect-ratio: 3 / 2; }
  #work .study__sum { -webkit-line-clamp: 3; max-width: 34ch; }
  .study__go { display: none; }   /* the whole card is the tap target on mobile */
}

/* Mobile: drop the fan, become a swipeable horizontal carousel */
@media (max-width: 720px) {
  /* On desktop the fan tucks up under the hero (negative margin). On a phone
     that pulls the carousel over the hero CTA — give it positive spacing. */
  #fun.section--tight { margin-top: 0; padding-top: clamp(28px, 7vw, 44px); }
  .fun__fan {
    display: flex;
    flex-wrap: nowrap;
    justify-content: flex-start;
    align-items: stretch;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    gap: 14px;
    padding: 6px 16px 14px;
    min-height: 0;
    scrollbar-width: none;              /* Firefox */
  }
  .fun__fan::-webkit-scrollbar { display: none; }   /* Chrome/Safari */
  .fun__card {
    flex: 0 0 auto;
    width: clamp(150px, 58vw, 220px);
    margin: 0;
    scroll-snap-align: center;
    transform: translateY(16px);        /* upright, no rotation */
    z-index: 1;
  }
  .fun.is-in .fun__card { transform: none; }
  .fun.is-in .fun__card:hover { transform: translateY(-4px) scale(1.02); }
  /* all tags bottom-left (no overlap in a carousel) */
  .fun__card .fun__tag,
  .fun__card:nth-child(n+6) .fun__tag { left: 8px; right: auto; bottom: 8px; }
  /* carousel cards don't spill downward, so the big desktop clearance
     would leave a dead gap — pull the heading back up */
  .fun__head { margin-top: clamp(24px, 6vw, 40px); }
}
/* Mobile hero: compact photo so the headline leads and a sliver of the next
   section shows without scrolling */
@media (max-width: 620px) {
  .hero__visual { width: auto; min-height: 0; margin-bottom: 4px; }
  .hero__photo { width: 104px; outline-width: 5px; }
  .hero__ring { width: clamp(150px, 46vw, 200px); }
}

/* ============================================================
   PROCESS + STACK — folder cards (hover/focus reveals contents)
   A back wall + front pocket; the items sit hidden behind the
   pocket, then rise and fan over the folder's top lip on hover.
   ============================================================ */
.folders {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: clamp(20px, 3vw, 32px);
  max-width: 760px; margin-inline: auto;
  margin-top: clamp(40px, 5vw, 64px);   /* room for items that rise above the folders */
}
.folder {
  position: relative;
  height: clamp(210px, 24vw, 250px);
  cursor: pointer; outline: none;
}
/* back wall + tab */
.folder__back {
  position: absolute; left: 0; right: 0; bottom: 0; height: 74%;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 18px; z-index: 1;
}
.folder__back::before {
  content: ""; position: absolute; top: -13px; left: 22px;
  width: 38%; height: 16px;
  background: var(--surface-2); border: 1px solid var(--line); border-bottom: none;
  border-radius: 10px 10px 0 0; z-index: 1;
}
/* items: hidden behind the pocket at rest, rise + fan on hover */
.folder__items {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
}
.folder__items > * {
  position: absolute; left: 50%; bottom: 30%;
  --tx: 0%; --r: 0deg;
  transform: translateX(-50%) translateY(24%) scale(.96);
  transform-origin: bottom center;
  transition: transform .55s cubic-bezier(.22, 1, .36, 1), box-shadow .3s;
  transition-delay: calc(var(--i) * 0.045s);
}
.folder:hover .folder__items > *,
.folder:focus-visible .folder__items > * {
  transform: translateX(-50%) translateX(var(--tx)) translateY(var(--ty, -120%)) rotate(var(--r)) scale(1);
}
/* fan offsets — Stack (7 logos): tight cluster popping up out of the mouth,
   centre highest, edges lower + rotated (icons overlap like a spilling pile) */
.folder__items--logos > *:nth-child(1){--tx:-122%;--ty:-96%; --r:-24deg}
.folder__items--logos > *:nth-child(2){--tx:-82%; --ty:-132%;--r:-15deg}
.folder__items--logos > *:nth-child(3){--tx:-41%; --ty:-154%;--r:-7deg}
.folder__items--logos > *:nth-child(4){--tx:0%;   --ty:-162%;--r:0deg}
.folder__items--logos > *:nth-child(5){--tx:41%;  --ty:-154%;--r:7deg}
.folder__items--logos > *:nth-child(6){--tx:82%;  --ty:-132%;--r:15deg}
.folder__items--logos > *:nth-child(7){--tx:122%; --ty:-96%; --r:24deg}
/* fan offsets — Process (5 chips): arc so chips sit at different heights
   (center highest) and stay readable instead of overlapping flat */
.folder__items:not(.folder__items--logos) > *:nth-child(1){--tx:-190%;--ty:-178%;--r:-17deg}
.folder__items:not(.folder__items--logos) > *:nth-child(2){--tx:-95%; --ty:-238%;--r:-9deg}
.folder__items:not(.folder__items--logos) > *:nth-child(3){--tx:0%;   --ty:-272%;--r:0deg}
.folder__items:not(.folder__items--logos) > *:nth-child(4){--tx:95%;  --ty:-238%;--r:9deg}
.folder__items:not(.folder__items--logos) > *:nth-child(5){--tx:190%; --ty:-178%;--r:17deg}
/* process step chips */
.folder__chip {
  display: grid; place-items: center;
  height: 32px; padding: 0 13px;
  background: #fff; border: 1px solid var(--line); border-radius: var(--pill);
  font-family: var(--display); font-size: 0.875rem; font-weight: 600;
  color: var(--ink); white-space: nowrap; box-shadow: var(--shadow-sm);
}
/* stack tool logos */
.folder__logo {
  display: grid; place-items: center;
  width: 54px; height: 54px;
  background: #fff; border: 1px solid var(--line); border-radius: 15px;
  box-shadow: var(--shadow-md);
}
.folder__logo svg { width: 30px; height: 30px; display: block; }
/* front pocket + label */
.folder__front {
  position: absolute; left: 0; right: 0; bottom: 0; height: 60%;
  background: linear-gradient(180deg, #eef1f5, #e4e8ee);
  border: 1px solid var(--line); border-top-color: rgba(255,255,255,.7);
  border-radius: 18px; z-index: 3;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: 16px 18px;
  transition: transform .4s var(--ease, ease), box-shadow .4s;
}
.folder:hover .folder__front,
.folder:focus-visible .folder__front {
  transform: translateY(4px); box-shadow: var(--shadow-md);
}
.folder__name {
  font-family: var(--display); font-size: 1.0625rem; font-weight: 600;
  color: var(--ink); letter-spacing: -0.01em; line-height: 1.1;
}
.folder__meta { font-size: 0.875rem; color: var(--muted); margin-top: 3px; }

@media (max-width: 620px) {
  .folders { grid-template-columns: 1fr; max-width: 360px; gap: 16px; }
  .folder { height: clamp(190px, 56vw, 230px); }
}

@media (prefers-reduced-motion: reduce) {
  .fun__card { opacity: 1; transition: box-shadow .3s; transform: rotate(var(--r,0deg)) translateY(var(--y,0)); }
}

/* ---------- Custom cursor: Figma-style arrow + "You" name tag ---------- */
html:has(body.has-cursor), body.has-cursor, body.has-cursor * { cursor: none !important; }   /* hide the native cursor (incl. the <html> region / scrollbar gutter) */
.cursor-fig {
  position: fixed; top: 0; left: 0; z-index: 99999; pointer-events: none;
  opacity: 0; will-change: transform; transition: opacity .25s ease;
}
body.has-cursor.is-visible .cursor-fig { opacity: 1; }
.cursor-fig__arrow {
  display: block; margin: -2px 0 0 -2px;        /* nudge the tip onto the real pointer */
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .28));
  transition: transform .12s ease;
}
.cursor-fig.is-down .cursor-fig__arrow { transform: scale(.82); }   /* little click squeeze */
.cursor-fig__tag {
  position: absolute; left: 20px; top: 23px;
  background: var(--brand, #1c1c1c); color: #fff;
  font: 600 12px/1 var(--sans, system-ui, sans-serif); letter-spacing: .01em;
  padding: 5px 8px; border-radius: 8px; border-top-left-radius: 3px;
  white-space: nowrap;
  box-shadow: 0 4px 12px -3px rgba(28, 28, 28, .5);
}
/* never on touch / coarse pointers (the JS also bails, so has-cursor isn't set there) */
@media (hover: none), (pointer: coarse) {
  .cursor-fig { display: none !important; }
  html:has(body.has-cursor), body.has-cursor, body.has-cursor * { cursor: auto !important; }
}

/* ============================================================
   PROCESS bento — two vertical cards + one horizontal card
   ============================================================ */
.bento {
  display: grid;
  grid-template-columns: 1fr;           /* single full-width process card */
  gap: clamp(16px, 2vw, 24px);
}
.bento-card {
  border: 1px solid var(--line, rgba(13,26,64,.10));
  border-radius: var(--radius-lg, 24px);
  background: #fff;
  padding: clamp(24px, 3vw, 40px);
  padding: round(clamp(24px, 3vw, 40px), 4px);   /* 40 @1280 */
  box-shadow: 0 1px 2px rgba(28,28,28,.04), 0 10px 28px -22px rgba(28,28,28,.22);   /* shared container lift — was nearly flat beside its neighbours */
}
.bento-card--h { grid-column: 1 / -1; }   /* third card spans the full width → horizontal */

/* --- Card 1: philosophy --- */
.philo { display: flex; flex-direction: column; }
.philo__title {
  font-family: "Averia Serif Libre", var(--display);
  font-weight: 700; font-size: clamp(1.625rem, 1.325rem + 1.16vw, 2.25rem);   /* 36px cap (lands 36 @1280) */
  line-height: 1.16; letter-spacing: -0.005em; color: #1c1c1c;
  margin: 0;
}
.philo__label {
  font-family: "Caveat", cursive; font-size: 1.5rem; color: var(--brand, #1c1c1c);
  margin-top: clamp(20px, 3vw, 32px);
}
.philo__txt {
  margin: 12px 0 0; color: #2a3142;
  font-family: var(--sans); font-weight: 400;
  font-size: 1.0625rem; line-height: 1.45; max-width: 44ch;   /* matches the project-card impact points */
}
/* chips sit right under the description (not pinned to the card bottom) */
.philo__chips { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: clamp(18px, 2.2vw, 24px) 0 0; }
.philo__chips li {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 14px; border-radius: var(--pill, 999px);
  border: 1px solid var(--line-2, rgba(12,13,18,.14));
  font-size: 0.8125rem; font-weight: 600; letter-spacing: .02em;
  text-transform: uppercase; color: var(--ink-2, #232934);
}
.philo__chips svg { width: 15px; height: 15px; color: var(--brand, #1c1c1c); }

/* AI-assisted workflow strip — subtle tools mention between the paragraph and the process grid */
.philo__ai {
  margin-top: 30px;                                   /* ~28–32px gap after the paragraph */
  padding: 6px 18px;                                  /* slim — the strip is a footnote, not a feature */
  border: 1px solid rgba(15, 23, 42, 0.06);
  background: rgba(15, 23, 42, 0.015);
  border-radius: var(--radius, 16px);
  display: flex; flex-direction: column; gap: 4px;
}
.philo__ai-title {
  font-family: var(--sans);
  font-size: 0.75rem; font-weight: 500; letter-spacing: .08em;
  text-transform: uppercase; color: var(--faint, #5a6273);
}
.philo__ai-tools {
  font-family: var(--sans);
  font-size: 1rem; font-weight: 600; letter-spacing: .01em;
  color: var(--ink, #0c0d12);
}
.philo__ai-note {
  font-family: var(--sans);
  font-size: 1rem; font-weight: 400; line-height: 1.5;   /* 16px floor — same as the process-card descriptions */
  color: var(--muted, #3a4150);
  margin-top: 2px;                                       /* breathing room under the tools line */
}

/* --- process card content cascade: eyebrow → heading → timeline (steps have
   their own stagger) → detail stage, hero-style --- */
.bento.reveal .philo__eyebrow,
.bento.reveal .philo__title,
.bento.reveal .flow-nav,
.bento.reveal .flow-stage {
  opacity: 0; transform: translateY(12px);
  transition: opacity .75s ease, transform .75s cubic-bezier(.22, 1, .36, 1);
}
.bento.reveal.is-in .philo__eyebrow,
.bento.reveal.is-in .philo__title,
.bento.reveal.is-in .flow-nav,
.bento.reveal.is-in .flow-stage { opacity: 1; transform: none; }
.bento.reveal.is-in .philo__eyebrow { transition-delay: .10s; }
.bento.reveal.is-in .philo__title   { transition-delay: .26s; }
.bento.reveal.is-in .flow-nav       { transition-delay: .46s; }
.bento.reveal.is-in .flow-stage     { transition-delay: .80s; }
/* inner cascade: after the grey panel box fades in, its content arrives piece by
   piece — same staggered feel as the study cards above. Only the active panel's
   content participates; step-to-step switching is still handled by flowPanelIn. */
.bento.reveal .flow-panel.is-on .flow-panel__num,
.bento.reveal .flow-panel.is-on .flow-panel__title,
.bento.reveal .flow-panel.is-on .flow-panel__what,
.bento.reveal .flow-panel.is-on .flow-panel__label,
.bento.reveal .flow-panel.is-on .flow-tools,
.bento.reveal .flow-panel.is-on .flow-panel__how {
  opacity: 0; transform: translateY(12px);
  transition: opacity .7s ease, transform .7s cubic-bezier(.22, 1, .36, 1);
}
.bento.reveal.is-in .flow-panel.is-on .flow-panel__num,
.bento.reveal.is-in .flow-panel.is-on .flow-panel__title,
.bento.reveal.is-in .flow-panel.is-on .flow-panel__what,
.bento.reveal.is-in .flow-panel.is-on .flow-panel__label,
.bento.reveal.is-in .flow-panel.is-on .flow-tools,
.bento.reveal.is-in .flow-panel.is-on .flow-panel__how { opacity: 1; transform: none; }
.bento.reveal.is-in .flow-panel.is-on .flow-panel__num   { transition-delay: .96s; }
.bento.reveal.is-in .flow-panel.is-on .flow-panel__title { transition-delay: 1.08s; }
.bento.reveal.is-in .flow-panel.is-on .flow-panel__what  { transition-delay: 1.20s; }
.bento.reveal.is-in .flow-panel.is-on .flow-panel__label { transition-delay: 1.14s; }
.bento.reveal.is-in .flow-panel.is-on .flow-tools        { transition-delay: 1.26s; }
.bento.reveal.is-in .flow-panel.is-on .flow-panel__how   { transition-delay: 1.40s; }
@media (prefers-reduced-motion: reduce) {
  .bento.reveal .philo__eyebrow, .bento.reveal .philo__title,
  .bento.reveal .flow-nav, .bento.reveal .flow-stage,
  .bento.reveal .flow-panel.is-on .flow-panel__num, .bento.reveal .flow-panel.is-on .flow-panel__title,
  .bento.reveal .flow-panel.is-on .flow-panel__what, .bento.reveal .flow-panel.is-on .flow-panel__label,
  .bento.reveal .flow-panel.is-on .flow-tools, .bento.reveal .flow-panel.is-on .flow-panel__how {
    transition: none; opacity: 1; transform: none;
  }
}

/* --- full-width process card: centered header --- */
.philo--full .philo__head--center { text-align: center; }
.philo--full .philo__head--center .philo__eyebrow {
  display: block; margin: 0 0 12px;
  font-family: var(--sans); font-size: 0.875rem; font-weight: 500;   /* 14px, medium */
  letter-spacing: .12em; text-transform: uppercase; color: var(--faint, #5a6273);
}
.philo--full .philo__head--center .philo__title { max-width: 34ch; margin-inline: auto; text-wrap: balance; }

/* services absorbed into the process card — a quiet chip row in the same
   language as the stage's tool pills; no divider, no heavy icon boxes */
.caps--row.caps--embed {
  display: block;
  margin-top: clamp(20px, 2.4vw, 28px);
  border-top: none;
  padding: 0;
}
.caps--row.caps--embed .caps__eyebrow { display: block; margin-bottom: 12px; }
.caps--row.caps--embed .caps__list { display: flex; flex-wrap: wrap; gap: 8px; }
.caps--row.caps--embed .caps__list li {
  flex: none; border-top: none;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 14px; border-radius: 999px;
  background: #f6f7f9; border: 1px solid var(--line, #e7eaf1);
  font-family: var(--sans); font-size: 0.875rem; font-weight: 500; color: var(--ink, #0c0d12);
  white-space: nowrap;
}
.caps--row.caps--embed .caps__ic {
  width: auto; height: auto; border-radius: 0;
  background: transparent; color: var(--ink, #0c0d12);
}
.caps--row.caps--embed .caps__ic svg { width: 15px; height: 15px; }

/* --- the workflow line: 6 numbered nodes on a continuous connector --- */
.flow {
  --flowY: 50px;                       /* number (12px) + 14px gap + half the 48px node */
  list-style: none; margin: clamp(24px, calc(2.2vw + 6px), 36px) auto 0; padding: 0;   /* heading → timeline 36px */
  margin-top: round(clamp(24px, calc(2.2vw + 6px), 36px), 4px);   /* 36 @1280 */
  width: 90%;                          /* slightly narrower than the card, centered */
  position: relative;
  display: grid; grid-template-columns: repeat(6, 1fr);
}
.flow::before {                        /* the connector line, drawn through the node centers */
  content: ""; position: absolute; z-index: 0;
  top: calc(var(--flowY) - 1px); height: 2px;
  left: calc(100% / 12); right: calc(100% / 12);
  background: rgba(12, 13, 18, 0.085);   /* ~15% lighter connector */
}
.flow__step { position: relative; padding: 0 10px; text-align: center; max-width: 170px; margin-inline: auto; }
.flow__step:not(:last-child)::after {  /* direction arrow on the line, at the column boundary */
  content: ""; position: absolute; z-index: 2;
  top: calc(var(--flowY) - 4.5px); right: -4.5px;
  width: 9px; height: 9px;
  border-top: 2px solid #d2d7df;    /* ~12% lighter arrows */
  border-right: 2px solid #d2d7df;
  transform: rotate(45deg);
}
.flow__num {
  display: block; margin-bottom: 14px;
  font-family: var(--sans); font-size: 0.875rem; font-weight: 600;   /* 14px */
  letter-spacing: .08em; line-height: 1; color: var(--faint, #5a6273);
  height: 1rem;                        /* the active step steps this up to 16px/700 — a fixed box keeps that from pushing its node and label 2px lower than the other five */
}
.flow__node {
  position: relative; z-index: 1;
  width: 48px; height: 48px; margin: 0 auto; border-radius: 50%;
  display: grid; place-items: center;
  background: #fff; border: 1px solid var(--line-2, rgba(12,13,18,.14));
  box-shadow: 0 2px 8px -4px rgba(13,26,64,.14);
  color: var(--ink, #0c0d12);
}
.flow__node svg { width: 20px; height: 20px; }
.flow__name {
  display: block; margin-top: 10px;    /* air between icon and title */
  min-height: 2.6em;                   /* two lines: “Build & Validate” and “Ship & Evolve” fit on one, the other four wrap, and without a reserved box the row read as ragged */
  font-weight: 600; font-size: 1rem; line-height: 1.3;   /* 16px */
  letter-spacing: -0.003em; color: var(--ink, #0c0d12);
  text-wrap: balance;
}
.flow__sub {
  display: block; margin-top: 11px;                    /* clear air between title and subtitle */
  font-size: 1rem; line-height: 1.4; color: #4b5568;   /* a touch more contrast than the numbers */
}

/* draw the flow in on scroll-reveal: line sweeps, steps rise in order, arrows follow */
.bento.reveal .flow::before { transform: scaleX(0); transform-origin: 0 50%; transition: transform .95s cubic-bezier(.55,0,.1,1) .25s; }
.bento.reveal.is-in .flow::before { transform: scaleX(1); }
.bento.reveal .flow__step { opacity: 0; transform: translateY(12px); transition: opacity .7s ease, transform .7s cubic-bezier(.2,.7,.3,1); }
.bento.reveal.is-in .flow__step { opacity: 1; transform: none; }
.bento.reveal .flow__step:nth-child(1) { transition-delay: .42s; }
.bento.reveal .flow__step:nth-child(2) { transition-delay: .60s; }
.bento.reveal .flow__step:nth-child(3) { transition-delay: .78s; }
.bento.reveal .flow__step:nth-child(4) { transition-delay: .96s; }
.bento.reveal .flow__step:nth-child(5) { transition-delay: 1.14s; }
.bento.reveal .flow__step:nth-child(6) { transition-delay: 1.32s; }
.bento.reveal .flow__step:not(:last-child)::after { opacity: 0; transition: opacity .35s ease; }
.bento.reveal.is-in .flow__step:not(:last-child)::after { opacity: 1; }
.bento.reveal .flow__step:nth-child(1)::after { transition-delay: .68s; }
.bento.reveal .flow__step:nth-child(2)::after { transition-delay: .86s; }
.bento.reveal .flow__step:nth-child(3)::after { transition-delay: 1.04s; }
.bento.reveal .flow__step:nth-child(4)::after { transition-delay: 1.22s; }
.bento.reveal .flow__step:nth-child(5)::after { transition-delay: 1.40s; }
@media (prefers-reduced-motion: reduce) {
  .bento.reveal .flow::before,
  .bento.reveal .flow__step,
  .bento.reveal .flow__step:not(:last-child)::after { opacity: 1; transform: none; transition: none; }
  .bento.reveal .flow::before { transform: scaleX(1); }
}

/* ---- live spotlight: the timeline runs itself — one step "on" at a time.
   The ink fill line grows to the active node, the active node inflates to a
   black chip with a white icon and a sweeping progress ring; the rest dim.
   Auto-advances (pauses on hover), click a step to jump. JS adds .is-live. ---- */
.flow::after {                          /* ink progress fill over the base line */
  content: ""; position: absolute; z-index: 0;
  top: calc(var(--flowY) - 1px); height: 2px;
  left: calc(100% / 12); right: calc(100% / 12);
  background: var(--ink, #0c0d12);
  transform: scaleX(var(--flow-fill, 0)); transform-origin: 0 50%;
  transition: transform .8s cubic-bezier(.22, 1, .36, 1);
  opacity: 0;
}
.flow.is-live::after { opacity: 1; }
/* each step is a real button (keyboard + AT); layout passes straight through */
.flow__stepbtn {
  display: block; width: 100%; margin: 0; padding: 0;
  background: none; border: 0; font: inherit; color: inherit;
  text-align: center; cursor: default;
}
.flow.is-live .flow__stepbtn { cursor: pointer; }
.flow__stepbtn:focus-visible { outline: 2px solid var(--ink, #0c0d12); outline-offset: 4px; border-radius: 14px; }
.flow.is-live .flow__num,
.flow.is-live .flow__name,
.flow.is-live .flow__sub { transition: opacity .45s ease, color .45s ease, transform .5s cubic-bezier(.34, 1.56, .5, 1); }
/* clear the inflated node + ring: label floats up, title drops down (desktop line only) */
@media (min-width: 901px) {
  .flow.is-live .flow__step.is-active .flow__num  { transform: translateY(-7px); }
  /* the name is NOT pushed down to match: scale(1.16) grows a 48px node by only
     ~3.9px below centre, and the label already carries 10px of margin, so the old
     translateY(7px) bought clearance that was not needed and left the active step
     sitting a line lower than the other five. */
}
/* three states — upcoming (default, lighter) · completed (.is-done, darker) · active */
.flow.is-live .flow__step .flow__num,
.flow.is-live .flow__step .flow__name { color: rgba(17, 24, 39, .42); }             /* upcoming: lightened ~10% */
.flow.is-live .flow__step .flow__node { color: rgba(17, 24, 39, .38); border-color: rgba(12, 13, 18, .12); }
.flow.is-live .flow__step.is-done .flow__num,
.flow.is-live .flow__step.is-done .flow__name { color: rgba(17, 24, 39, .74); }     /* completed: clearly darker than upcoming */
.flow.is-live .flow__step.is-done .flow__node { color: #2b313c; border-color: rgba(12, 13, 18, .26); }
.flow.is-live .flow__step.is-done:not(:last-child)::after { border-color: var(--ink, #0c0d12); }   /* completed arrows turn ink with the fill line */
.flow.is-live .flow__node {
  transition: background .45s ease, color .45s ease, transform .5s cubic-bezier(.34, 1.56, .5, 1),
              border-color .45s ease, box-shadow .45s ease;
}
.flow.is-live .flow__step:not(.is-active):hover .flow__node { transform: translateY(-2px); }
.flow.is-live .flow__step.is-active .flow__node {
  background: #1c1c1c; color: #fff; border-color: #1c1c1c;
  transform: scale(1.16);
  box-shadow: 0 10px 24px -10px rgba(12, 13, 18, .45);
}
.flow.is-live .flow__step.is-active .flow__num { color: var(--ink, #0c0d12); font-weight: 700; font-size: 1rem; }   /* 16px on active */
.flow.is-live .flow__step.is-active .flow__name { color: var(--ink, #0c0d12); }
/* dwell progress — a thin conic ring sweeping around the active node (JS drives --ring 0→1) */
.flow.is-live .flow__step.is-active .flow__node::before {
  content: ""; position: absolute; inset: -6px; border-radius: 50%;
  background: conic-gradient(#1c1c1c calc(var(--ring, 0) * 1turn), rgba(12, 13, 18, .10) 0);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 1px), #000 calc(100% - 0.5px));
          mask: radial-gradient(farthest-side, transparent calc(100% - 1px), #000 calc(100% - 0.5px));
}
@media (prefers-reduced-motion: reduce) {
  .flow::after { transition: none; }                       /* fill still shows progress, just without motion */
  .flow.is-live .flow__step.is-active .flow__node { transform: none; }
  .flow.is-live .flow__step.is-active .flow__node::before { display: none; }
  .flow.is-live .flow__step.is-active .flow__num,
  .flow.is-live .flow__step.is-active .flow__name { transform: none; }
}

/* ---- detail stage: the active step's full story below the timeline —
   ghost serif number + title + "what" on the left; tools chips + how-AI-carries-it
   on the right. Panels swap with the spotlight. ---- */
.flow-stage { margin-top: clamp(26px, 2.9vw, 36px); }   /* +10px separation from the step labels */
.flow-panel {
  display: none;
  background: #f6f7f9;                       /* same stage grey as the project-card media */
  border-radius: var(--radius-lg, 24px);     /* on-system with every other card */
  padding: clamp(16px, 2vw, 24px) clamp(24px, 2.8vw, 40px);   /* −12px vertical; width unchanged */
  padding: round(clamp(16px, 2vw, 24px), 4px) round(clamp(24px, 2.8vw, 40px), 4px);   /* 24 · 36 @1280 */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(24px, 3vw, 48px);
  gap: round(clamp(24px, 3vw, 48px), 4px);   /* 40 @1280 */
  align-items: stretch;                      /* divider spans full content height */
}
.flow-panel.is-on { display: grid; animation: flowPanelIn 1.8s cubic-bezier(.22, 1, .36, 1) both; }
@keyframes flowPanelIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }
.flow-panel__num {
  display: block; line-height: 1;
  font-family: "Averia Serif Libre", var(--display); font-weight: 700;
  font-size: clamp(2.25rem, 3.53vw, 2.75rem);   /* 44px cap @1280 */
  color: transparent; -webkit-text-stroke: 1.5px rgba(12, 13, 18, .30);
}
.flow-panel__title {
  margin: 10px 0 0;
  font-family: "Averia Serif Libre", var(--display); font-weight: 700;
  font-size: clamp(1.375rem, 1.9vw, 1.5rem); line-height: 1.2;   /* 24px cap @1280 */
  letter-spacing: -0.01em; color: var(--ink, #0c0d12);
}
.flow-panel__what {
  margin: 10px 0 0; max-width: 36ch;
  font-family: var(--sans); font-size: 1.125rem; line-height: 1.55;   /* 18px */
  color: #3a4150;
  text-wrap: pretty;   /* steps 01 and 05 ended on a single word — pretty pulls a word down from the line above rather than leaving the orphan */
}
.flow-panel__side { border-left: 1px solid rgba(12, 13, 18, .08); padding-left: clamp(24px, 3vw, 48px); }
.flow-panel__side { padding-left: round(clamp(24px, 3vw, 48px), 4px); }   /* 40 @1280 — matches the panel gap */
.flow-panel__label {
  display: block;
  font-family: var(--sans); font-size: 0.75rem; font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--faint, #5a6273);
}
.flow-tools { list-style: none; margin: 12px 0 16px; padding: 0; display: flex; flex-wrap: nowrap; gap: 6px; }
.flow-tools li {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 8px; border-radius: 999px;
  background: #fff; border: 1px solid var(--line, #e7eaf1);
  font-family: var(--sans); font-size: 0.875rem; font-weight: 500; color: var(--ink, #0c0d12);
  white-space: nowrap;
}
.flow-tools li svg { width: 13px; height: 13px; flex: none; }
@media (max-width: 720px) { .flow-tools { flex-wrap: wrap; } }   /* stacked panel can wrap */
.flow-panel__how {
  margin: 0;
  font-family: var(--sans); font-size: 1rem; line-height: 1.55;
  color: #4b5568;
  text-wrap: pretty;   /* same orphan guard as .flow-panel__what — step 03 was ending on “implementation.” alone */
}
@media (max-width: 720px) {
  .flow-panel { grid-template-columns: 1fr; gap: 20px; padding: 22px 20px; }
  .flow-panel__side { border-left: none; padding-left: 0; border-top: 1px solid rgba(12, 13, 18, .08); padding-top: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .flow-panel.is-on { animation: none; }
}

/* ---- mobile flow header: one step at a time, stepped through with arrows ---- */
.flow-nav { display: none; }
/* ≤900px: the rail hides — the flow becomes one step card at a time, advanced
   by the arrows (or the auto-dwell), like a guided wizard. */
@media (max-width: 900px) {
  .flow { display: none; }
  .flow-nav {
    display: flex; align-items: center; justify-content: space-between;
    margin: 0 0 12px;
  }
  .flow-nav__count {
    font-family: var(--sans); font-size: 0.8125rem; font-weight: 600;
    letter-spacing: .08em; color: var(--faint, #5a6273);
    font-variant-numeric: tabular-nums; flex: none;
  }
  /* story-style progress: six thin segments — done = ink, active fills over the
     dwell (rAF drives --p each frame), upcoming stays light */
  .flow-nav__track { display: flex; flex: 1; gap: 5px; margin: 0 14px; }
  .flow-nav__track span {
    position: relative; overflow: hidden;
    flex: 1; height: 3px; border-radius: 999px;
    background: rgba(12, 13, 18, .08);
  }
  .flow-nav__track span::after {
    content: ""; position: absolute; inset: 0; border-radius: inherit;
    background: #1c1c1c;
    transform: scaleX(var(--p, 0)); transform-origin: 0 50%;
  }
  .flow-nav__track span.is-done::after { transform: scaleX(1); }
  .flow-nav__btns { display: flex; gap: 8px; }
  .flow-nav__btn {
    width: 40px; height: 40px; border-radius: 12px;
    border: 1px solid var(--line, #e7eaf1); background: #fff; color: var(--ink, #0c0d12);
    display: grid; place-items: center; cursor: pointer;
    transition: background .25s ease, color .25s ease;
  }
  .flow-nav__btn:active { background: #1c1c1c; color: #fff; border-color: #1c1c1c; }
  .flow-nav__btn:focus-visible { outline: 2px solid var(--ink, #0c0d12); outline-offset: 2px; }
}
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .flow-nav__track span.is-active::after { transform: scaleX(1); }   /* no dwell animation — show the current segment solid */
}

/* (legacy) old two-column process grid, kept for reference */
.philo__tools {
  margin-top: 22px;
}
.philo__tools .tools__title {
  font-family: "Averia Serif Libre", var(--display);
  font-weight: 700; font-size: clamp(1.1875rem, 1.7vw, 1.4375rem);
  line-height: 1.18; letter-spacing: -0.005em; color: #1c1c1c; margin: 0;
}
.philo__tools .tools__sub { margin: 8px 0 clamp(18px, 2.2vw, 24px); color: var(--muted, #3a4150); font-size: 1rem; line-height: 1.55; }
.philo__tools .tools__grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(10px, 1.2vw, 14px);
}
@media (max-width: 520px) {
  .philo__tools .tools__grid { grid-template-columns: 1fr; }
}

/* --- Card 2: capabilities --- */
.caps { display: flex; flex-direction: column; }
.caps__eyebrow {
  font-family: var(--sans); font-size: 0.8125rem; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; color: var(--faint, #5a6273);
  margin-bottom: clamp(16px, 2vw, 22px);
}
.caps__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; flex: 1; }
.caps__list li {
  flex: 1;
  display: flex; align-items: center; gap: 14px;
  padding: clamp(10px, 1.4vw, 14px) 0;
  font-family: var(--display); font-weight: 600;
  font-size: clamp(1.0625rem, 1.6vw, 1.25rem); color: var(--ink, #0c0d12);
  border-top: 1px solid var(--line, rgba(13,26,64,.08));
}
.caps__list li:first-child { border-top: none; }
.caps__ic {
  flex: none; width: 38px; height: 38px; border-radius: 12px;
  display: grid; place-items: center;
  background: var(--ink, #0c0d12); color: #fff;
}
.caps__ic svg { width: 19px; height: 19px; }

/* --- horizontal services card (below the workflow): aligned 4-column grid --- */
.caps--row { padding: clamp(20px, 2.4vw, 28px) clamp(24px, 3vw, 40px); }
.caps--row .caps__list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);   /* 4 in row one, remaining 3 land on the same column lines */
  gap: 6px clamp(16px, 2.4vw, 32px);
}
.caps--row .caps__list li {
  flex: none;
  border-top: none;
  padding: 4px 0;
  gap: 12px;
  font-size: 1.0625rem;
}
.caps--row .caps__ic { width: 34px; height: 34px; border-radius: var(--radius-sm); }
.caps--row .caps__ic svg { width: 17px; height: 17px; }
.caps--row .caps__eyebrow { margin-bottom: 10px; }
@media (max-width: 900px) {
  .caps--row .caps__list { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .caps--row .caps__list { grid-template-columns: 1fr; }
}

/* --- Card 3: tools (horizontal) --- */
.tools {
  display: grid; grid-template-columns: minmax(220px, 0.8fr) 2fr;
  gap: clamp(24px, 3.4vw, 48px); align-items: start;
}
.tools__title {
  font-family: "Averia Serif Libre", var(--display);
  font-weight: 700; font-size: clamp(1.375rem, 2.2vw, 1.75rem);
  line-height: 1.14; letter-spacing: -0.01em; color: var(--ink, #0c0d12); margin: 0;
}
.tools__sub { margin: 12px 0 0; color: var(--muted, #3a4150); font-size: 1rem; line-height: 1.55; }
.tools__grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(12px, 1.4vw, 16px);
}
.btool {
  display: flex; align-items: center; gap: 12px;
  padding: 14px; border-radius: var(--radius, 16px);
  border: 1px solid var(--line, rgba(13,26,64,.10));
  transition: transform .25s var(--ease, ease), box-shadow .25s, border-color .25s;
}
.btool:hover { transform: translateY(-2px); box-shadow: 0 10px 22px -14px rgba(13,26,64,.4); border-color: var(--line-2, rgba(12,13,18,.16)); }
.btool__ic {
  flex: none; width: 36px; height: 36px; border-radius: var(--radius-sm);
  display: grid; place-items: center;
  background: #f6f7f9; border: 1px solid var(--line); color: var(--muted, #3a4150);
}
.btool__ic svg { width: 18px; height: 18px; }
.btool__txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.btool__name { font-weight: 600; font-size: 1.0625rem; letter-spacing: -0.003em; color: var(--ink, #0c0d12); }
.btool__tag {
  font-size: 1rem; font-weight: 400; letter-spacing: .01em;   /* 16px floor — matches the AI-strip note */
  color: var(--faint, #5a6273); line-height: 1.4;
}

@media (max-width: 860px) {
  .bento { grid-template-columns: 1fr; }      /* stack the two vertical cards on small screens */
  .tools { grid-template-columns: 1fr; }
  .tools__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 520px) {
  .tools__grid { grid-template-columns: 1fr; }
}

/* =====================================================================
   ON-LOAD HOVER TEASER  → each of the four interactive buttons replays
   its hover animation ONCE on landing (in → brief hold → out), so the
   motion is discoverable. Fires ~1.4s in, after the hero entrance.
   Pure CSS (no fill) so each element returns to rest and :hover still works.
   ===================================================================== */
@media (prefers-reduced-motion: no-preference) {
  /* shared timeline: rest → peak (hold) → rest */
  @keyframes demoRise    { 0%,18% { transform: translateY(101%); }            48%,60% { transform: translateY(0); }                       88%,100% { transform: translateY(101%); } }
  @keyframes demoFlipOut { 0%,18% { transform: translateY(0); }               48%,60% { transform: translateY(-120%); }                   88%,100% { transform: translateY(0); } }
  @keyframes demoFlipIn  { 0%,18% { transform: translateY(120%); }            48%,60% { transform: translateY(0); }                       88%,100% { transform: translateY(120%); } }
  @keyframes demoIcoFlip { 0%,18% { transform: rotateX(0); }                  48%,60% { transform: rotateX(-360deg); }                    88%,100% { transform: rotateX(0); } }
  @keyframes demoCopyIco { 0%,18% { transform: rotateX(0) scale(1); }         48%,60% { transform: rotateX(-360deg) scale(1.06); }        88%,100% { transform: rotateX(0) scale(1); } }
  @keyframes demoPop     { 0%,18% { transform: translateY(0) scale(1); }      48%,60% { transform: translateY(-3px) scale(1.05); box-shadow: 0 14px 28px -12px rgba(23,24,28,.7); }  88%,100% { transform: translateY(0) scale(1); } }
  @keyframes demoArrow   { 0%,18% { width: 0; opacity: 0; margin-left: 0; transform: translateX(-6px); }   48%,60% { width: 17px; opacity: 1; margin-left: 7px; transform: translateX(0); }   88%,100% { width: 0; opacity: 0; margin-left: 0; transform: translateX(-6px); } }

  /* Resume — the dark panel rises up and back (quick, finishes during the hero load) */
  .nav__links a.nav__cta::before     { animation: demoRise 1s cubic-bezier(.4,0,.2,1) .2s 1; }
  /* nav text labels (Work/Experience/Process/About) no longer replay the flip on load */
}

/* =====================================================================
   HOW I THINK  → left: serif heading + an accordion of principles;
   right: a sticky LinkedIn connect card. Black/grey, on-system tokens.
   ===================================================================== */
.think {
  display: grid; grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr);
  gap: clamp(20px, 3vw, 48px); align-items: start;
}
.think__title {
  font-family: "Averia Serif Libre", var(--display);
  font-weight: 700; line-height: 1.16; letter-spacing: -0.01em;
  font-size: clamp(1.875rem, 3.4vw, 2.6rem);
  color: #1c1c1c; margin: 0 0 clamp(28px, 4vw, 52px);
}

/* left column: heading + accordion live in one card */
.think__main {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: 0 1px 2px rgba(28, 28, 28, .04), 0 10px 28px -22px rgba(28, 28, 28, .22);
  overflow: hidden;
}
.think-head { padding: clamp(24px, 3vw, 34px) clamp(18px, 2vw, 26px) clamp(16px, 2vw, 22px); }
.think-head .think__title { margin: 0; }
.think-head .sec-box-head__sub { margin-top: clamp(10px, 1.4vw, 14px); }

/* ---- accordion: flat rows divided by hairlines inside the card ---- */
.faq { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }
.faq__item {
  border: none; border-top: 1px solid var(--line); border-radius: 0;
  background: transparent; overflow: hidden;
  transition: background .25s var(--ease);
}
.faq__item.is-open { box-shadow: none; }
.faq__item:hover { background: rgba(13, 26, 64, .02); }
.faq__q {
  width: 100%; display: flex; align-items: center; gap: 16px;
  padding: clamp(16px, 1.8vw, 22px) clamp(18px, 2vw, 26px);
  background: none; border: none; cursor: pointer; text-align: left;
  font-family: var(--display); font-weight: 600; color: var(--ink);
}
.faq__num { font-family: var(--mono, var(--display)); font-weight: 700; font-size: 0.9375rem; color: rgba(31, 41, 55, .42); flex: none; }
.faq__item.is-open .faq__num { display: none; }
.faq__t { flex: 1; font-size: clamp(1.0625rem, 1.4vw, 1.1875rem); }
.faq__q:focus-visible { outline: 2px solid var(--ink, #0c0d12); outline-offset: -2px; border-radius: 10px; }
.faq__ic { position: relative; flex: none; width: 22px; height: 22px; color: var(--ink); }   /* box (hit area) unchanged */
.faq__ic::before, .faq__ic::after {
  content: ""; position: absolute; background: currentColor; border-radius: 2px;
  transition: transform .3s var(--ease), opacity .3s var(--ease);
}
.faq__ic::before { left: 4px; right: 4px; top: 10px; height: 2px; }            /* horizontal bar — ~12% shorter */
.faq__ic::after  { top: 4px; bottom: 4px; left: 10px; width: 2px; }            /* vertical bar (hidden when open → minus) */
.faq__item.is-open .faq__ic::after { transform: scaleY(0); opacity: 0; }
/* answer: animate grid-rows 0fr → 1fr so it expands smoothly with no JS measuring */
.faq__a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .4s var(--ease); }
.faq__item.is-open .faq__a { grid-template-rows: 1fr; }
.faq__a-in { overflow: hidden; }
.faq__a-in p {
  margin: 0; padding: 0 clamp(18px, 2vw, 26px) clamp(18px, 2vw, 24px);
  font-family: var(--sans); font-weight: 400; font-size: 1.0625rem; line-height: 1.45; color: #2a3142;
}

/* ---- LinkedIn connect card ---- */
.connect {
  position: sticky; top: 96px;
  border: 1px solid var(--line); border-radius: var(--radius-lg); background: #fff;
  padding: clamp(28px, 3vw, 40px);
  box-shadow: 0 2px 6px -4px rgba(13,26,64,.10);
  display: flex; flex-direction: column; justify-content: center;   /* content centres in the card height */
}
.connect__avatar {
  display: block; width: 92px; height: 92px; border-radius: 50%; overflow: hidden;   /* +9% */
  background: radial-gradient(circle at 50% 35%, #3a3a3a, #1c1c1c);
  margin-bottom: clamp(12px, 1.6vw, 18px);   /* tighter to the heading */
}
.connect__avatar img { width: 100%; height: 100%; object-fit: cover; filter: grayscale(1); }
.connect__avatar.is-empty { display: block; }
.connect__title {
  font-family: "Averia Serif Libre", var(--display);
  font-weight: 700; line-height: 1.2; letter-spacing: -0.01em;
  font-size: clamp(1.375rem, 2vw, 1.75rem); color: #1d1f24; margin: 0 0 12px;
}
.connect__txt { font-family: var(--sans); font-weight: 400; font-size: 1.0625rem; line-height: 1.45; color: #2a3142; margin: 0 0 clamp(20px, 2.4vw, 28px); max-width: 30ch; }
.connect__btn.btn { height: 48px; padding: 0 22px; gap: 10px; font-size: 1.0625rem; }
.connect__li { width: 19px; height: 19px; flex: none; }

@media (max-width: 860px) {
  .think { grid-template-columns: 1fr; }
  .connect { position: static; }
}

/* =====================================================================
   EXPERIENCE  → timeline list: company badge · role + dates · blurb
   ===================================================================== */
.exp-title {
  font-family: "Averia Serif Libre", var(--display);
  font-weight: 700; line-height: 1.16; letter-spacing: -0.01em;
  font-size: clamp(1.625rem, 1.325rem + 1.16vw, 2.25rem); color: #1c1c1c;   /* 36px cap — shared section-heading step */
  margin: 0 0 clamp(28px, 4vw, 52px);
}

/* section intro card: eyebrow + heading + subtitle, so the title doesn't float on the page bg */
.sec-box-head {
  background: var(--surface, #fff);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg, 24px);
  padding: clamp(18px, 2vw, 24px) clamp(28px, 3.4vw, 44px);
  box-shadow: 0 1px 2px rgba(28, 28, 28, .04), 0 10px 28px -22px rgba(28, 28, 28, .22);
  margin: 0 0 clamp(14px, 1.8vw, 20px);
}
.sec-box-head .exp-title,
.sec-box-head .think__title { margin: 0; }
.sec-box-head__eyebrow {
  display: block;
  font-family: var(--sans); font-size: 0.8125rem; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; color: var(--faint, #5a6273);
  margin-bottom: clamp(10px, 1.4vw, 14px);
}
.sec-box-head__sub {
  margin: clamp(12px, 1.6vw, 16px) 0 0;
  font-family: var(--sans); font-weight: 400; font-size: 1.125rem;   /* 18px */
  line-height: 1.5; color: #2a3142; max-width: 62ch;
  text-wrap: normal;   /* greedy: fill line 1 as far as it goes */
}
/* one card holding the heading + every role, separated by hairline dividers */
.exp-list {
  display: flex; flex-direction: column;
  background: var(--surface, #fff);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg, 24px);
  box-shadow: 0 1px 2px rgba(28, 28, 28, .04), 0 10px 28px -22px rgba(28, 28, 28, .22);
  overflow: hidden;
}
.exp-head { padding: clamp(24px, 3vw, 36px) clamp(24px, 3vw, 40px) clamp(20px, 2.4vw, 28px); }
.exp-head { padding: round(clamp(24px, 3vw, 36px), 4px) round(clamp(24px, 3vw, 40px), 4px) round(clamp(20px, 2.4vw, 28px), 4px); }   /* 36 · 40 · 28 @1280 */
/* content cascade: head first, then the roles top-to-bottom (hero-style) */
.exp-list.reveal .exp-head,
.exp-list.reveal .exp-row {
  opacity: 0; transform: translateY(16px);
  transition: opacity .9s ease, transform .9s cubic-bezier(.22, 1, .36, 1);
}
.exp-list.reveal.is-in .exp-head,
.exp-list.reveal.is-in .exp-row { opacity: 1; transform: none; }
/* slower, wider stagger — the list is tall, so each row gets a longer, more
   visible arrival as the cascade travels down */
.exp-list.reveal.is-in .exp-head { transition-delay: .10s; }
.exp-list.reveal.is-in .exp-row:nth-of-type(1) { transition-delay: .34s; }
.exp-list.reveal.is-in .exp-row:nth-of-type(2) { transition-delay: .56s; }
.exp-list.reveal.is-in .exp-row:nth-of-type(3) { transition-delay: .78s; }
.exp-list.reveal.is-in .exp-row:nth-of-type(4) { transition-delay: 1.00s; }
.exp-list.reveal.is-in .exp-row:nth-of-type(5) { transition-delay: 1.22s; }
.exp-list.reveal.is-in .exp-row:nth-of-type(6) { transition-delay: 1.44s; }
@media (prefers-reduced-motion: reduce) {
  .exp-list.reveal .exp-head, .exp-list.reveal .exp-row { transition: none; opacity: 1; transform: none; }
}
.exp-head .exp-title { margin: 0; }
/* the shared 62ch cap wrapped this one-sentence summary onto a second line even
   though the card is wide enough to hold it — lift the cap here only */
.exp-head .sec-box-head__sub { margin-top: clamp(10px, 1.4vw, 14px); max-width: none; }
.exp-row {
  display: grid;
  grid-template-columns: 48px minmax(200px, 320px) 1fr;
  gap: clamp(20px, 2.66vw, 44px); align-items: center;
  gap: round(clamp(20px, 2.66vw, 44px), 4px);   /* 36 @1280 */
  padding: clamp(20px, 2.2vw, 24px) clamp(24px, 3vw, 40px);
  padding: round(clamp(20px, 2.2vw, 24px), 4px) round(clamp(24px, 3vw, 40px), 4px);   /* 24 · 40 @1280 */
  border-top: 1px solid var(--line);
  transition: background .25s var(--ease, ease);
}
.exp-row:first-child { border-top: none; }
.exp-row:hover { background: rgba(13, 26, 64, .025); }
.exp-logo {
  width: 48px; height: 48px; border-radius: var(--radius-sm); flex: none;   /* matches the 48px process nodes */
  display: grid; place-items: center;
  background: #1c1c1c; color: #fff;
  font-family: var(--display); font-weight: 700; font-size: 1.125rem; line-height: 1;
  box-shadow: 0 4px 12px -5px rgba(28, 28, 28, .5);
}
/* image variant — real brand marks (extracted square avatars) instead of a letter */
.exp-logo--img { background: #fff; overflow: hidden; }
.exp-logo--img img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }
.exp-role__title {
  font-family: var(--sans); font-weight: 700; line-height: 1.25;
  font-size: 1.125rem; color: #1c1c1c;                           /* 18px — one step above the 17px step names */
}
.exp-role__meta { font-family: var(--sans); font-size: 1rem; font-weight: 500; color: var(--muted); margin-top: 4px; }   /* 16px */
.exp-sep { margin: 0 8px; color: var(--faint); }
.exp-desc {
  font-family: var(--sans); font-weight: 400; font-size: 1rem; line-height: 1.5;   /* 16px — matches the process how-lines */
  color: #2a3142; max-width: 56ch; margin: 0;
}

/* wrapper is invisible on desktop — rows keep flowing in the .exp-list column */
.exp-rows { display: contents; }

@media (max-width: 720px) {
  .exp-row { grid-template-columns: 48px 1fr; row-gap: 14px; }
  .exp-desc { grid-column: 1 / -1; }
}

@media (max-width: 620px) {
  /* experience on mobile: the six roles as a horizontal swipe row of cards
     inside the box — one card of scroll height instead of six stacked
     (same pattern as the snapshot stats) */
  .exp-rows {
    display: flex; gap: 12px;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    padding: 4px 16px 20px;
  }
  .exp-rows::-webkit-scrollbar { display: none; }
  .exp-row {
    flex: 0 0 78%; max-width: 300px;
    scroll-snap-align: center;
    display: flex; flex-direction: column; align-items: flex-start; gap: 12px;
    background: #fff; border: 1px solid var(--line); border-radius: 16px;
    padding: 18px 16px;
  }
  .exp-row:first-child { border-top: 1px solid var(--line); }   /* cards keep a full border */
  .exp-head { padding-bottom: 12px; }
}

/* STACK: title + a single small row of tool tiles, all in one card */
.stack-card {
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius-lg, 24px);
  box-shadow: 0 1px 2px rgba(28, 28, 28, .04), 0 10px 28px -22px rgba(28, 28, 28, .22);
  padding: clamp(22px, 2.6vw, 32px) clamp(24px, 3vw, 40px);
}
.stack-card__title {
  font-family: "Averia Serif Libre", var(--display); font-weight: 700;
  line-height: 1.16; letter-spacing: -0.01em; color: #1c1c1c;
  font-size: clamp(1.875rem, 3.4vw, 2.6rem);
  margin: 0 0 clamp(18px, 2.2vw, 26px);
}
.stack-grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(16, 1fr); gap: clamp(8px, 1vw, 12px);
}
.stack-ic {
  aspect-ratio: 1; border-radius: 12px;
  background: #f6f7f9; border: 1px solid var(--line);
  display: grid; place-items: center; color: #1c1c1c;
  transition: transform .25s var(--ease, ease), box-shadow .25s, border-color .25s, background .25s;
}
.stack-ic:hover {
  transform: translateY(-3px); background: #fff;
  border-color: var(--line-2, rgba(28, 28, 28, .14));
  box-shadow: 0 2px 4px rgba(28, 28, 28, .05), 0 14px 28px -18px rgba(28, 28, 28, .4);
}
.stack-ic svg { width: clamp(20px, 1.9vw, 24px); height: clamp(20px, 1.9vw, 24px); display: block; }
@media (max-width: 900px) { .stack-grid { grid-template-columns: repeat(8, 1fr); } }
@media (max-width: 480px) { .stack-grid { grid-template-columns: repeat(6, 1fr); } }

/* =====================================================================
   SHIPPING  → two columns of icon + title + blurb (posts | plugins)
   ===================================================================== */
.ship { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 5vw, 72px); align-items: start; }
.ship-col { display: flex; flex-direction: column; gap: clamp(14px, 1.8vw, 22px); }
.ship-item { display: flex; gap: 16px; align-items: flex-start; }
.ship-ico {
  width: 46px; height: 46px; flex: none; border-radius: var(--radius-sm);
  background: var(--c, #e7ebf3); background-size: cover;
  box-shadow: 0 3px 10px -5px rgba(13,26,64,.3);
  display: grid; place-items: center; color: #fff; font-size: 1.1rem;
}
.ship-ico--dark { background: #1c1c1c; }
.ship-ico--fig  { background: #1c1c1c; }
.ship-title { font-family: var(--sans); font-weight: 700; font-size: 1.0625rem; line-height: 1.3; color: #1c1c1c; }
.ship-title--sm { font-size: 1rem; }
.ship-tag { font-weight: 500; color: var(--faint); }
.ship-desc { font-family: var(--sans); font-size: 0.9375rem; line-height: 1.45; color: var(--muted); margin-top: 4px; }


/* =====================================================================
   BIO  → about + stats + portrait
   ===================================================================== */
.bio { display: grid; grid-template-columns: 1.25fr 1fr; gap: clamp(32px, 5vw, 80px); align-items: start; }
.bio__label { font-family: var(--mono); font-size: 0.75rem; letter-spacing: .14em; text-transform: uppercase; color: var(--faint); }
.bio__title { font-family: "Averia Serif Libre", var(--display); font-weight: 700; font-size: clamp(1.625rem, 2.8vw, 2.25rem); color: #1c1c1c; line-height: 1.18; letter-spacing: -0.01em; margin: 12px 0 18px; }
.bio__p { font-family: var(--sans); font-size: 1.0625rem; line-height: 1.6; color: var(--muted); margin-bottom: 16px; max-width: 56ch; }
.bio__p:last-child { margin-bottom: 0; }
.bio__side { display: flex; flex-direction: column; gap: clamp(20px, 2.4vw, 30px); }
.bio__num { font-family: "Averia Serif Libre", var(--display); font-weight: 700; font-size: clamp(1.5rem, 2.2vw, 1.875rem); color: #1c1c1c; display: block; }
.bio__stat-txt { font-family: var(--sans); font-size: 1rem; line-height: 1.5; color: var(--muted); margin-top: 6px; max-width: 36ch; }
.bio__photo { display: block; width: 100%; aspect-ratio: 16 / 11; border-radius: var(--radius); background: linear-gradient(135deg, #c9ced9, #8b93a5); }

/* =====================================================================
   WRITING  → article list with thumbnails
   ===================================================================== */
.writing__head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; border-bottom: 1px solid var(--line); padding-bottom: 18px; margin-bottom: clamp(8px, 1.4vw, 16px); }
.writing__title { font-family: "Averia Serif Libre", var(--display); font-weight: 700; font-size: clamp(1.875rem, 3.2vw, 2.5rem); color: #1c1c1c; letter-spacing: -0.01em; }
.writing__all { display: inline-flex; align-items: center; gap: 6px; font-family: var(--sans); font-size: 0.9375rem; font-weight: 500; color: var(--muted); }
.writing__all:hover { color: #1c1c1c; }
.writing__list { display: flex; flex-direction: column; }
.wr-row { display: grid; grid-template-columns: 40px 1fr 132px; gap: clamp(16px, 2.4vw, 40px); align-items: center; padding: clamp(20px, 2.4vw, 30px) 0; border-bottom: 1px solid var(--line); transition: background .25s var(--ease); }
.wr-row:hover { background: rgba(28,28,28,.02); }
.wr-num { font-family: var(--mono); font-size: 0.8125rem; color: var(--faint); }
.wr-cat { font-family: var(--mono); font-size: 0.6875rem; letter-spacing: .12em; text-transform: uppercase; color: var(--faint); }
.wr-title { font-family: var(--sans); font-weight: 700; font-size: clamp(1.0625rem, 1.5vw, 1.25rem); color: #1c1c1c; line-height: 1.3; margin: 6px 0; }
.wr-desc { font-family: var(--sans); font-size: 0.9375rem; line-height: 1.45; color: var(--muted); max-width: 60ch; }
.wr-thumb { display: block; width: 132px; height: 80px; border-radius: 12px; background: var(--c, #d7dbe4); box-shadow: 0 6px 16px -8px rgba(13,26,64,.3); }

/* =====================================================================
   SNAPSHOT  → dark intro card + headline stats grid
   ===================================================================== */
.snap { display: grid; grid-template-columns: minmax(280px, 0.9fr) 1.6fr; gap: clamp(20px, 2.6vw, 32px); align-items: stretch; }
.snap-intro { background: #1c1c1c; color: #fff; border-radius: var(--radius-lg); padding: clamp(22px, 2.2vw, 28px); display: flex; flex-direction: column; justify-content: space-between; height: 100%; }   /* space-between splits any slack from the taller stat column into the two gaps between signature, lead and list instead of pooling under the list */
/* signature image (white ink on transparent — sits directly on the dark card) */
.snap-intro__sign { display: block; margin-bottom: clamp(10px, 1.2vw, 14px); }
.snap-intro__sign img { width: clamp(106px, 12.3vw, 132px); height: auto; display: block; }   /* −12% */
/* ---- snapshot entrance: cards rise one by one (hero-style stagger) ----
   The wrapper stops animating as a single block; each card gets its own rise. */
.snap.reveal { opacity: 1; transform: none; transition: none; }
.snap.reveal .snap-intro,
.snap.reveal .snap-stat {
  opacity: 0; transform: translateY(22px);
  transition: opacity .85s cubic-bezier(.22, 1, .36, 1), transform .85s cubic-bezier(.22, 1, .36, 1);
}
.snap.reveal.is-in .snap-intro,
.snap.reveal.is-in .snap-stat { opacity: 1; transform: none; }
.snap.reveal.is-in .snap-intro { transition-delay: .06s; }
.snap.reveal.is-in .snap-stats > .snap-stat:nth-of-type(1) { transition-delay: .28s; }
.snap.reveal.is-in .snap-stats > .snap-stat:nth-of-type(2) { transition-delay: .46s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(1) { transition-delay: .64s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(2) { transition-delay: .78s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(3) { transition-delay: .92s; }
/* inner cascade — hero-style: each card lands, then its number rises, then its
   lines follow one by one (delays = card delay + .14 / .24 / .34) */
.snap.reveal .snap-num,
.snap.reveal .snap-stat-list li {
  opacity: 0; transform: translateY(10px);
  transition: opacity .7s ease, transform .7s cubic-bezier(.22, 1, .36, 1);
}
.snap.reveal.is-in .snap-num,
.snap.reveal.is-in .snap-stat-list li { opacity: 1; transform: none; }
.snap.reveal.is-in .snap-stats > .snap-stat:nth-of-type(1) .snap-num { transition-delay: .54s; }
.snap.reveal.is-in .snap-stats > .snap-stat:nth-of-type(1) .snap-stat-list li:nth-child(1) { transition-delay: .70s; }
.snap.reveal.is-in .snap-stats > .snap-stat:nth-of-type(1) .snap-stat-list li:nth-child(2) { transition-delay: .86s; }
.snap.reveal.is-in .snap-stats > .snap-stat:nth-of-type(2) .snap-num { transition-delay: .72s; }
.snap.reveal.is-in .snap-stats > .snap-stat:nth-of-type(2) .snap-stat-list li:nth-child(1) { transition-delay: .88s; }
.snap.reveal.is-in .snap-stats > .snap-stat:nth-of-type(2) .snap-stat-list li:nth-child(2) { transition-delay: 1.04s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(1) .snap-num { transition-delay: .90s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(1) .snap-stat-list li:nth-child(1) { transition-delay: 1.06s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(1) .snap-stat-list li:nth-child(2) { transition-delay: 1.22s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(2) .snap-num { transition-delay: 1.04s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(2) .snap-stat-list li:nth-child(1) { transition-delay: 1.20s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(2) .snap-stat-list li:nth-child(2) { transition-delay: 1.36s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(3) .snap-num { transition-delay: 1.18s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(3) .snap-stat-list li:nth-child(1) { transition-delay: 1.34s; }
.snap.reveal.is-in .snap-impacts .snap-stat:nth-of-type(3) .snap-stat-list li:nth-child(2) { transition-delay: 1.50s; }
@media (prefers-reduced-motion: reduce) {
  .snap.reveal .snap-intro, .snap.reveal .snap-stat,
  .snap.reveal .snap-num, .snap.reveal .snap-stat-list li { transition: none; opacity: 1; transform: none; }
}

/* "signed by hand" entrance — signature writes in left-to-right, lead rises, bullets cascade */
.snap.reveal .snap-intro__sign img {
  clip-path: inset(0 100% 0 0);
  transition: clip-path .9s cubic-bezier(.55, 0, .1, 1) .15s;
}
.snap.reveal.is-in .snap-intro__sign img { clip-path: inset(0 -8% 0 0); }
.snap.reveal .snap-intro__lead,
.snap.reveal .snap-intro__list li {
  opacity: 0; transform: translateY(10px);
  transition: opacity .75s ease, transform .75s cubic-bezier(.22, 1, .36, 1);
}
.snap.reveal.is-in .snap-intro__lead { opacity: 1; transform: none; transition-delay: .70s; }
.snap.reveal.is-in .snap-intro__list li { opacity: 1; transform: none; }
.snap.reveal.is-in .snap-intro__list li:nth-child(1) { transition-delay: 1.00s; }
.snap.reveal.is-in .snap-intro__list li:nth-child(2) { transition-delay: 1.16s; }
.snap.reveal.is-in .snap-intro__list li:nth-child(3) { transition-delay: 1.32s; }
@media (prefers-reduced-motion: reduce) {
  .snap.reveal .snap-intro__sign img { transition: none; clip-path: none; }
  .snap.reveal .snap-intro__lead, .snap.reveal .snap-intro__list li { transition: none; opacity: 1; transform: none; }
}
.snap-intro__lead {
  font-family: "Averia Serif Libre", var(--display); font-style: normal; font-weight: 700;   /* matches headings */
  font-size: clamp(1.125rem, 1.563vw, 1.25rem); line-height: 1.35; color: #fff;   /* 20px cap (lands 20 @1280) */
  margin: 0 0 clamp(20px, 2vw, 28px); text-wrap: balance;
  margin-bottom: round(clamp(20px, 2vw, 28px), 4px);   /* 24 @1280 */
}
.snap-intro__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: clamp(8px, 1vw, 10px); }
.snap-intro__list li {
  position: relative; padding-left: 22px;
  font-family: var(--sans); font-weight: 400; font-size: 1rem; line-height: 1.45;   /* 16px */
  color: rgba(255,255,255,.72);
}
.snap-intro__list li::before {
  content: ""; position: absolute; left: 2px; top: .55em;
  width: 7px; height: 7px; border-radius: 50%; background: rgba(255,255,255,.55);
}
.snap-intro__btn.btn { margin-top: auto; align-self: flex-start; background: #fff; color: #1c1c1c; height: 44px; padding: 0 22px; }
.snap-stats { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: clamp(12px, 1.4vw, 16px); }   /* rows share the leftover height so the stat column ends level with the dark card instead of stopping ~90px short */
.snap-stat { background: #fff; border: 1px solid var(--line); border-radius: var(--radius-lg); padding: clamp(16px, 1.9vw, 24px); box-shadow: var(--shadow-sm); display: flex; flex-direction: column; justify-content: center; gap: clamp(12px, 1.4vw, 18px); }   /* lands 24 @1280 (even). The rows stretch to meet the dark card; centring the number + line as one cluster splits the slack evenly, where space-between read as a hole in the middle. */
.snap-stat--wide { grid-column: 1 / -1; }
.snap-impacts { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(10px, 1.2vw, 14px); }
.snap-impacts .snap-num { font-size: clamp(1.75rem, 2.2vw, 2rem); }   /* 32px @1280 — a step under the top row so three-up cards keep breathing room */
/* Three-up cards are only ~214px wide. Inline, the icon + its gap ate 26 of the
   166px content box, leaving 138px — narrow enough that “adopted shared tokens,”
   could not hold together on one line. Stacking the icon and trimming the padding
   returns the full 174px to the text. */
.snap-impacts .snap-stat { padding: clamp(14px, 1.6vw, 20px); }
.snap-impacts .snap-stat-list li { display: block; }
.snap-impacts .snap-stat-list svg { float: left; margin: 2px 9px 0 0; }   /* floated, not a flex column: the icon shares the first line, but only that line pays for it — every line below runs the full 174px */
@media (max-width: 560px) { .snap-impacts { grid-template-columns: 1fr; } }
.snap-num { font-family: "Averia Serif Libre", var(--display); font-weight: 700; font-size: clamp(1.875rem, 2.5vw, 2.25rem); color: #1c1c1c; display: block; margin-bottom: 10px; line-height: 1.1; }   /* 36px @1280 — the number carries the card; the single support line stays 16px */
/* label on its own line under the number — consistent alignment for all five, no wrapping */
.snap-num em {
  display: block; margin: 4px 0 0;
  font-family: var(--sans); font-style: normal; font-weight: 600;
  font-size: 0.75rem; letter-spacing: 0.07em; text-transform: uppercase;
  color: #0c0d12; line-height: 1.2;   /* matches the project-card stat label ink */
}
.snap-stat-txt { font-family: var(--sans); font-weight: 400; font-size: 1.0625rem; line-height: 1.45; color: #2a3142; max-width: 48ch; }
/* stat bullets — icon + line, two per card (mirrors the project-card impact rows) */
.snap-stat-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.snap-stat-list li {
  display: flex; align-items: flex-start; gap: 9px;
  font-family: var(--sans); font-weight: 400; font-size: 1rem; line-height: 1.4; color: #2a3142;   /* 16px */
}
.snap-stat-list svg { flex: none; width: 17px; height: 17px; margin-top: 2px; color: #767f8f; }   /* ~10% darker for stronger icon presence */

@media (max-width: 860px) {
  .ship, .bio, .snap { grid-template-columns: 1fr; }
  .snap-stats { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 620px) {
  .wr-row { grid-template-columns: 28px 1fr; }
  .wr-thumb { display: none; }
  /* snapshot stats on mobile: full cards, but as a horizontal swipe row —
     one card of scroll height instead of five stacked (site's mobile pattern) */
  .snap-stats {
    display: flex; gap: 12px;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    margin: 0 calc(-1 * var(--gutter));                   /* bleed to screen edge */
    padding: 2px var(--gutter) 6px;
  }
  .snap-stats::-webkit-scrollbar { display: none; }
  .snap-impacts { display: contents; }                    /* impacts join the same row */
  .snap-stat {
    flex: 0 0 78%; max-width: 300px;
    scroll-snap-align: center;
  }
}

/* =====================================================================
   HERO — static two-line heading + two-line sub · résumé ghost CTA
   ===================================================================== */
.hero__em { font-style: italic; }   /* AI phrase: quiet italic accent, no animation */
.hero__i  { font-style: italic; font-weight: 600; color: var(--ink, #1c1c1c); }  /* B2B/B2C + AI emphasis */
.hero__b  { font-weight: 600; color: inherit; }  /* B2B/B2C + AI: light bold, same color */
.hero__b--strong { font-weight: 700; }           /* "7+ years": a touch heavier */
/* secondary CTA: quiet ghost résumé button */
.hero__resume { gap: 0; transform-origin: center; transition: transform .4s cubic-bezier(.34, 1.56, .5, 1), box-shadow .35s ease, border-color .35s ease; }
/* download icon hidden at rest, slides in on hover — mirrors the primary CTA arrow reveal */
.hero__resume-ic {
  flex: none; width: 0; opacity: 0; margin-left: 0; transform: translateX(-6px);
  transition: width .35s var(--ease, ease), opacity .25s, margin-left .35s var(--ease, ease), transform .35s var(--ease, ease);
}
.hero__resume:hover,
.hero__resume:focus-visible {
  transform: scale(1.06);   /* same spring zoom as the primary CTA */
  border-color: rgba(12, 13, 18, .48);
  box-shadow: 0 14px 28px -14px rgba(28, 28, 28, .35);
}
.hero__resume:hover .hero__resume-ic,
.hero__resume:focus-visible .hero__resume-ic { width: 16px; opacity: 1; margin-left: 8px; transform: translateX(0); }
.hero__resume:active { transform: scale(.99); }
@media (prefers-reduced-motion: reduce) {
  .hero__resume, .hero__resume-ic { transition: none; }
  .hero__resume:hover { transform: none; }
}
/* the hard line breaks only make sense on wide screens; let text wrap naturally on mobile */
@media (max-width: 620px) {
  .hero__title br, .hero__sub br, .philo__title br { display: none; }
}

/* ---- Container system ---------------------------------------------------
   Every page-level container paints the same box. Before this there were four
   competing recipes: hero/footer at 18px-50px .22, approach + process at
   10px-28px .22, the project cards at 24px-50px .32, and the snapshot tiles
   nearly flat at 2px-8px .04 — plus two different border colours (#e7eaf1 and
   rgba(12,13,18,.08)) that read as the same grey until you put them side by side.

   .study is deliberately NOT in this list: the project cards are the only
   clickable containers, and their heavier lift is what separates “this is a
   link” from “this is a panel”. */
.hero-box,
.cta-final,
.footer__card,
.reach-markets,
.tst,
.bento-card,
.exp-list,
.snap-stat {
  border: 1px solid rgba(12, 13, 18, .08);
  border-radius: var(--radius-lg, 24px);
  box-shadow: 0 1px 2px rgba(28, 28, 28, .04), 0 10px 28px -22px rgba(28, 28, 28, .22);
}

/* =====================================================================
   CONTACT PAGE  ->  one container card: head + (form | rail)
   Same box, heading step and micro-labels as the homepage sections; the
   rail reuses the footer's cta-mail / cta-link components verbatim so
   the copy control and the chip animations are one source of truth.
   ===================================================================== */
/* contact.html carries no footer (the form IS the call to action), so the
   section supplies the page-closing gap the footer normally provides — same
   clamp as .cta-foot's padding-bottom. */
.section:has(.contact-card) { padding-bottom: clamp(40px, 6vw, 76px); }
.contact-card {
  background: var(--surface, #fff);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg, 24px);
  box-shadow: 0 1px 2px rgba(28, 28, 28, .04), 0 10px 28px -22px rgba(28, 28, 28, .22);
  overflow: hidden;
}
.contact-card__head {
  padding: clamp(28px, 3.2vw, 40px) clamp(24px, 3vw, 40px) clamp(20px, 2.4vw, 28px);
  padding: round(clamp(28px, 3.2vw, 40px), 4px) round(clamp(24px, 3vw, 40px), 4px) round(clamp(20px, 2.4vw, 28px), 4px);   /* 40 - 40 - 28 @1280, mirrors .exp-head */
}
.contact-title {
  font-family: "Averia Serif Libre", var(--display);
  font-weight: 700; line-height: 1.16; letter-spacing: -0.01em;
  font-size: clamp(1.625rem, 1.325rem + 1.16vw, 2.25rem); color: #1c1c1c;   /* shared section-heading step (36px cap) */
  margin: 0; text-wrap: balance;
}
/* one-line head like .exp-head: the card is wide enough, so no ch caps */
.contact-card__head .sec-box-head__sub { max-width: none; }

.contact-body {
  display: grid; grid-template-columns: 1.08fr .92fr;
  border-top: 1px solid var(--line);
}

/* ---- form (left) ---- */
.contact-form {
  padding: clamp(24px, 3vw, 36px) clamp(24px, 3vw, 40px) clamp(28px, 3.2vw, 40px);
  padding: round(clamp(24px, 3vw, 36px), 4px) round(clamp(24px, 3vw, 40px), 4px) round(clamp(28px, 3.2vw, 40px), 4px);
}
.contact-form .frow { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
.contact-form .field { margin-bottom: 20px; }
.contact-form .field label {
  font-family: var(--sans); font-size: 0.8125rem; font-weight: 600;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2, #232934);
  margin-bottom: 8px;   /* homepage micro-label voice (snap-num em / crail labels) */
}
.contact-form .field input,
.contact-form .field textarea {
  border-color: var(--line-2);   /* firmer than the card hairline so the wells read as controls */
  border-radius: var(--radius-sm);
  background: var(--surface, #fff);
}
.contact-form .field input:hover,
.contact-form .field textarea:hover { border-color: rgba(12, 13, 18, .24); }
.contact-form .field input::placeholder,
.contact-form .field textarea::placeholder { color: #9aa1af; }
.contact-form .field textarea { min-height: 196px; }   /* sized so form and rail bottom out together at 1280 */
/* send: the site's prominent primary step (44 - 0 24 - 18) with the
   cta-book spring hover + arrow reveal, exactly like Book a Call */
.contact-send-row { display: flex; align-items: center; flex-wrap: wrap; gap: 16px; margin-top: 4px; }
.contact-send.btn { height: 44px; padding: 0 24px; font-size: 1.125rem; }
.contact-send-note { margin: 0; font-family: var(--sans); font-size: 0.875rem; color: var(--faint, #5a6273); }

/* ---- rail (right) ---- */
.contact-rail {
  border-left: 1px solid var(--line);
  padding: clamp(24px, 3vw, 36px) clamp(24px, 3vw, 40px) clamp(28px, 3.2vw, 40px);
  padding: round(clamp(24px, 3vw, 36px), 4px) round(clamp(24px, 3vw, 40px), 4px) round(clamp(28px, 3.2vw, 40px), 4px);
  display: flex; flex-direction: column; gap: clamp(20px, 2.4vw, 28px);
}
/* availability: soft panel opener - hero status pill + one support line */
.crail-avail {
  background: var(--bg-soft, #f6f7f9);
  border: 1px solid var(--line);
  border-radius: var(--radius, 16px);
  padding: 18px 20px 20px;
}
.crail-avail .status { font-size: 0.875rem; padding: 6px 12px 6px 10px; }   /* the hero pill scales to 24px; step it down to UI size here */
.crail-avail .status .status__dot { width: 9px; height: 9px; }
.crail-avail__txt {
  margin: 12px 0 0; font-family: var(--sans); font-weight: 400;
  font-size: 1rem; line-height: 1.5; color: #2a3142;
}
.crail-label {
  display: block; margin-bottom: 10px;
  font-family: var(--sans); font-size: 0.8125rem; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; color: var(--faint, #5a6273);   /* same voice as .sec-box-head__eyebrow */
}
/* footer components, stretched to the rail column */
.contact-rail .cta-mail { display: flex; width: 100%; justify-content: space-between; }
.contact-rail .cta-mail__addr { overflow: hidden; text-overflow: ellipsis; }
.crail-links { display: flex; flex-direction: column; gap: 10px; }
.contact-rail .cta-link { width: 100%; padding: 0 6px 0 14px; border-color: var(--line-2); }   /* #eef1f6 was tuned for the footer card; on white it vanished */
.contact-rail .cta-link .cta-link__chip { margin-left: auto; }
/* meta: ruled rows pinned to the rail foot so the two columns bottom out together */
.crail-meta { list-style: none; margin: auto 0 0; padding: 0; }
.crail-meta li {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  padding: 13px 2px; border-top: 1px solid var(--line);
}
.crail-meta .k {
  font-family: var(--sans); font-size: 0.8125rem; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; color: var(--faint, #5a6273);
}
.crail-meta .v { font-family: var(--sans); font-size: 1rem; font-weight: 500; color: var(--ink-2, #232934); }

/* content cascade on scroll-in: head, then form, then rail (exp-list pattern) */
.contact-card.reveal .contact-card__head,
.contact-card.reveal .contact-form,
.contact-card.reveal .contact-rail {
  opacity: 0; transform: translateY(16px);
  transition: opacity .9s ease, transform .9s cubic-bezier(.22, 1, .36, 1);
}
.contact-card.reveal.is-in .contact-card__head,
.contact-card.reveal.is-in .contact-form,
.contact-card.reveal.is-in .contact-rail { opacity: 1; transform: none; }
.contact-card.reveal.is-in .contact-card__head { transition-delay: .10s; }
.contact-card.reveal.is-in .contact-form      { transition-delay: .30s; }
.contact-card.reveal.is-in .contact-rail      { transition-delay: .50s; }
@media (prefers-reduced-motion: reduce) {
  .contact-card.reveal .contact-card__head, .contact-card.reveal .contact-form,
  .contact-card.reveal .contact-rail { transition: none; opacity: 1; transform: none; }
}

@media (max-width: 900px) {
  .contact-body { grid-template-columns: 1fr; }
  .contact-rail { border-left: 0; border-top: 1px solid var(--line); }
}
@media (max-width: 560px) {
  .contact-form .frow { grid-template-columns: 1fr; }
  .contact-send-row { align-items: flex-start; flex-direction: column; gap: 12px; }
  .contact-send.btn { width: 100%; max-width: 340px; justify-content: center; }
}

/* ============================================================
   NOTES & CRAFT — three writing cards (left) + five craft notes (right)
   Sits below the process section, in the same .bento-card shell.
   Cards are BORDERED, not filled: the homepage already spends
   #f6f7f9 on card media stages and process panels, so another
   grey block here would flatten the page.
   ============================================================ */
.notes.bento-card { padding: clamp(20px, 2.2vw, 28px); }
.notes__grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 3.2vw, 48px);
}
/* ---- left: three writing cards ---- */
.notes__reads { display: grid; gap: 8px; }
.note-read {
  display: grid; grid-template-columns: 88px minmax(0, 1fr); gap: 20px;
  align-items: center;
  padding: 12px; border-radius: var(--radius, 24px);
  background: #fff; border: 1px solid rgba(12, 13, 18, .12);
  text-decoration: none; color: inherit;
  transition: border-color .35s ease, box-shadow .45s ease,
              transform .5s cubic-bezier(.34, 1.56, .5, 1);
}
/* the same hover the ghost buttons use: spring the scale, deepen the edge */
.note-read:hover,
.note-read:focus-visible {
  border-color: rgba(12, 13, 18, .30);
  box-shadow: 0 14px 28px -18px rgba(28, 28, 28, .35);
  transform: translateY(-3px);
}
.note-read__tile {
  width: 80px; height: 80px; border-radius: 18px;
  display: grid; place-items: center;
  background: #f6f7f9; color: #1c1c1c;
  transition: background .35s ease, color .35s ease;
}
.note-read__tile svg { width: 28px; height: 28px; }
.note-read:hover .note-read__tile { background: #1c1c1c; color: #fff; }
.note-read__body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.note-read__meta { color: var(--faint, #6b7280); }
.note-read__title {
  font-family: var(--sans); font-weight: 700; font-size: 1.0625rem;
  line-height: 1.3; letter-spacing: -0.01em; color: #1c1c1c;
}
.note-read__desc {
  font-family: var(--sans); font-weight: 400; font-size: 0.9375rem;
  line-height: 1.5; color: #2a3142;
}

/* ---- right: five craft notes — compact rows, dark icon square ---- */
.notes__tips { list-style: none; margin: 0; padding: 0; display: grid; gap: 16px; }
.note-tip { display: grid; grid-template-columns: 48px minmax(0, 1fr); gap: 16px; align-items: start; }
.note-tip__ic {
  width: 48px; height: 48px; border-radius: 14px;
  display: grid; place-items: center;
  background: #1c1c1c; color: #fff;
}
.note-tip__ic svg { width: 22px; height: 22px; }
.note-tip__body { min-width: 0; }
.note-tip__head {
  margin: 0; display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px;
  font-family: var(--sans); font-size: 1.0625rem; line-height: 1.3;
}
.note-tip__name { font-weight: 700; color: #1c1c1c; letter-spacing: -0.01em; }
.note-tip__sep { color: rgba(12, 13, 18, .28); }
.note-tip__kind { font-weight: 500; color: var(--faint, #6b7280); }
.note-tip__desc {
  margin: 6px 0 0; font-family: var(--sans); font-weight: 400;
  font-size: 0.9375rem; line-height: 1.5; color: #2a3142;
}

/* reveal — joins the staggered entrance the process card uses */
.bento.reveal .notes__grid { opacity: 0; transform: translateY(14px); transition: opacity .7s ease, transform .7s cubic-bezier(.2,.7,.3,1); }
.bento.reveal.is-in .notes__grid { opacity: 1; transform: none; transition-delay: .42s; }

@media (min-width: 901px) {
  /* three tall cards against five compact rows: spread the rows so both
     columns finish on the same line. The column is a grid item so it already
     stretches, but the <ul> inside it does not — hence the flex column. */
  .notes__col { display: flex; flex-direction: column; }
  .notes__tips { flex: 1 1 auto; align-content: space-between; }
}
@media (max-width: 900px) {
  .notes__grid { grid-template-columns: 1fr; gap: 32px; }
}
@media (max-width: 620px) {
  .note-read { grid-template-columns: 56px minmax(0, 1fr); gap: 16px; padding: 12px; }
  .note-read__tile { width: 56px; height: 56px; border-radius: 14px; }
  .note-read__tile svg { width: 22px; height: 22px; }
  /* Measured, not guessed: at 375 the meta line needs 182.4px in a 181px box.
     .eyebrow here is 14px/600, so its 0.56px tracking over 22 characters is
     what pushes it 1.4px over and onto a second line. */
  .note-read__meta { letter-spacing: .02em; }
  .notes__tips { gap: 18px; }
  .note-tip { grid-template-columns: 42px minmax(0, 1fr); gap: 14px; }
  .note-tip__ic { width: 42px; height: 42px; border-radius: 12px; }
  .note-tip__ic svg { width: 19px; height: 19px; }
}
@media (prefers-reduced-motion: reduce) {
  .note-read, .note-read__tile { transition: none; }
  .note-read:hover { transform: none; }
  .bento.reveal .notes__grid { opacity: 1; transform: none; }
}
