/* ============================================================
   site.css — generated by tools/build-css.mjs. DO NOT EDIT.
   Edit the source files below, re-run the script, and bump the
   ?v= query on the site.css <link> tags.
   Sources: progressive-blur.css, sticky-nav.css, figtree.css, page-transitions.css, marquee.css, footer.css
   ============================================================ */


/* ================== source: progressive-blur.css ================== */
/* ============================================================
   Progressive blur — fixed strip at the bottom of the viewport.
   3 stacked layers (was 8) — each backdrop-filter layer forces a
   separate GPU compositing pass over the page, so fewer layers
   means dramatically cheaper scrolling. Wide overlapping
   bell-shaped masks cross-fade the blur amounts so the ramp
   still reads as continuous across the 96px strip.
   The bottom layer anchors fully opaque to 100% so the maximum
   blur reaches the viewport edge.
   ============================================================ */

.pb-stack {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 96px;
  pointer-events: none;
  z-index: 60;
  isolation: isolate;
}

.pb-stack > .pb-layer {
  position: absolute;
  inset: 0;
}

/* --- Layer 1 — gentle blur easing in from the top edge --- */
.pb-stack > .pb-layer:nth-child(1) {
  -webkit-backdrop-filter: blur(0.5px);
  backdrop-filter: blur(0.5px);
  -webkit-mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0.5) 8%,
    rgba(0, 0, 0, 1) 16%,
    rgba(0, 0, 0, 1) 26%,
    rgba(0, 0, 0, 0.5) 36%,
    rgba(0, 0, 0, 0) 48%
  );
  mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0.5) 8%,
    rgba(0, 0, 0, 1) 16%,
    rgba(0, 0, 0, 1) 26%,
    rgba(0, 0, 0, 0.5) 36%,
    rgba(0, 0, 0, 0) 48%
  );
}

/* --- Layer 2 — medium blur through the middle of the strip --- */
.pb-stack > .pb-layer:nth-child(2) {
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  -webkit-mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 28%,
    rgba(0, 0, 0, 0.5) 40%,
    rgba(0, 0, 0, 1) 52%,
    rgba(0, 0, 0, 1) 64%,
    rgba(0, 0, 0, 0.5) 76%,
    rgba(0, 0, 0, 0) 88%
  );
  mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 28%,
    rgba(0, 0, 0, 0.5) 40%,
    rgba(0, 0, 0, 1) 52%,
    rgba(0, 0, 0, 1) 64%,
    rgba(0, 0, 0, 0.5) 76%,
    rgba(0, 0, 0, 0) 88%
  );
}

/* --- Layer 3 — anchors the strongest blur to the viewport edge --- */
.pb-stack > .pb-layer:nth-child(3) {
  -webkit-backdrop-filter: blur(6.5px);
  backdrop-filter: blur(6.5px);
  -webkit-mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 58%,
    rgba(0, 0, 0, 0.5) 78%,
    rgba(0, 0, 0, 1) 100%
  );
  mask-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 58%,
    rgba(0, 0, 0, 0.5) 78%,
    rgba(0, 0, 0, 1) 100%
  );
}

/* Soft white tint — eases the blurred content toward the page bg.
   Curve uses extra stops so it doesn't kink. */
.pb-stack > .pb-tint {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.02) 30%,
    rgba(255, 255, 255, 0.07) 55%,
    rgba(255, 255, 255, 0.15) 80%,
    rgba(255, 255, 255, 0.25) 100%
  );
}

@media print {
  .pb-stack { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .pb-stack > .pb-layer:nth-child(1),
  .pb-stack > .pb-layer:nth-child(2) {
    display: none;
  }
  .pb-stack > .pb-layer:nth-child(3) {
    -webkit-backdrop-filter: blur(5px);
    backdrop-filter: blur(5px);
  }
}


/* ================== source: sticky-nav.css ================== */
/* ============================================================
   Sticky nav pill — appears after the original Framer nav
   scrolls past the viewport top. Floats centered at the top
   with glass treatment, morphs in smoothly.

   Motion rules:
   - GPU-only (transform + opacity + filter:blur)
   - Custom ease-out cubic-bezier (stronger than CSS default)
   - Asymmetric enter (240ms) / exit (180ms)
   - transform-origin: top center (morphs from where the original nav was)
   - scale starts at 0.96, never 0
   - blur(2px) during transit masks the visual swap
   - prefers-reduced-motion: opacity only
   - hover gated to fine pointer
   ============================================================ */

:root {
  --snav-ease: cubic-bezier(0.23, 1, 0.32, 1);
}

.snav {
  position: fixed;
  top: 14px;
  left: 50%;
  z-index: 110;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 6px 8px 6px 6px;
  border-radius: 999px;
  background-color: rgba(255, 255, 255, 0.62);
  -webkit-backdrop-filter: blur(18px) saturate(1.6);
  backdrop-filter: blur(18px) saturate(1.6);
  box-shadow:
    0 0.5px 0 rgba(255, 255, 255, 0.7) inset,
    0 -0.5px 0 rgba(0, 0, 0, 0.05) inset,
    0 8px 24px -12px rgba(0, 0, 0, 0.18),
    0 2px 6px -3px rgba(0, 0, 0, 0.08);
  /* Hidden state */
  opacity: 0;
  transform: translate3d(-50%, -10px, 0) scale(0.96);
  filter: blur(2px);
  pointer-events: none;
  transform-origin: top center;
  /* Exit transition (180ms, snappy) */
  transition:
    opacity 180ms var(--snav-ease),
    transform 180ms var(--snav-ease),
    filter 180ms var(--snav-ease),
    background-color 320ms var(--snav-ease),
    box-shadow 320ms var(--snav-ease);
}

.snav[data-visible="1"] {
  opacity: 1;
  transform: translate3d(-50%, 0, 0) scale(1);
  filter: blur(0);
  pointer-events: auto;
  /* Enter transition (240ms, more presence) */
  transition:
    opacity 240ms var(--snav-ease),
    transform 240ms var(--snav-ease),
    filter 240ms var(--snav-ease),
    background-color 320ms var(--snav-ease),
    box-shadow 320ms var(--snav-ease);
}

/* Subtle top sheen on the pill itself (glass craft) */
.snav::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.45) 0%,
    rgba(255, 255, 255, 0) 45%
  );
  mix-blend-mode: overlay;
  opacity: 0.9;
}

/* Logo button */
.snav-logo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 999px;
  color: #1a1a1a;
  text-decoration: none;
  transition: background-color 160ms var(--snav-ease),
              transform 140ms var(--snav-ease),
              color 320ms var(--snav-ease);
  flex-shrink: 0;
  position: relative;
  z-index: 1;
}
.snav-logo svg {
  width: 34px;
  height: 34px;
  display: block;
}
.snav-logo:active { transform: scale(0.94); }

/* Vertical divider after the logo */
.snav-sep {
  width: 1px;
  height: 16px;
  margin: 0 4px;
  background: rgba(0, 0, 0, 0.08);
  flex-shrink: 0;
  transition: background-color 320ms var(--snav-ease);
}

/* Nav links */
.snav-link {
  display: inline-block;
  padding: 8px 12px;
  border-radius: 999px;
  font-family: "Figtree", "Space Grotesk", "Space Grotesk Placeholder", sans-serif;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.3px;
  color: rgba(0, 0, 0, 0.62);
  text-decoration: none;
  background: transparent;
  position: relative;
  z-index: 1;
  transition:
    color 160ms var(--snav-ease),
    background-color 160ms var(--snav-ease),
    transform 140ms var(--snav-ease);
  white-space: nowrap;
}
.snav-link[aria-current="page"] {
  color: #e8503a;
  font-weight: 700;
}
.snav-link:active { transform: scale(0.96); }

/* ------------------------------------------------------------------
   Top nav — consistent inactive dimming across every page.
   Home dims inactive tab wrappers to .5 (so the dark link text reads
   gray) and brings them to full on hover; inner pages shipped them at
   full opacity (black). Replicate home everywhere. "Inactive" = a
   wrapper whose link isn't the current page — which leaves the active
   tab (accent <p>, or home's <a data-…current>) untouched.
   ------------------------------------------------------------------ */
nav.framer-WLHpg .framer-1gxxlpg > div { transition: opacity 0.2s ease; }
nav.framer-WLHpg .framer-1gxxlpg > div:has(a:not([data-framer-page-link-current])) {
  opacity: 0.5 !important;
}
nav.framer-WLHpg .framer-1gxxlpg > div:has(a:not([data-framer-page-link-current])):hover {
  opacity: 1 !important;
}

/* ------------------------------------------------------------------
   "Skills" tab — a "new" cue. CSS-only (::after), scoped to the Skills
   link in the top nav + sticky pill, AND to the active Skills <p> on
   the /skills page (.sk-nav-current) so the badge persists there too.
   ------------------------------------------------------------------ */
nav.framer-WLHpg a[href="./skills"]::after,
nav.framer-WLHpg .sk-nav-current::after,
.snav .snav-link[href="./skills"]::after {
  content: "new";
  font-size: 8px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  vertical-align: super;
  margin-left: 3px;
  color: #e8503a;       /* brand/accent, full opacity */
  -webkit-text-fill-color: #e8503a;
  opacity: 1;
}

@media (hover: hover) and (pointer: fine) {
  .snav-logo:hover { background-color: rgba(0, 0, 0, 0.04); }
  .snav-link:hover { background-color: rgba(0, 0, 0, 0.04); color: rgba(0, 0, 0, 1); }
}

/* Hide on small screens — the original nav still works on mobile */
@media (max-width: 720px) {
  .snav { display: none !important; }
}

/* Reduced motion: opacity-only, no transform, no blur */
@media (prefers-reduced-motion: reduce) {
  .snav {
    transform: translate3d(-50%, 0, 0);
    filter: none;
    transition: opacity 160ms linear;
  }
  .snav[data-visible="1"] {
    transform: translate3d(-50%, 0, 0);
    filter: none;
    transition: opacity 160ms linear;
  }
}


/* ============================================================
   Auto dark-mode — engaged by sticky-nav.js (data-theme="dark")
   while the pill floats over the dark "AI Lab & Experiments"
   section, so the glass reads correctly on dark surfaces.
   ============================================================ */
.snav[data-theme="dark"] {
  background-color: rgba(28, 28, 30, 0.72);
  box-shadow:
    0 0.5px 0 rgba(255, 255, 255, 0.10) inset,
    0 -0.5px 0 rgba(0, 0, 0, 0.45) inset,
    0 10px 28px -12px rgba(0, 0, 0, 0.55),
    0 2px 6px -3px rgba(0, 0, 0, 0.35);
}
.snav[data-theme="dark"]::before {
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.12) 0%,
    rgba(255, 255, 255, 0) 45%
  );
  opacity: 0.6;
}
.snav[data-theme="dark"] .snav-sep {
  background: rgba(255, 255, 255, 0.14);
}
.snav[data-theme="dark"] .snav-logo {
  color: #fff;
}
.snav[data-theme="dark"] .snav-link {
  color: rgba(255, 255, 255, 0.95) !important;
}
.snav[data-theme="dark"] .snav-link[aria-current="page"] {
  color: #ff6f59 !important;
}
@media (hover: hover) and (pointer: fine) {
  .snav[data-theme="dark"] .snav-logo:hover { background-color: rgba(255, 255, 255, 0.08); }
  .snav[data-theme="dark"] .snav-link:hover { background-color: rgba(255, 255, 255, 0.08); color: #fff !important; }
}


/* ============================================================
   Mobile menu — hamburger injected into the top "Phone" nav by
   sticky-nav.js (mountMobileMenu). The button lives inside the
   phone-only nav variant, so it's automatically hidden on desktop
   (≥1440px) where the full horizontal nav shows.
   ============================================================ */
.mnav-host { position: relative; }   /* containing block for the absolute button */

.mnav-burger {
  position: absolute;
  top: 50%;
  right: 22px;
  transform: translateY(-50%);
  z-index: 5;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: #1a1a1a;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.mnav-box { position: relative; width: 22px; height: 14px; }
.mnav-box > span {
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 0.28s var(--snav-ease), opacity 0.18s var(--snav-ease), top 0.28s var(--snav-ease);
}
.mnav-box > span:nth-child(1) { top: 0; }
.mnav-box > span:nth-child(2) { top: 6px; }
.mnav-box > span:nth-child(3) { top: 12px; }
.mnav-burger.is-open .mnav-box > span:nth-child(1) { top: 6px; transform: rotate(45deg); }
.mnav-burger.is-open .mnav-box > span:nth-child(2) { opacity: 0; }
.mnav-burger.is-open .mnav-box > span:nth-child(3) { top: 6px; transform: rotate(-45deg); }

/* dim/blur backdrop */
.mnav-overlay {
  position: fixed;
  inset: 0;
  z-index: 120;
  background: rgba(20, 20, 22, 0.30);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity 0.24s var(--snav-ease);
}
.mnav-overlay.is-open { opacity: 1; }

/* dropdown card */
.mnav-panel {
  position: fixed;
  top: 14px;
  right: 14px;
  z-index: 130;
  min-width: 224px;
  max-width: calc(100vw - 28px);
  padding: 8px;
  background: rgba(255, 255, 255, 0.92);
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  backdrop-filter: blur(20px) saturate(1.6);
  border-radius: 0;                       /* sharp corners — consistent with the rest of the site */
  box-shadow:
    0 0.5px 0 rgba(255, 255, 255, 0.7) inset,
    0 12px 40px -12px rgba(0, 0, 0, 0.32),
    0 2px 8px -4px rgba(0, 0, 0, 0.12);
  transform-origin: top right;
  opacity: 0;
  transform: translateY(-8px) scale(0.96);
  transition: opacity 0.24s var(--snav-ease), transform 0.24s var(--snav-ease);
}
.mnav-panel.is-open { opacity: 1; transform: translateY(0) scale(1); }

.mnav-list { list-style: none; margin: 0; padding: 0; }
.mnav-link {
  display: block;
  padding: 13px 16px;
  border-radius: 0;
  font-family: "Figtree", "Space Grotesk", sans-serif;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: 0.2px;
  color: #1a1a1a;
  text-decoration: none;
  transition: background-color 0.16s var(--snav-ease), color 0.16s var(--snav-ease);
}
.mnav-link[aria-current="page"] { color: #e8503a; font-weight: 700; }
.mnav-link[href="./skills"]::after {
  content: "new";
  font-size: 9px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  vertical-align: super;
  margin-left: 5px;
  color: #e8503a;
  -webkit-text-fill-color: #e8503a;
}
@media (hover: hover) { .mnav-link:hover { background: rgba(0, 0, 0, 0.05); } }
.mnav-link:active { background: rgba(0, 0, 0, 0.08); }

.mnav-overlay[hidden], .mnav-panel[hidden] { display: none !important; }
html.mnav-lock { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .mnav-box > span,
  .mnav-overlay,
  .mnav-panel { transition-duration: 0.001ms; }
  .mnav-panel { transform: none; }
  .mnav-panel.is-open { transform: none; }
}


/* ================== source: figtree.css ================== */
/* ============================================================
   Figtree global font override
   ------------------------------------------------------------
   Loads Figtree from Google Fonts and routes every existing
   typeface reference (Inter, Space Grotesk, Switzer, JetBrains
   Mono, Geist, Geist Mono, Instrument Serif, Mona Sans, Kalam,
   Kode Mono, Satoshi, Wasted Year, and their *Placeholder*
   metric-shim siblings) through Figtree without touching the
   inline Framer styles in the HTML.

   How it works:
   1. Self-hosted @font-face blocks load the Figtree variable
      font (300–900, italic + roman) from /assets/fonts/figtree
      so the family is available everywhere — no external
      Google Fonts request.
   2. @font-face aliases redeclare each existing family with
      src: local("Figtree"). Because these declarations come
      after the inline <style data-framer-font-css> block, the
      browser uses them when resolving font-family lookups —
      so "Inter", "Space Grotesk", etc. all render Figtree.
   3. A * { font-family: ... !important } rule + Framer CSS
      variable overrides act as a belt-and-braces safety net
      for any inline style="font-family:..." declarations.
   ============================================================ */

/* ---- Figtree variable font, self-hosted (was: Google Fonts @import) ---- */
/* latin */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('/assets/fonts/figtree/figtree-roman-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('/assets/fonts/figtree/figtree-roman-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* italic latin */
@font-face {
  font-family: 'Figtree';
  font-style: italic;
  font-weight: 300 900;
  font-display: swap;
  src: url('/assets/fonts/figtree/figtree-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* italic latin-ext */
@font-face {
  font-family: 'Figtree';
  font-style: italic;
  font-weight: 300 900;
  font-display: swap;
  src: url('/assets/fonts/figtree/figtree-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---- Font-family aliases: redirect every existing family to Figtree ---- */
/* The browser picks the LAST matching @font-face in document order, so as
   long as figtree.css is linked after Framer's inline font block these win. */

@font-face { font-family: "Inter";                       src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Inter";                       src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }
@font-face { font-family: "Inter Placeholder";           src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Inter Placeholder";           src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }

@font-face { font-family: "Space Grotesk";               src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Space Grotesk";               src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }
@font-face { font-family: "Space Grotesk Placeholder";   src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Space Grotesk Placeholder";   src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }

@font-face { font-family: "Switzer";                     src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Switzer";                     src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }
@font-face { font-family: "Switzer Placeholder";         src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Switzer Placeholder";         src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }

@font-face { font-family: "Geist";                       src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Geist";                       src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }
@font-face { font-family: "Geist Placeholder";           src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Geist Placeholder";           src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }
@font-face { font-family: "Geist Mono";                  src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Geist Mono";                  src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }

@font-face { font-family: "JetBrains Mono";              src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "JetBrains Mono";              src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }

@font-face { font-family: "Mona Sans";                   src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Mona Sans";                   src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }
@font-face { font-family: "Mona Sans Placeholder";       src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Mona Sans Placeholder";       src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }

@font-face { font-family: "Instrument Serif";            src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Instrument Serif";            src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }
@font-face { font-family: "Instrument Serif Placeholder";src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Instrument Serif Placeholder";src: local("Figtree Italic"), local("Figtree-Italic"); font-weight: 100 900; font-style: italic; font-display: swap; }

@font-face { font-family: "Kalam";                       src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Kode Mono";                   src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Satoshi";                     src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Wasted Year";                 src: local("Figtree"), local("Figtree-Regular"); font-weight: 100 900; font-style: normal; font-display: swap; }

/* ---- Belt-and-braces: force Figtree on every element ---- */

html, body, button, input, select, textarea, optgroup {
  font-family: 'Figtree', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
}

* {
  font-family: 'Figtree', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
}

/* NOTE: deliberately NOT ::first-letter / ::first-line here. Setting
   font-family on ::first-line repaints the first formatted line of EVERY
   element in Figtree at paint time — silently overriding any element that
   wants a different font (e.g. the Space Mono install commands on /skills),
   while getComputedStyle still reports the element's own font. That made the
   mono look applied in the inspector but render as Figtree. The element's own
   font-family already cascades to its text, so these pseudos add nothing. */
*::before,
*::after,
*::placeholder,
*::selection {
  font-family: 'Figtree', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
}

/* ---- Override every Framer font-family CSS variable ---- */
:root, html, body, [data-framer-component-type], [data-framer-component-type] * {
  --framer-font-family: 'Figtree', sans-serif !important;
  --framer-font-family-bold: 'Figtree', sans-serif !important;
  --framer-font-family-italic: 'Figtree', sans-serif !important;
  --framer-font-family-bold-italic: 'Figtree', sans-serif !important;
  --framer-blockquote-font-family: 'Figtree', sans-serif !important;
  --framer-blockquote-font-family-bold: 'Figtree', sans-serif !important;
  --framer-blockquote-font-family-italic: 'Figtree', sans-serif !important;
  --framer-blockquote-font-family-bold-italic: 'Figtree', sans-serif !important;
  --framer-link-font-family: 'Figtree', sans-serif !important;
  --framer-link-current-font-family: 'Figtree', sans-serif !important;
  --framer-link-hover-font-family: 'Figtree', sans-serif !important;
  --framer-code-font-family: 'Figtree', sans-serif !important;
  --framer-font-family-preview: 'Figtree', sans-serif !important;
  --font-family: 'Figtree', sans-serif !important;
}

/* ============================================================
   Component-level typography spec (Figma → CSS)
   ============================================================ */

/* ---- Navbar: "Available for work" badge ---- */
/* Figtree 12 / kerning 1 / rgb(138,138,138) */
[data-framer-name="Available for work"],
[data-framer-name="Available for work"] p,
[data-framer-name="Available for work"] p * {
  font-size: 12px !important;
  letter-spacing: 1px !important;
  color: rgb(138, 138, 138) !important;
  --framer-font-size: 12px !important;
  --framer-letter-spacing: 1px !important;
  --framer-text-color: rgb(138, 138, 138) !important;
  --extracted-r6o4lv: rgb(138, 138, 138) !important;
}

/* ---- Navbar links (original Framer nav) ---- */
/* Inactive: Figtree 15 / Medium / kerning 0.4 / rgb(153,153,153)
   Active:   Figtree 15 / Bold   / kerning 0.4 / rgb(232, 80, 58) */
[data-framer-name="Links"] p.framer-text {
  font-size: 15px !important;
  letter-spacing: 0.4px !important;
  --framer-font-size: 15px !important;
  --framer-letter-spacing: 0.4px !important;
}
[data-framer-name="Links"] p.framer-text a {
  font-size: 15px !important;
  font-weight: 500 !important;
  letter-spacing: 0.4px !important;
  color: #1e1e1e !important;
}
[data-framer-name="Links"] p.framer-text a[data-framer-page-link-current="true"] {
  font-weight: 700 !important;
  color: rgb(232, 80, 58) !important;
}

/* ---- Sticky-nav pill (custom): same spec ---- */
.snav-link {
  font-size: 15px !important;
  font-weight: 500 !important;
  letter-spacing: 0.4px !important;
  color: #1e1e1e !important;
}
.snav-link[aria-current="page"] {
  font-weight: 700 !important;
  color: rgb(232, 80, 58) !important;
}

/* ============================================================
   Project category cards (Work / Photography listings)
   Card = button[role="listitem"] with an aria-label
   ============================================================ */

/* ---- Tag chip (PRD, SYS, APL, FIG, A.I) ---- */
/* Figtree 9 / Medium / line-height 12 / letter-spacing 1.5px */
button[role="listitem"][aria-label] > div > div[style*="top:0"][style*="right:0"] {
  font-size: 9px !important;
  font-weight: 500 !important;
  letter-spacing: 1.5px !important;
  line-height: 12px !important;
}

/* ---- Card title (e.g. "Figma Plugins") ---- */
/* Figtree 17 / Bold / line-height 19.2 */
button[role="listitem"][aria-label] > div > div[style*="left:0"][style*="bottom:0"] > div:not(.cc-subtitle) {
  font-size: 17px !important;
  font-weight: 700 !important;
  line-height: 19.2px !important;
  letter-spacing: -0.02em !important;
}

/* ---- Card subtitle (e.g. "3 projects") ---- */
/* Figtree 13 / Medium / line-height 13.5 */
button[role="listitem"][aria-label] .cc-subtitle {
  font-size: 13px !important;
  font-weight: 500 !important;
  line-height: 13.5px !important;
  letter-spacing: 0 !important;
}

/* ============================================================
   Hero block (replaces the old PNG with coded markup).
   Centered flex column inside the parent Framer container.
   ============================================================ */
.hero-coded {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 6px 13px;
  box-sizing: border-box;
}
.hero-wordmark {
  display: block;
  width: 100%;
  height: auto;
  max-height: 70%;
  flex: 0 1 auto;
}
.hero-tagline {
  margin: 0;
  font-family: 'Figtree', system-ui, -apple-system, BlinkMacSystemFont, sans-serif !important;
  font-size: clamp(13px, 1.18vw, 17px);
  font-weight: 400;
  line-height: 1.2;
  text-align: center;
  color: rgba(0, 0, 0, 0.5);
  flex: 0 0 auto;
}
.hero-tagline * {
  font-family: 'Figtree', system-ui, -apple-system, BlinkMacSystemFont, sans-serif !important;
}
.hero-tagline .hero-experience {
  font-weight: 500 !important;
  background: linear-gradient(90deg, #F5C19E, #FA1616);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent !important;
}
.hero-tagline .hero-users {
  color: rgba(30, 30, 30, 0.25) !important;
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}



/* ================== source: page-transitions.css ================== */
/* ============================================================
   Page transitions — soft fade between full-page navigations
   ------------------------------------------------------------
   Replaces Framer's SPA cross-page transition after the Framer
   runtime is removed. Pure CSS fade driven by two classes on
   <html> that page-transitions.js toggles:
     .pt-in  → fade the page in on load / bfcache restore
     .pt-out → fade the page out just before navigating away
   No-JS / reduced-motion: no classes are added, page shows
   instantly (graceful fallback).
   ============================================================ */

@media (prefers-reduced-motion: no-preference) {
  html.pt-in body {
    animation: pt-page-in 300ms ease both;
  }
  html.pt-out body {
    opacity: 0 !important;
    transition: opacity 260ms ease;
  }
}

@keyframes pt-page-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}


/* ================== source: marquee.css ================== */
/* ============================================================
   Marquee — CSS replacement for Framer's Ticker component
   ------------------------------------------------------------
   Framer rendered horizontal tickers as a <ul> with an inline
   transform:translateX(...) (and often an opacity:0 wrapper),
   then drove the scroll + reveal with JS. marquee.js strips
   those placeholders, duplicates the items for a seamless loop,
   and adds .fx-marquee — the scroll itself is this CSS keyframe.
   Used on: index (video ticker), about, work-physicswallah,
   youtube (image marquees).
   ============================================================ */

.fx-marquee {
  width: max-content !important;
  opacity: 1 !important;
  transform: translateX(0);
  will-change: transform;
  animation: fx-marquee-scroll var(--fx-marquee-dur, 50s) linear infinite;
}

.fx-marquee:hover {
  animation-play-state: paused;
}

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

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


/* ================== source: footer.css ================== */
/* ============================================================
   Footer — shared across every page that renders the site footer
   (index, about, photography, youtube, and the work case studies).
   Page-agnostic selectors (data-framer-name / colour tokens) since
   the Framer hash classes differ per page.
   ============================================================ */

/* Tagline: "Always open to conversations about design…" → 14px */
[data-framer-name^="Always open to conversations"] p.framer-text {
  --framer-font-size: 14px !important;
  font-size: 14px !important;
}

/* Credit line: "© 2026 · Built with ❤ and cmd+z · Bengaluru, KA"
   → 12px + ALL CAPS. The 10px / rgb(200,200,200) token is unique
   to these credit parts (social labels are rgb(26,26,26)). */
p.framer-text[style*="--framer-font-size:10px"][style*="rgb(200, 200, 200)"] {
  --framer-font-size: 12px !important;
  font-size: 12px !important;
  text-transform: uppercase !important;
}

/* Social containers (Mail, X, GitHub, LinkedIn, Substack, YouTube,
   Figma) — the only `motion.a` elements on the page. Hover fills the
   container with #FAFAFA, with a smooth transition.
   Equal padding on all four sides (Framer ships `0 12px` + fixed
   height); `height:auto` lets the symmetric padding size the box
   (8px ≈ the original 33px height). */
[data-framer-name="motion.a"] {
  transition: background-color 0.2s ease !important;
  padding: 8px !important;
  height: auto !important;
}
[data-framer-name="motion.a"]:hover {
  background-color: #FAFAFA !important;
}

/* External link labels (Mail, LinkedIn, Twitter/X, …) → 12px */
[data-framer-name="motion.a"] p.framer-text {
  --framer-font-size: 12px !important;
  font-size: 12px !important;
}

/* ------------------------------------------------------------------
   Rebuilt social row (footer-links.js replaces the broken ≥1440 row on
   inner pages with these clean canonical pills — icons lifted from the
   home footer). Matches the home pills, but hovers to PURE WHITE since
   the inner-page footer sits on a #FAFAFA background (home stays on
   white + #FAFAFA hover via the rule above).
   ------------------------------------------------------------------ */
.ftx-row {
  display: flex !important;          /* beat the inherited Framer row class */
  flex-wrap: nowrap !important;
  align-items: center !important;
  justify-content: flex-start !important;
  gap: 8px !important;               /* matches the home row gap */
  width: auto !important;
  height: auto !important;
}
.ftx-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;                          /* home: icon→label gap */
  padding: 8px;                      /* home: 8px all sides */
  border: 1px solid rgba(26, 26, 26, 0.1);  /* home border colour */
  border-radius: 0;                  /* home: sharp corners, not rounded */
  font-size: 12px;
  line-height: 1;
  color: rgb(26, 26, 26);
  text-decoration: none;
  background: transparent;
  white-space: nowrap;
  transition: background-color 0.2s ease;
}
.ftx-pill:hover { background-color: #fff; }
.ftx-pill .ftx-ico { width: 11px; height: 11px; flex: none; display: inline-flex; }  /* home icon size */
.ftx-pill .ftx-ico svg { width: 100%; height: 100%; display: block; fill: currentColor; }
.ftx-pill .ftx-label { white-space: nowrap; }

