:root{
  color-scheme: dark;
  --bg: #000;
  --surface: #14141c;
  --text: #f4f4f8;
  --text-muted: #a3a3b8;
  --border: #232332;
  --nav-h: 65px; /* fallback; JS measures the real height into this var */
  /* Shared left/right edge padding - nav, footer, hero and every section read
     this one var. The max() term caps the content column at --container on
     wide screens, so every section starts and ends on the same vertical lines. */
  --gutter: max(clamp(40px, 11vw, 200px), calc((100vw - var(--container)) / 2));
  --footer-h: 560px; /* fallback; JS measures the real content height into this var */

  /* ---- Design tokens ------------------------------------------------
     Change a value here and it updates everywhere it is used. */

  /* Colour (aliases of the palette above + the few brand/status colours) */
  --color-bg: var(--bg);
  --color-surface: var(--surface);
  --color-text: var(--text);
  --color-text-muted: var(--text-muted);
  --color-border: var(--border);
  --border-strong: #3a3a4a;   /* hover / emphasised border */
  --accent: #9d2433;          /* brand red (hero "Vriyox") */
  --danger: #ff8a8a;          /* form errors */
  --on-light: #0a0a10;        /* text on white buttons */

  /* Typography - one family for the whole site */
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, sans-serif;
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --fw-black: 800;
  --fs-caption: .75rem;
  --fs-small: .875rem;
  --fs-body: .875rem;
  --fs-lead: clamp(1rem, 1.3vw, 1.125rem);
  --fs-h4: clamp(1rem, 1.6vw, 1.25rem);
  --fs-h3: clamp(1.25rem, 2.4vw, 1.75rem);
  --fs-h2: clamp(1.5rem, 4vw, 2rem);
  --fs-h1: clamp(2rem, 4.6vw, 3.25rem);
  --fs-display: clamp(2.25rem, 5vw, 3rem);
  --lh-tight: 1.1;
  --lh-heading: 1.15;
  --lh-body: 1.6;
  --ls-heading: -0.02em;
  --ls-label: .08em;

  /* Spacing scale (4px base) */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;
  --space-30: 120px;
  --section-y: clamp(64px, 9vw, 112px);   /* vertical padding of every section */

  /* Layout */
  --container: 1200px;
  --container-narrow: 768px;

  /* Radius scale */
  --radius-sm: 4px;
  --radius-md: 8px;    /* buttons, inputs, small cards */
  --radius-lg: 16px;   /* cards */
  --radius-xl: 24px;   /* large panels, hero image */
  --radius-full: 9999px;

  /* Elevation */
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, .35);
  --shadow-md: 0 10px 28px -14px rgba(0, 0, 0, .55);
  --shadow-lg: 0 30px 70px -30px rgba(0, 0, 0, .6);

  /* Motion: one easing family, three speeds */
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-in: cubic-bezier(.4, 0, .6, 1);
  --dur-fast: .2s;     /* micro interactions: hover, press, focus */
  --dur-base: .35s;    /* normal UI transitions */
  --dur-slow: .6s;     /* large elements */
  --dur-reveal: .85s;  /* scroll reveals */
}
/* Phones: one 16px side margin everywhere - the same distance the Skills card
   keeps from the screen edge - so nav, hero, every section/card and the footer
   line up on the same edges. */
@media (max-width: 600px){
  :root{ --gutter: 16px; }
}

*{ box-sizing: border-box; }

/* Never allow a horizontal scrollbar, on any viewport - a safety net for
   any element that might otherwise overflow the viewport width (long
   words, an oversized canvas frame, etc.). Set on body ONLY, with
   overflow-y forced back to visible: per the CSS overflow spec, setting
   overflow-x without overflow-y auto-computes overflow-y to "auto" on
   whichever element(s) you set it on. Doing that on BOTH html and body
   turns them into two separate, independently-scrolling containers -
   which is exactly what silently breaks position:sticky (the sticky
   header/hero panels) after a scroll, since "nearest
   scrolling ancestor" stops being the single viewport scroll everything
   else assumes. Body-only + explicit overflow-y:visible avoids that. */
body{ overflow-x: hidden; overflow-y: visible; }
html{ max-width: 100%; }

/* Site-wide smooth scrolling - glides on anchor nav (About/Portfolio/
   Skills/Contact links) and, in Chromium/Edge, ordinary wheel scroll too.
   Reduced-motion users get instant scroll instead, per their preference. */
html{ scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
}

body{
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: .875rem;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.nav{
  position: -webkit-sticky; /* older iOS Safari needs the prefix or it silently falls back to static */
  position: sticky;
  top: 0;
  z-index: 100;
  border-bottom: 1px solid var(--border);
  padding: 12px var(--gutter);
  background: var(--bg);
}

.nav__inner{
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}

.brand{
  display: inline-flex;
  align-items: center;
  font-weight: 700;
  font-size: 1.1rem;
  letter-spacing: .01em;
  color: var(--text);
  text-decoration: none;
}

.brand__label{
  white-space: nowrap;
}

.nav__links{
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex: 1;
  gap: 18px;
  margin-left: 24px;
}

.nav__links a{
  color: var(--text-muted);
  text-decoration: none;
  font-size: .875rem;
}

.nav__links a:hover{
  color: var(--text);
}

.nav__connect{
  display: inline-flex;
  align-items: center;
  padding: 11px 18px;
  border-radius: 8px;
  background: #fff;
  color: #0a0a10;
  font-weight: 600;
  font-size: .875rem;
  white-space: nowrap;
  text-decoration: none;
  transition: transform .2s;
}
/* Services hover dropdown (desktop) */
.nav__item{ position: relative; }
.nav__menu{
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 260px;
  display: none;
  flex-direction: column;
  padding-top: 26px; /* hover bridge so the menu doesn't close crossing the gap */
  z-index: 110;
}
.nav__links .nav__menu a{
  padding: 12px 16px;
  background: #fff;
  color: #0a0a10;
  border: 1px solid #e5e5e5;
  border-top: none;
  white-space: nowrap;
}
.nav__menu a:first-child{ border-top: 1px solid #e5e5e5; border-radius: 8px 8px 0 0; }
.nav__menu a:last-child{ border-radius: 0 0 8px 8px; }
.nav__links .nav__menu a:hover{ color: #000; background: #f0f0f0; }
/* Down-arrow on the trigger so users know Services opens a menu */
.nav__item--has-menu > a{
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.nav__item--has-menu > a::after{
  content: "";
  width: 6px;
  height: 6px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform .2s;
}
.nav__item--has-menu:hover > a,
.nav__item--has-menu:focus-within > a{ color: var(--text); }
.nav__item--has-menu:hover > a::after,
.nav__item--has-menu:focus-within > a::after{ transform: translateY(1px) rotate(225deg); }
.nav__item--has-menu:hover .nav__menu,
.nav__item--has-menu:focus-within .nav__menu{ display: flex; }

.nav__links a.nav__connect{ font-size: .875rem; }
.nav__links a.nav__connect,
.nav__links a.nav__connect:hover{
  color: #000;
}
.nav__connect:hover{
  transform: translateY(-1px);
}

/* ===== Mobile nav toggle (hamburger, top-right) =====
   Hidden on desktop; on small screens it replaces the always-visible link
   row so the nav never has to wrap/cram and never forces the page wider
   than the viewport (see the overflow-x guard on html/body below too). */
.nav__toggle{
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  margin-right: -10px; /* keep the bars optically flush with the gutter */
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  flex: none;
}
.nav__toggle span{
  display: block;
  width: 20px;
  height: 1px;
  background: var(--text);
  border-radius: 1px;
  transition: transform .25s, opacity .25s;
}
/* translateY = bar height (1px) + gap (5px), so the X's arms cross at the centre */
.nav__toggle[aria-expanded="true"] span:nth-child(1){ transform: translateY(6px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] span:nth-child(2){ opacity: 0; }
.nav__toggle[aria-expanded="true"] span:nth-child(3){ transform: translateY(-6px) rotate(-45deg); }

/* 900px, not 760px: with 6 nav links + the "Connect Us" pill, the full
   desktop row only clears without wrapping from ~900px up (measured) - a
   lower breakpoint here left a 761-895px dead zone where "Connect Us"
   wrapped onto its own awkward second line instead of collapsing into the
   hamburger menu with the rest of the nav. */
@media (max-width: 900px){
  .nav__toggle{ display: flex; }
  /* Full-screen menu: slides in from the right over the whole page. The brand
     and the toggle (X) stay above it (z-index 2) so the menu can be closed. */
  .brand, .nav__toggle{ position: relative; z-index: 2; }
  .nav__links{
    position: fixed;
    inset: 0;
    z-index: 1;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    flex: none;
    margin-left: 0;
    gap: 0;
    width: 100%;
    height: 100vh;
    height: 100dvh;
    box-sizing: border-box;
    overflow-y: auto;
    background: var(--bg);
    padding: calc(var(--nav-h, 64px) + 16px) var(--gutter) 32px;
    display: flex;
    visibility: hidden;
    transform: translateX(100%);
    transition: transform .4s var(--ease-out), visibility 0s linear .4s;
  }
  .nav__links.is-open{
    visibility: visible;
    transform: translateX(0);
    transition: transform .4s var(--ease-out), visibility 0s;
  }
  html.nav-open{ overflow: hidden; }
  /* Compact rows, each separated by a 1px divider (Connect Us pill excluded) */
  .nav__links a{ width: 100%; padding: 7px 0; }
  .nav__links > a:not(.nav__connect),
  .nav__item--has-menu > a{ border-bottom: 1px solid var(--border); }
  .nav__item{ width: 100%; }
  .nav__menu{ position: static; display: flex; min-width: 0; padding: 0 0 0 16px; }
  .nav__links .nav__menu a,
  .nav__links .nav__menu a:hover{ background: none; color: var(--text-muted); border: 0 !important; border-bottom: 1px solid var(--border) !important; border-radius: 0 !important; padding: 6px 0; white-space: normal; }
  /* Connect Us now lives inside the dropdown (moved there so it isn't
     stranded with no mobile equivalent) - keep it looking like the pill
     button it is instead of inheriting the plain link row's flush-left
     full-bleed padding above. */
  .nav__links .nav__connect{
    width: auto;
    justify-content: center;
    padding: 11px 18px;
    margin-top: 12px;
  }
}

/* ===== Hero: founder reveal ===== */
.hero-split{
  position: sticky;
  top: var(--nav-h);
  z-index: 1;
  height: calc(100vh - var(--nav-h));
  background: var(--bg);
}

.hero-split__stage{
  position: relative;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.sr-only{
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ===== Founder reveal: fades in automatically on load ===== */
.hero-split__reveal{
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(24px, 5vw, 72px);
  padding-inline: var(--gutter);
  opacity: 0;
  pointer-events: none;
  transition: opacity 1s var(--ease-out);
}
.hero-split__reveal.is-visible{
  opacity: 1;
  pointer-events: auto;
}

.hero-split__reveal-text{
  transform: translateY(26px);
  transition: transform 1s var(--ease-out);
  margin-top: clamp(-45px, -3vw, -20px);
}
.hero-split__reveal-image{
  transform: translateX(34px) scale(0.95);
  transition: transform 1s var(--ease-out);
}
.hero-split__reveal.is-visible .hero-split__reveal-text,
.hero-split__reveal.is-visible .hero-split__reveal-image{
  transform: none;
}

.hero-split__reveal-text{
  max-width: 68ch;
  flex: 1 1 420px;
}

.hero-split__reveal-eyebrow{
  margin: 0 0 8px;
  font-size: 1.4rem;
  color: var(--text-muted);
  font-weight: 500;
}

.hero-split__reveal-title{
  margin: 0 0 22px;
  font-size: clamp(3.1rem, 7vw, 5.8rem);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--accent);
}

.hero-split__reveal-desc{
  margin: 0;
  color: var(--text-muted);
  font-size: .875rem;
  line-height: 1.65;
}

.hero-split__cta-row{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin-top: clamp(36px, 4.5vw, 48px);
}
.hero-split__cta--outline{
  padding: 10px 17px;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--text);
}

.hero-split__reveal-image{
  flex: none;
  width: min(42%, 540px);
  height: min(78vh, 700px);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg);
  border: 1.5px solid rgba(255, 255, 255, 0.18);
}

.hero-split__reveal-image img{
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 68% 15%;
  display: block;
}

@media (max-width: 900px){
  .hero-split__reveal{
    flex-direction: column-reverse;
    justify-content: center;
    text-align: center;
    padding-block: 32px;
  }
  .hero-split__reveal-text{ max-width: 100%; }
  .hero-split__reveal-image{
    width: min(70%, 320px);
    height: auto;
    aspect-ratio: 3 / 4;
  }
}

@media (prefers-reduced-motion: reduce){
  .hero-split{ height: auto; }
  .hero-split__stage{ height: auto; padding-block: 15vh; }
  .hero-split__reveal{
    position: relative;
    opacity: 1;
    pointer-events: auto;
    flex-direction: column-reverse;
    text-align: center;
    padding-block: 40px;
  }
  .hero-split__reveal-text, .hero-split__reveal-image{ transform: none; }
  .hero-split__reveal-image{ width: min(70%, 320px); height: auto; aspect-ratio: 3 / 4; }
}

/* Mobile hero order (<= 900px only; desktop layout is untouched):
   "Hi, I'm the Founder of" + "Vriyox"  ->  description  ->  photo  ->  buttons.
   The text wrapper is flattened (display: contents) so its children can be
   interleaved with the photo; the two buttons share the row equally. */
@media (max-width: 900px){
  /* Hero grows with its content (tall photo) instead of clipping it inside a
     fixed 100vh box; it scrolls normally rather than sticking. */
  .hero-split{ position: relative; top: auto; height: auto; min-height: calc(100vh - var(--nav-h)); }
  .hero-split__stage{ height: auto; min-height: calc(100vh - var(--nav-h)); }
  .hero-split__reveal{
    position: relative;
    inset: auto;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 0;
    text-align: center;
    padding-block: 28px;
  }
  .hero-split__reveal-text{ display: contents; }
  .hero-split__reveal-eyebrow{ order: 1; width: 100%; text-align: left; margin: 0 0 4px; font-size: 1.15rem; }
  .hero-split__reveal-title{ order: 2; width: 100%; text-align: left; margin: 0 0 clamp(12px, 2.4vh, 20px); font-size: clamp(2.7rem, 12.5vw, 3.8rem); }
  /* Description reads like the footer blurb: full width, left-aligned. */
  .hero-split__reveal-desc{ order: 3; width: 100%; text-align: left; margin: 0 0 clamp(14px, 2.6vh, 22px); font-size: .875rem; line-height: 1.55; }
  /* Photo fills the full content column; height stays capped so the buttons still fit. */
  .hero-split__reveal-image{
    order: 4;
    width: 100%;
    max-width: none;
    height: min(60vh, 560px);
    aspect-ratio: auto;
  }
  .hero-split__cta-row{
    order: 5;
    width: 100%;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 12px;
    margin-top: clamp(16px, 3vh, 26px);
  }
  .hero-split__cta-row .nav__connect{ justify-content: center; text-align: center; width: 100%; }
  .hero-split__cta-row .nav__connect:last-child:nth-child(odd){ grid-column: 1 / -1; }
  /* Children replace the flattened wrapper for the fade-up entrance. */
  .hero-split__reveal-eyebrow,
  .hero-split__reveal-title,
  .hero-split__reveal-desc,
  .hero-split__cta-row{
    transform: translateY(26px);
    transition: transform 1s var(--ease-out);
  }
  .hero-split__reveal.is-visible .hero-split__reveal-eyebrow,
  .hero-split__reveal.is-visible .hero-split__reveal-title,
  .hero-split__reveal.is-visible .hero-split__reveal-desc,
  .hero-split__reveal.is-visible .hero-split__cta-row{ transform: none; }
  .hero-split__reveal-image{ transform: translateY(26px) scale(.95); }
  .hero-split__reveal.is-visible .hero-split__reveal-image{ transform: none; }
}
/* Phones: text, photo and buttons all share one 16px side margin - the same
   as the Skills card (the section gutter is ~43px, which left them narrow). */
@media (max-width: 600px){
  .hero-split__reveal{ padding-inline: 16px; }
}
/* Short phones: shrink the photo a little more so all three buttons still fit. */
@media (max-width: 900px) and (max-height: 700px){
  .hero-split__reveal-image{ height: min(46vh, 340px); }
  .hero-split__reveal-desc{ margin-bottom: 12px; }
  .hero-split__reveal-title{ margin-bottom: 10px; }
  .hero-split__cta-row{ margin-top: 14px; gap: 10px; }
}

/* ==========================================================================
   Sticky reveal footer - slides up from behind the page and pins at the
   bottom of the viewport until its own height scrolls past.
   ========================================================================== */
.sticky-footer{
  position: relative;
  z-index: 3;
  height: var(--footer-h);
  width: 100%;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
  /* Opaque backing: at fractional zoom/DPR the fixed layer and this box round
     to different pixels, leaving a hairline where the sticky hero behind the
     page showed through. This covers that seam. */
  background: var(--bg);
}

.sticky-footer__fixed{
  position: fixed;
  left: 0;
  bottom: 0;
  height: var(--footer-h);
  width: 100%;
  background: var(--bg);
}

.sticky-footer__sticky{
  position: sticky;
  top: calc(100vh - var(--footer-h));
  height: var(--footer-h);
  overflow: hidden;
  background: var(--bg);
}

.sticky-footer__content{
  position: relative;
  isolation: isolate;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: clamp(36px, 5vw, 64px); /* same as the top padding: line-to-content above == content-to-line below */
  padding: clamp(36px, 5vw, 64px) var(--gutter) 16px;
  background: var(--bg);
}

.sticky-footer__top{
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(32px, 5vw, 64px);
}

.sticky-footer__brand{
  flex: 1 1 280px;
  max-width: 380px;
}

.sticky-footer__mark{
  display: inline-block;
  margin-bottom: 18px;
}

.sticky-footer__desc{
  margin: 0;
  color: var(--text-muted);
  font-size: .875rem;
  line-height: 1.6;
}

.sticky-footer__group{
  flex: 1 1 160px;
}
.sticky-footer__group h3{
  margin: 0 0 8px;
  font-size: .8rem;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text);
}
.sticky-footer__group ul{
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.sticky-footer__group a,
.sticky-footer__group span{
  color: var(--text-muted);
  font-size: .875rem;
  text-decoration: none;
  transition: color .25s;
}
.sticky-footer__group a:hover{ color: var(--text); }

.sticky-footer__bottom{
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
  margin-inline: calc(-1 * var(--gutter));
  border-top: 1px solid var(--border);
  padding-top: 18px;
  padding-bottom: 0;
  padding-inline: var(--gutter);
  color: var(--text-muted);
  font-size: .875rem;
  text-align: center;
}
.sticky-footer__bottom p{ margin: 0; }

@media (max-width: 640px){
  /* Compact mobile footer: brand on top, link groups in two columns. */
  .sticky-footer__content{ gap: 44px; padding-top: 44px; padding-bottom: 16px; }
  .sticky-footer__top{
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 28px 20px;
  }
  .sticky-footer__brand{ grid-column: 1 / -1; max-width: 100%; margin-bottom: 4px; }
  .sticky-footer__mark{ margin-bottom: 8px; }
  .sticky-footer__desc{ font-size: .875rem; line-height: 1.45; }
  .sticky-footer__group h3{ margin-bottom: 10px; font-weight: 900; }
  .sticky-footer__group ul{ gap: 2px; }
  .sticky-footer__group a,
  .sticky-footer__group span{ font-size: .875rem; }
  .sticky-footer__bottom{ padding-top: 12px; }
}

@media (prefers-reduced-motion: reduce){
  .sticky-footer{ height: auto; clip-path: none; }
  .sticky-footer__fixed{ position: relative; height: auto; }
  .sticky-footer__sticky{ position: relative; top: 0; height: auto; overflow: visible; }
}

/* ==========================================================================
   Circular carousel - "What I do": vanilla-JS/CSS port of a supplied
   React/framer-motion "circular-carousel" component (see
   includes/circular-carousel.php and js/circular-carousel.js). Cards sit on
   an elliptical arc computed in JS and are moved with a single CSS
   transition instead of framer-motion's spring physics.
   ========================================================================== */
.carousel{
  position: relative;
  z-index: 2;
  padding-block: clamp(56px, 8vw, 100px);
  background: var(--bg);
}

.perspective-slider__lead{ text-align: center; }
.carousel__desc,
.perspective-slider__lead{
  max-width: clamp(46ch, 70vw, 88ch);
  margin: 14px auto 0;
  color: var(--text-muted);
  font-size: .875rem;
  line-height: 1.6;
}
/* My Work intro: same width and side padding as the Experience intro (only the
   shared section gutter), with balanced wrapping. */
.perspective-slider__lead{ text-wrap: balance; }

/* Scroll-driven mode (class added by js/circular-carousel.js, never under
   reduced motion): the section is stretched to a few screens tall and its
   content pins under the nav, so scrolling steps through card 1..last and
   then the page moves on. Height is set inline by JS from the card count. */
.carousel.is-scroll-driven{ padding-block: 0; }

.carousel.is-scroll-driven .carousel__pin{
  position: -webkit-sticky;
  position: sticky;
  top: var(--nav-h);
  display: flex;
  min-height: calc(100vh - var(--nav-h));
  flex-direction: column;
  justify-content: center;
  padding-block: 24px;
}

/* ==========================================================================
   Depth system - shared building blocks for the spatial scroll experience
   that runs from the Work section through Skills. Depth comes from
   grayscale light/shadow only (no color), per the monochrome identity.
   ========================================================================== */
.section-eyebrow{
  margin: 0 0 10px;
  font-size: .8rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-align: center;
}
.section-heading{
  margin: 0;
  line-height: var(--lh-heading);
  text-wrap: balance;
  font-size: var(--fs-h2);
  font-weight: 800;
  letter-spacing: -0.01em;
  text-align: center;
}

/* Reveal: fade + a short upward move, one-shot. No blur/scale - it should
   read as the content settling in, not an effect. */
[data-depth-reveal]{
  opacity: 0;
  transform: translate3d(0, 30px, 0);
  transition: opacity .85s var(--ease-out), transform .85s var(--ease-out);
  will-change: transform, opacity;
}
[data-depth-reveal].is-in{
  opacity: 1;
  transform: translate3d(0, 0, 0);
  will-change: auto;
}
@media (max-width: 640px){
  [data-depth-reveal]{ transform: translate3d(0, 18px, 0); transition-duration: .7s; }
}
@media (prefers-reduced-motion: reduce){
  [data-depth-reveal]{ opacity: 1; transform: none; filter: none; transition: none; }
}

/* ==========================================================================
   Work - project cards as floating surfaces with scroll parallax and a
   restrained pointer tilt on desktop.
   ========================================================================== */
.work{
  position: relative;
  z-index: 2;
  background: var(--bg);
  padding-inline: var(--gutter);
  perspective: 1600px;
}
.skills__pin{
  padding-block: var(--section-y);
}

.work__head{ text-align: center; margin-bottom: clamp(40px, 6vw, 64px); }

/* ==========================================================================
   Perspective slider - vanilla-JS port of a supplied React/GSAP
   "infinite-perspective-slider" component. Replaces the old Experience
   timeline: same $experience data (see includes/perspective-slider-data.php),
   shown as a drag/scroll-driven row of tilting cards instead of a vertical
   rail. See js/perspective-slider.js for the interaction/physics and why
   wheel/drag capture is scoped to the stage instead of the whole window.
   ========================================================================== */
.perspective-slider{
  position: relative;
  z-index: 2;
  background: var(--bg);
  overflow: hidden;
}
.perspective-slider__pin{ padding-block: var(--section-y); }
.perspective-slider__head{ padding-inline: var(--gutter); }
.perspective-slider__stage{
  --pslider-gap: 24px;
  --pslider-img-h: clamp(180px, 32vh, 340px);
  position: relative;
  margin-top: clamp(24px, 4vh, 48px);
  margin-inline: var(--gutter);
  perspective: 2200px;
  cursor: grab;
  /* Default / fallback: a plain native horizontal scroller (touch swipe,
     drag on desktop). The scroll-scrub mode below replaces this when the
     whole section fits one screen. */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
}
.perspective-slider__stage::-webkit-scrollbar{ display: none; }
.perspective-slider__stage.is-dragging{ cursor: grabbing; scroll-snap-type: none; }
.perspective-slider__strip{
  display: flex;
  gap: var(--pslider-gap);
  width: max-content;
}
.perspective-slider__card{
  position: relative;
  flex: 0 0 auto;
  width: clamp(220px, 26vw, 320px);
  display: flex;
  flex-direction: column;
  gap: 10px;
  scroll-snap-align: start;
  will-change: transform;
  transform-origin: center center;
  user-select: none;
}
.perspective-slider__number{
  margin: 0;
  font-size: .875rem;
  font-weight: 700;
  letter-spacing: .06em;
  color: var(--text-muted);
}
.perspective-slider__image-wrap{
  position: relative;
  width: 100%;
  height: var(--pslider-img-h);
  overflow: hidden;
  border-radius: var(--radius-md);
  background: var(--surface);
  transition: transform .35s var(--ease-out);
}
.perspective-slider__card:hover .perspective-slider__image-wrap{ transform: translateY(-6px); }
.perspective-slider__image{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}
.perspective-slider__title{
  margin: 0;
  font-size: 1.05rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .02em;
  color: #fff;
}
.perspective-slider__desc{
  margin: 0;
  font-size: .875rem;
  color: var(--text-muted);
}

/* Prev / next arrows + counter: only in swipe (native) mode; the scroll-scrub
   desktop mode is driven by page scroll and hides them. */
.perspective-slider__nav{
  display: none;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-top: clamp(20px, 3vh, 32px);
}
.pslider--native .perspective-slider__nav{ display: flex; }
.perspective-slider__arrow{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.perspective-slider__arrow svg{ width: 20px; height: 20px; }
.perspective-slider__arrow:hover:not(:disabled){ background: #fff; color: #000; }
.perspective-slider__arrow:active:not(:disabled){ transform: scale(.94); }
.perspective-slider__arrow:disabled{ opacity: .3; cursor: default; }
.perspective-slider__arrow:focus-visible{ outline: 2px solid var(--text-muted); outline-offset: 2px; }
.perspective-slider__count{
  min-width: 64px;
  text-align: center;
  font-size: .875rem;
  font-weight: 700;
  letter-spacing: .08em;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

/* Scroll-scrub mode (js/perspective-slider.js): the section becomes a tall
   runway, the pin sticks under the nav, and vertical scrolling slides the
   cards sideways - the first three are visible, the rest move in as you
   keep scrolling. overflow: clip (not hidden) so sticky still works. */
.pslider--scrub{ overflow: clip; }
.pslider--scrub .perspective-slider__pin{
  position: -webkit-sticky;
  position: sticky;
  top: var(--nav-h);
  min-height: calc(100vh - var(--nav-h));
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: clamp(20px, 3vh, 40px);
}
.pslider--scrub .perspective-slider__stage{
  overflow: hidden;
  height: calc(var(--pslider-img-h) + 150px);
  scroll-snap-type: none;
}
.pslider--scrub .perspective-slider__strip{
  position: absolute;
  inset: 0;
  width: auto;
  display: block;
  transform-style: preserve-3d;
}
.pslider--scrub .perspective-slider__image{
  will-change: transform; /* JS drifts it a few px against the slide (js/perspective-slider.js) */
}
.pslider--scrub .perspective-slider__card{
  position: absolute;
  left: 0;
  top: 0;
}
/* Heading stays perfectly still while pinned - skip its reveal slide. */
.pslider--scrub .perspective-slider__head[data-depth-reveal]{
  opacity: 1;
  transform: none;
  filter: none;
  transition: none;
}

@media (max-width: 1024px){
  .perspective-slider__stage{ --pslider-gap: 20px; }
}
@media (max-width: 640px){
  .perspective-slider__stage{
    --pslider-gap: 16px;
    --pslider-img-h: clamp(200px, 48vw, 260px);
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 0;
  }
  .perspective-slider__card{ width: calc(100vw - 2 * var(--gutter)); } /* one card per view - next one stays off-stage */
  .perspective-slider__title{ font-size: 1rem; }
  .perspective-slider__desc{ font-size: .875rem; }
}

@media (prefers-reduced-motion: reduce){
  .perspective-slider__card{ transition: none; }
}

/* ==========================================================================
   Skills - spatial grid; groups lift toward the viewer on hover.
   ========================================================================== */
.skills{
  position: relative;
  z-index: 2;
  background: var(--bg);
  padding-block: clamp(64px, 9vw, 120px);
  padding-inline: var(--gutter);
  perspective: 1600px;
}

/* ==========================================================================
   Content pages - About / Portfolio / Contact / Privacy Policy. Plain,
   readable, crawlable prose pages that share the site's nav/footer chrome
   but skip the homepage's heavy canvas/3D treatment.
   ========================================================================== */
.page{
  /* Full-width with gutter padding only - same box model as every home
     page section (.work, .perspective-slider, ...). No
     max-width/centering here, and .page__lede/.page__section p no longer
     cap their own width either - text now runs the same full width as
     the rest of the page. */
  position: relative;
  z-index: 2;
  padding-inline: var(--gutter);
  padding-block: clamp(40px, 6vw, 72px) clamp(64px, 9vw, 120px);
  /* Inner pages have no CTA card, so the divider above the footer is this
     section's bottom line (same 1px line as the home page's .cta). */
  border-bottom: 1px solid var(--border);
}

/* About page only - slightly narrower left/right padding than the shared
   --gutter every other page (home/portfolio/contact) uses. */
/* About shares the site gutter like every other page, with equal left and right
   padding: the text runs the full content width (no narrower cap, which left a
   big empty strip only on the right). */
.page--about{ padding-inline: calc(var(--gutter) + clamp(12px, 6vw, 96px)); }

.page__head{ margin-bottom: clamp(36px, 5vw, 56px); }
.page__title{
  margin: 0 0 14px;
  font-size: var(--fs-h1);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.page__lede{
  margin: 0;
  color: var(--text-muted);
  font-size: .8125rem;
  line-height: 1.65;
}

.page__section{ margin-block: clamp(36px, 5vw, 56px); }
.page__section h2{
  margin: 0 0 12px;
  font-size: clamp(1rem, 1.8vw, 1.25rem);
  font-weight: 700;
  letter-spacing: -0.01em;
}
.page__section p{
  margin: 0 0 16px;
  color: var(--text-muted);
  font-size: .8125rem;
  line-height: 1.7;
}
.page__section p:last-child{ margin-bottom: 0; }
.page__section a{ color: var(--text); text-decoration-color: var(--border); text-underline-offset: 3px; }
.page__section a:hover{ text-decoration-color: var(--text); }

.page__list{
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.page__list li{
  color: var(--text-muted);
  font-size: .8125rem;
  line-height: 1.6;
  padding-left: 20px;
  position: relative;
}
.page__list li::before{
  content: "";
  position: absolute;
  left: 0;
  top: 10px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--border);
}

/* Contact page - left/right split (structure ported from
   vriyox.com/contact-us/, colors/typography kept as the site's own).
   Left: plain info column (no card - reads like the rest of the page's
   text). Right: a real self-hosted form in an elevated card (see
   contact.php for the server-side handling - no third-party form service). */
.contact-split{
  display: grid;
  grid-template-columns: minmax(220px, .85fr) minmax(320px, 1.15fr);
  gap: clamp(40px, 6vw, 88px);
  align-items: start;
  margin-bottom: clamp(48px, 7vw, 80px);
}
@media (max-width: 760px){
  .contact-split{ grid-template-columns: 1fr; }
}

.contact-split__info{ display: flex; flex-direction: column; gap: clamp(28px, 4vw, 40px); }
.contact-split__info .page__cta-row{ margin-top: 0; }

.contact-info{ display: grid; gap: 22px; }
.contact-info__item{ display: flex; flex-direction: column; gap: 5px; }
.contact-info__label{
  font-size: .72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--text-muted);
}
.contact-info__value{ font-size: .8125rem; color: var(--text); text-decoration: none; }
a.contact-info__value:hover{ text-decoration: underline; text-decoration-color: var(--border); }

.contact-follow{ display: grid; gap: 14px; }
.contact-follow__heading{
  margin: 0;
  font-size: .72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--text-muted);
}
.contact-follow__icons{ display: flex; flex-wrap: wrap; gap: 12px; }
.contact-follow__icons a{
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--border);
  transition: transform .25s, border-color .25s;
}
.contact-follow__icons a:hover{ transform: translateY(-2px); border-color: var(--border-strong); }
.contact-follow__icons svg{ width: 20px; height: 20px; display: block; }

.contact-form{
  position: relative;
  display: grid;
  gap: 18px;
  padding: clamp(28px, 4vw, 44px);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  background: var(--surface);
  box-shadow: 0 30px 70px -30px rgba(0, 0, 0, .6);
}
.contact-form__honeypot{
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}
.contact-form__row{ display: flex; flex-direction: column; gap: 8px; }
.contact-form__row label{
  font-size: .72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-muted);
}

.contact-form__row input,
.contact-form__row select,
.contact-form__row textarea{
  width: 100%;
  padding: 12px 14px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: .92rem;
  resize: vertical;
  outline: none;
  transition: border-color .25s, box-shadow .25s;
}
.contact-form__row input::placeholder,
.contact-form__row textarea::placeholder{ color: var(--text-muted); }
.contact-form__row input:focus-visible,
.contact-form__row select:focus-visible,
.contact-form__row textarea:focus-visible{
  border-color: rgba(255, 255, 255, .4);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .08);
}
.contact-form__row select{ appearance: auto; }
.contact-form button[type="submit"]{
  justify-self: start;
  margin-top: 4px;
  border: none;
  font: inherit;
  cursor: pointer;
}

.contact-form-status{
  margin-bottom: 16px;
  padding: 12px 16px;
  border-radius: var(--radius-md);
  font-size: .9rem;
  border: 1px solid var(--border);
}
.contact-form-status--ok{ background: rgba(255,255,255,.06); color: var(--text); }
.contact-form-status--error{ background: rgba(255,80,80,.08); color: var(--danger); border-color: rgba(255,80,80,.3); }

.page__cta-row{
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: clamp(28px, 4vw, 40px);
}
.page__cta{
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 13px 24px;
  border-radius: var(--radius-full);
  font-weight: 600;
  font-size: .8125rem;
  text-decoration: none;
  transition: transform .25s, border-color .25s;
}
.page__cta--primary{ background: #fff; color: #0a0a10; }
.page__cta--primary:hover{ transform: translateY(-2px); }
.page__cta--ghost{ border: 1px solid var(--border); color: var(--text); }
.page__cta--ghost:hover{ border-color: var(--border-strong); transform: translateY(-2px); }
.page__cta:focus-visible{ outline: 2px solid var(--text-muted); outline-offset: 2px; }
/* `.page__section a` (link colour for prose) is more specific than the button
   variants above, so inside a section the filled button got near-white text on
   its white background ("Get in touch" on /business/ looked blank). Re-assert
   the button colours with matching specificity. */
.page__section a.page__cta{ text-decoration: none; }
.page__section a.page__cta--primary,
.page__section a.page__cta--primary:hover{ color: #0a0a10; }
.page__section a.page__cta--ghost,
.page__section a.page__cta--ghost:hover{ color: var(--text); }

/* Portfolio detail cards - richer than the homepage teaser, text-first */
.page__case{
  border-top: 1px solid var(--border);
  padding-block: clamp(28px, 4vw, 40px);
}
.page__case:first-of-type{ border-top: none; padding-top: 0; }
.page__case-meta{
  margin: 0 0 8px;
  font-size: .78rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.page__case-title{
  margin: 0 0 10px;
  font-size: clamp(.95rem, 1.6vw, 1.15rem);
  font-weight: 700;
}
.page__case p{
  margin: 0;
  color: var(--text-muted);
  font-size: .8125rem;
  line-height: 1.7;
}
.page__case dl{
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 12px;
  margin: 16px 0 0;
  font-size: .8rem;
}
.page__case dt{ color: var(--text-muted); }
.page__case dd{ margin: 0; color: var(--text); }

@media (max-width: 640px){
  .page__case dl{ grid-template-columns: 1fr; gap: 2px 0; }
  .page__case dt{ margin-top: 8px; }
}

/* Mobile: tighter vertical rhythm on the content pages (About, Portfolio and
   the rest of .page). Desktop spacing is untouched. */
@media (max-width: 640px){
  .page{ padding-block: 24px 40px; }
  .page__head{ margin-bottom: 24px; }
  .page__title{ margin-bottom: 10px; }
  .page__section{ margin-block: 24px; }
  .page__section h2{ margin-bottom: 8px; }
  .page__section p{ margin-bottom: 12px; }
  .page__list{ gap: 8px; }
  .page__case{ padding-block: 20px; }
  .page__case-meta{ margin-bottom: 6px; }
  .page__case-title{ margin-bottom: 8px; }
  .page__case dl{ margin-top: 12px; }
}

/* ==========================================================================
   404
   ========================================================================== */
.not-found{
  min-height: 60vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: clamp(64px, 12vw, 140px) var(--gutter);
  border-bottom: 1px solid var(--border);
}
.not-found__code{
  margin: 0;
  font-size: clamp(3.5rem, 10vw, 7rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--text);
}
.not-found__title{
  margin: 12px 0 10px;
  font-size: clamp(1.3rem, 2.6vw, 1.8rem);
  font-weight: 700;
}
.not-found__desc{
  margin: 0 0 32px;
  max-width: 46ch;
  color: var(--text-muted);
  font-size: .8125rem;
  line-height: 1.6;
}

/* Hand-off motion for the pinned sections (js/section-motion.js drives these
   custom properties; without JS/scrub they stay at their neutral defaults). */

.pslider--scrub .perspective-slider__pin,
.carousel.is-scroll-driven .carousel__pin{
  transform: translate3d(0, var(--sec-y, 0px), 0) scale(var(--sec-scale, 1));
  transform-origin: 50% 40%;
  opacity: var(--sec-o, 1);
  will-change: transform, opacity;
}

/* Anchor glide past the carousel (js/anchor-scroll.js): fade it out instead
   of letting its cards spin while the page scrolls through its runway. */
html[data-gliding] .carousel.is-scroll-driven .carousel__pin{
  opacity: 0;
  transition: opacity .3s ease;
}

/* Anchor target for the header's "What I do" link: land just under the sticky nav. */
#carousel{ scroll-margin-top: var(--nav-h); }

/* ==========================================================================
   FAQ - vanilla port of the supplied React/shadcn "faqs-01" accordion
   (see includes/faq.php, js/faq.js). Items are outlined cards rather than
   ruled rows so no extra divider lines appear on the home page.
   ========================================================================== */
.faq{
  position: relative;
  z-index: 2;
  background: var(--bg);
  padding-block: clamp(32px, 4.5vw, 56px) var(--section-y); /* heading sits higher than other sections */
  padding-inline: var(--gutter);
}
.faq__inner{ max-width: var(--container-narrow); margin-inline: auto; }
.faq__head{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
}
.faq__lead{
  /* Full width of the FAQ column (768px) with no extra side padding, so the
     description runs wide like the My Work intro used to. */
  max-width: 100%;
  margin: 0;
  color: var(--text-muted);
  font-size: 1rem;
  line-height: 1.6;
  text-wrap: balance;
}
.faq__lead a{ color: var(--text); font-weight: 500; text-underline-offset: 4px; text-decoration: none; }
.faq__lead a:hover{ text-decoration: underline; }

.faq__list{
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: clamp(32px, 5vw, 48px);
}
.faq__item{
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  transition: border-color .4s, background .4s, box-shadow .5s var(--ease-out);
}
.faq__item:hover,
.faq__item.is-open{ border-color: var(--border-strong); }
/* Open state: same surface as every other card (--surface), the project's
   hover border (var(--border-strong)) and the same soft shadow the Skills cards use. */
.faq__item.is-open{ box-shadow: 0 10px 28px -14px rgba(0,0,0,.45); }
.faq__q{ margin: 0; }
.faq__trigger{
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 22px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: .875rem;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  border-radius: 8px;
}
.faq__trigger:focus-visible{ outline: 2px solid var(--text-muted); outline-offset: -2px; }
.faq__trigger svg{
  flex: none;
  width: 18px;
  height: 18px;
  color: var(--text-muted);
  transition: transform .35s var(--ease-out), color .3s;
}
.faq__item.is-open .faq__trigger svg{ transform: rotate(180deg); color: var(--text); }
.faq__panel{
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .6s var(--ease-out);
}
.faq__item.is-open .faq__panel{ grid-template-rows: 1fr; }
.faq__panel-inner{
  min-height: 0;
  overflow: hidden;
  visibility: hidden;
  opacity: 0;
  transition: opacity .3s ease, visibility 0s linear .6s;
}
.faq__item.is-open .faq__panel-inner{
  visibility: visible;
  opacity: 1;
  transition: opacity .5s ease .1s, visibility 0s;
}
.faq__panel-inner p{
  margin: 0;
  padding: 0 22px 14px;
  color: var(--text-muted);
  font-size: .875rem;
  line-height: 1.65;
  /* The answer glides down into place as it opens and lifts back as it closes. */
  transform: translate3d(0, -8px, 0);
  transition: transform .45s var(--ease-out);
}
.faq__item.is-open .faq__panel-inner p{
  transform: translate3d(0, 0, 0);
  transition: transform .65s var(--ease-out) .08s;
}

.faq__cta{
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 40px;
  padding: 20px;
  border: 1px dashed var(--border);
  border-radius: 8px;
  background: var(--surface);
}
.faq__cta-text{ display: flex; align-items: center; gap: 12px; }

.faq__cta-title{ margin: 0; color: var(--text); font-size: .875rem; font-weight: 500; }
.faq__cta-sub{ margin: 2px 0 0; color: var(--text-muted); font-size: .875rem; }
.faq__cta-btn{
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 18px;
  border-radius: var(--radius-full);
  background: #fff;
  color: #000;
  font-size: .875rem;
  font-weight: 600;
  text-decoration: none;
  transition: transform .2s;
}
.faq__cta-btn svg{ width: 16px; height: 16px; }
/* Hover/active come from the shared button rules ("Buttons: one size..."): same as every other button. */
@media (max-width: 640px){
  /* Full container width, everything centred: icon, text, then a full-width button */
  .faq__cta{ flex-direction: column; align-items: stretch; justify-content: center; width: 100%; box-sizing: border-box; text-align: center; }
  .faq__cta-text{ flex-direction: column; align-items: center; justify-content: center; text-align: center; }
  .faq__cta-btn{ justify-content: center; width: 100%; box-sizing: border-box; }
}
@media (prefers-reduced-motion: reduce){
  .faq__panel, .faq__panel-inner, .faq__panel-inner p, .faq__trigger svg, .faq__item{ transition: none; }
  .faq__panel-inner p{ transform: none; }
}

/* ==========================================================================
   Call-to-action - vanilla port of the supplied React/shadcn
   "call-to-action" component (see includes/cta.php). Sizes follow the
   original Tailwind classes: py-16 md:py-32, max-w-5xl, text-4xl lg:text-5xl,
   mt-12 button row with gap-4, lg buttons (h-11 px-8 rounded-md).
   ========================================================================== */
.cta{
  position: relative;
  z-index: 2;
  background: var(--bg);
  padding-block: var(--section-y) clamp(4px, .5vw, 8px); /* wordmark carries the space above the footer line */
  padding-inline: var(--gutter);
  /* The divider above the footer belongs to this section (its bottom line),
     not the footer, which draws no top line of its own - so the two can
     never stack into a double-thick line. A real border, like the header's. */
  border-bottom: 1px solid var(--border);
  /* Opaque 1px cover under the border: at fractional zoom/DPR the CTA and the
     fixed footer round to different pixels, and the sticky hero behind the
     page glowed through that seam as a bright patch on the divider. */
  box-shadow: 0 1px 0 0 var(--bg);
}
/* Heading, copy and both buttons sit together in one card (same border /
   surface language as the FAQ items above it). */
.cta__inner{
  max-width: var(--container);
  margin-inline: auto;
  padding: clamp(36px, 6vw, 72px) clamp(20px, 5vw, 64px);
  border-radius: var(--radius-md);
  background: var(--surface);
  text-align: center;
}
/* Oversized "Vriyox" wordmark under the card: each letter rises out of its
   own clipped mask when js/main.js adds .is-in on scroll. */
.cta__wordmark{
  display: flex;
  justify-content: center;
  max-width: var(--container);
  /* Centred between the card above and the divider line below: the glyphs sit
     lower in their box than the box's own padding suggests, so half of the old
     top gap (M) moves to the bottom. .059em/2px = the box's top/bottom
     asymmetry measured from a 402px phone screenshot. Total height unchanged. */
  --wm-gap: clamp(40px, 6vw, 88px);
  margin: calc(var(--wm-gap) * .5 + .059em + 2px) auto 0;
  padding-bottom: calc(var(--wm-gap) * .5 - .059em - 2px);
  font-size: clamp(3.5rem, 17vw, 13.5rem);
  font-weight: var(--fw-black);
  line-height: 1.1;
  letter-spacing: -0.04em;
  color: var(--text);
  user-select: none;
}
/* 3D scroll: js/main.js writes --wm-rx/--wm-ry/--wm-z per letter from scroll
   position, so the letters fold up out of the depth as the section scrolls in
   (and fold back when scrolling up). Falls back to flat with no JS. */
.cta__wordmark{ perspective: 900px; perspective-origin: 50% 40%; }
.cta__wordmark-mask{
  display: block; overflow: hidden; padding-block: .04em .16em;
  transform-origin: 50% 100%;
  transform: rotateX(var(--wm-rx, 0deg)) rotateY(var(--wm-ry, 0deg)) translateZ(var(--wm-z, 0px));
  will-change: transform;
}
.cta__wordmark-char{
  display: block;
  transform: translateY(110%);
  transition: transform 1.1s var(--ease-out);
}
.cta__wordmark.is-in .cta__wordmark-char{ transform: none; }
@media (prefers-reduced-motion: reduce){
  .cta__wordmark-char{ transform: none; transition: none; }
  .cta__wordmark-mask{ transform: none; will-change: auto; }
}
.cta__title{
  margin: 0;
  letter-spacing: var(--ls-heading);
  font-size: var(--fs-h2);
  font-weight: var(--fw-black);
  line-height: var(--lh-tight);
  text-wrap: balance;
}
.cta__desc{
  margin: 16px 0 0;
  color: var(--text-muted);
  font-size: .875rem;
  line-height: 1.6;
}
.cta__actions{
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 16px;
  margin-top: 48px;
}
.cta__btn{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  padding-inline: 32px;
  border-radius: var(--radius-md);
  font-size: .875rem;
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color .2s, color .2s, transform .2s;
}
.cta__btn:focus-visible{ outline: 2px solid var(--text-muted); outline-offset: 2px; }
.cta__btn--primary{ background: #fff; color: #000; }
.cta__btn--primary:hover{ background: rgba(255,255,255,.9); transform: translateY(-1px); }

@media (max-width: 900px){

  

  /* A perspective ancestor makes sticky children shimmer while scrolling on
     touch browsers; the 3D hover depth it provides is desktop-only anyway. */
  .skills:not(.skills--scrub){ perspective: none; }

}

/* ==========================================================================
   DESIGN SYSTEM LAYER
   Site-wide consistency rules built on the tokens in :root. Loaded last on
   purpose: it normalises buttons, form controls, focus, tap targets and
   motion across every page without touching page-specific layout above.
   ========================================================================== */

/* ---- Base --------------------------------------------------------------- */
html{ -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
img, video{ max-width: 100%; }
button, input, select, textarea{ font-family: inherit; }
h1, h2, h3, h4{ text-wrap: balance; }
p, li{ text-wrap: pretty; }
:focus-visible{ outline: 2px solid var(--text); outline-offset: 2px; }

/* ---- Buttons: one size, one radius, one type style --------------------- */
.nav__connect,
.page__cta,
.cta__btn,
.faq__cta-btn,
.contact-form button[type="submit"]{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 43px;
  padding: 0 var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: #fff;
  color: var(--on-light);
  font-family: inherit;
  font-size: .8125rem;
  font-weight: var(--fw-semibold);
  line-height: 1;
  letter-spacing: 0;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.nav__connect:hover,
.page__cta:hover,
.cta__btn:hover,
.faq__cta-btn:hover,
.contact-form button[type="submit"]:hover{
  background: rgba(255, 255, 255, .88);
  transform: translateY(-1px);
}
.nav__connect:active,
.page__cta:active,
.cta__btn:active,
.faq__cta-btn:active,
.contact-form button[type="submit"]:active{ transform: translateY(0); }

/* Outline variant */
.hero-split__cta--outline,
.page__cta--ghost{
  background: transparent;
  color: var(--text);
  border-color: var(--text-muted);
}
.hero-split__cta--outline:hover,
.page__cta--ghost:hover{
  background: rgba(255, 255, 255, .06);
  border-color: var(--text);
}

/* Accent variant: the "Learn More" button in the home CTA card (includes/cta.php).
   Doubled class so it outranks the shared white button above. */
.cta__btn.cta__btn--accent{ background: #9d2433; color: #fff; }
.cta__btn.cta__btn--accent:hover{ background: #b12a3c; }

/* Header button sits in a 44px row - keep the bar height unchanged */
.nav .nav__connect{ min-height: 43px; }

/* ---- Forms: shared control height, 16px text (no iOS zoom), no overflow -- */
.contact-split > *,
.contact-form,
.contact-form__row{ min-width: 0; }
.contact-form__row input,
.contact-form__row select,
.contact-form__row textarea{
  max-width: 100%;
  min-width: 0;
  font-size: var(--fs-body);
}
.contact-form__row input,
.contact-form__row select{ min-height: 44px; }

.faq__trigger{ min-height: 44px; }

/* ---- Tap targets: >= 44px on phones / touch ------------------------------ */
@media (max-width: 900px), (pointer: coarse){
  .brand{ min-height: 44px; }
  .sticky-footer__group ul{ gap: 0; }
  .sticky-footer__group li a{
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  .contact-follow__icons a{ width: 44px; height: 44px; }
  a.contact-info__value{
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

}
/* Footer link lists are deliberately tighter than the 44px rule above
   (phones only) - rows were ~44px apart, which made the footer very tall. */
@media (max-width: 640px){
  .sticky-footer__group li a{ min-height: 24px; }
}

/* ---- Reduced motion: keep layout and state changes, drop the movement ---- */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---- Page headers: eyebrow follows the title's alignment ----------------- */
.page__head .section-eyebrow{ text-align: left; }

@media (max-width: 900px){
  /* six 44px social icons fit one row on a 390px phone */
  .contact-follow__icons{ gap: var(--space-2); }
}

/* ---- Section hand-off: no blank screen between pinned sections ------------
   Each pinned section (carousel, Skills, My Work) ends its fade-out exactly
   when its pin releases (js/section-motion.js). The next section is pulled up
   by one section-padding (the gap above its heading), so its heading reaches
   the bottom of the viewport at that same moment: the outgoing content is
   fully gone (next stays hidden until then), and the incoming heading is
   already arriving - never a mix, never an empty screen. */
.carousel.is-scroll-driven,
.pslider--scrub{ margin-bottom: calc(-1 * var(--section-y)); }

/* "Learn More" buttons (header + hero): brand red on every device. */
.nav .nav__connect,
.nav__links a.nav__connect,
.nav__links a.nav__connect:hover,
.hero-split__cta--outline,
.hero-split__cta--outline:hover{
  background: #9d2433;
  color: #fff;
  border-color: #9d2433;
}
.nav .nav__connect:hover,
.hero-split__cta--outline:hover{ background: #b02a3c; border-color: #b02a3c; }

/* ==========================================================================
   Contact page - premium pass
   Icon rows in one panel, full-size colour social icons, consistent type
   (caption / body tokens) and a refined form card. Loaded after the design
   system layer on purpose so it wins over the shared button/control rules.
   ========================================================================== */
.contact-split{ gap: clamp(32px, 5vw, 72px); align-items: start; }

/* --- Info panel: one card, one row per channel --- */
.contact-info{
  display: grid;
  gap: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, #181822, var(--surface));
  overflow: hidden;
}
.contact-info__item{
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 18px clamp(16px, 2.4vw, 22px);
  color: var(--text);
  text-decoration: none;
  transition: background-color var(--dur-base) var(--ease-out);
}
.contact-info__item + .contact-info__item{ border-top: 1px solid var(--border); }
a.contact-info__item:hover{ background: rgba(255, 255, 255, .04); }
.contact-info__icon{
  flex: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  border: 1px solid var(--border-strong);
  background: rgba(255, 255, 255, .04);
  color: var(--text);
  transition: background-color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.contact-info__icon svg{ width: 22px; height: 22px; display: block; }
a.contact-info__item:hover .contact-info__icon{ background: var(--accent); border-color: var(--accent); transform: translateY(-1px); }
.contact-info__text{ display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.contact-info__label{
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  letter-spacing: .08em;
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--text-muted);
}
.contact-info__value{
  font-size: var(--fs-body);
  font-weight: 500;
  line-height: 1.45;
  color: var(--text);
  overflow-wrap: anywhere;
  text-decoration: none;
}

/* --- Social: full-size colour brand icons --- */
.contact-follow{ gap: 16px; }
.contact-follow__heading{
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  letter-spacing: .08em;
  line-height: 1.2;
}
.contact-follow__icons{ display: flex; flex-wrap: wrap; gap: 14px; }
.contact-follow__icons a{
  display: block;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .16), 0 8px 18px -8px rgba(0, 0, 0, .7);
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.contact-follow__icons a:hover{
  transform: translateY(-3px) scale(1.05);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .4), 0 14px 26px -10px rgba(0, 0, 0, .9);
}
.contact-follow__icons svg{ width: 100%; height: 100%; display: block; border-radius: 50%; }

/* --- Form card --- */
.contact-form{
  gap: 20px;
  padding: clamp(24px, 4vw, 44px);
  border-radius: var(--radius-xl);
  background: linear-gradient(180deg, #181822, var(--surface));
  box-shadow: 0 40px 80px -36px rgba(0, 0, 0, .8), inset 0 1px 0 rgba(255, 255, 255, .05);
}
.contact-form__head{ display: grid; gap: 6px; margin-bottom: 4px; }
.contact-form__title{
  margin: 0;
  font-size: var(--fs-h3);
  font-weight: var(--fw-bold);
  letter-spacing: -0.01em;
  line-height: 1.2;
  color: var(--text);
}
.contact-form__sub{ margin: 0; font-size: .8125rem; line-height: 1.5; color: var(--text-muted); }
.contact-form__row{ gap: 8px; }
.contact-form__row label{
  font-size: var(--fs-small);
  font-weight: var(--fw-semibold);
  letter-spacing: 0;
  text-transform: none;
  color: var(--text);
}

.contact-form__row input,
.contact-form__row select,
.contact-form__row textarea{
  padding: 13px 16px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-strong);
  background: rgba(0, 0, 0, .35);
  line-height: 1.4;
  transition: border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), background-color var(--dur-base) var(--ease-out);
}
.contact-form__row textarea{ min-height: 132px; }
.contact-form__row input:hover,
.contact-form__row select:hover,
.contact-form__row textarea:hover{ border-color: #4a4a5c; }
.contact-form__row input:focus,
.contact-form__row select:focus,
.contact-form__row textarea:focus,
.contact-form__row input:focus-visible,
.contact-form__row select:focus-visible,
.contact-form__row textarea:focus-visible{
  border-color: var(--accent);
  background: rgba(0, 0, 0, .5);
  box-shadow: 0 0 0 4px rgba(157, 36, 51, .22);
}
.contact-form__row select{
  appearance: none;
  -webkit-appearance: none;
  padding-right: 44px;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23a3a3b8' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
}
.contact-form__row select option{ background: var(--surface); color: var(--text); }

.contact-form button[type="submit"]{
  justify-self: stretch;
  width: 100%;
  min-height: 52px;
  margin-top: 6px;
  gap: 10px;
  border-radius: var(--radius-md);
  background: var(--accent);
  color: #fff;
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  box-shadow: 0 14px 30px -14px rgba(157, 36, 51, .9);
}
.contact-form button[type="submit"]:hover{ background: #b12a3c; transform: translateY(-1px); }
.contact-form button[type="submit"] span{ display: inline-block; transition: transform var(--dur-base) var(--ease-out); }
.contact-form button[type="submit"]:hover span{ transform: translateX(4px); }

.contact-form-status{ border-radius: var(--radius-md); font-size: var(--fs-small); line-height: 1.5; }

/* White form card: re-scope text tokens so labels/inputs stay readable. */
.contact-form{
  --text: #14141c;
  --text-muted: #5b5b6e;
  background: #fff;
  box-shadow: 0 40px 80px -36px rgba(0, 0, 0, .6);
}
.contact-form__row input,
.contact-form__row select,
.contact-form__row textarea{
  background: #fff;
  border-color: #d4d4de;
  color: #14141c;
}
.contact-form__row input:hover,
.contact-form__row select:hover,
.contact-form__row textarea:hover{ border-color: #a8a8b8; }
.contact-form__row input:focus,
.contact-form__row select:focus,
.contact-form__row textarea:focus,
.contact-form__row input:focus-visible,
.contact-form__row select:focus-visible,
.contact-form__row textarea:focus-visible{ background: #fff; }
.contact-form__row select option{ background: #fff; color: #14141c; }
.contact-form-status--ok{ background: rgba(20, 140, 60, .1); }

/* Contact page: centred intro (eyebrow + lede). */
.page--contact .page__head,
.page--contact .page__head .section-eyebrow,
.page--contact .page__lede{ text-align: center; }
.page--contact .page__lede{ max-width: 60ch; margin-inline: auto; padding-inline: 0; }
/* Intro band: same background as the form card, full-bleed (edge to edge, up to
   the nav) so its bottom divider runs the full page width. */
.page--contact .page__head{
  margin-inline: calc(-1 * var(--gutter));
  margin-top: calc(-1 * clamp(40px, 6vw, 72px));
  padding: clamp(20px, 3vw, 32px) var(--gutter) clamp(16px, 2.4vw, 24px);
  margin-bottom: clamp(24px, 3.5vw, 36px);
  background: linear-gradient(180deg, #181822, var(--surface));
  border-bottom: 1px solid var(--border);
}

.page--contact .page__title{ margin-bottom: 8px; }

/* Contact info column: no panel background/border - icon + text rows sit
   straight on the page. */
.contact-info{
  gap: 6px;
  border: 0;
  border-radius: 0;
  background: none;
  overflow: visible;
}
.contact-info__item{ padding: 10px 0; }
.contact-info__item + .contact-info__item{ border-top: 0; }
a.contact-info__item:hover{ background: none; }

/* Contact info icons: small plain icons (no box) in front of each row. */
.contact-info__item{ gap: 12px; align-items: flex-start; }
.contact-info__icon{
  width: 20px;
  height: 20px;
  margin-top: 1px;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--text-muted);
}
.contact-info__icon svg{ width: 20px; height: 20px; }
a.contact-info__item:hover .contact-info__icon{ background: none; border-color: transparent; transform: none; color: var(--text); }

/* Icon sits on the same line as its label ("✉ Email"); the value goes below. */
.contact-info__item{
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  column-gap: 8px;
  row-gap: 4px;
}
.contact-info__text{ display: contents; }
.contact-info__icon{ grid-column: 1; grid-row: 1; margin-top: 0; width: 18px; height: 18px; }
.contact-info__icon svg{ width: 18px; height: 18px; }
.contact-info__label{ grid-column: 2; grid-row: 1; }
.contact-info__value{ grid-column: 1 / -1; grid-row: 2; }

/* Dividers between the contact info rows (Email / WhatsApp / Availability / Location). */
.contact-info{ gap: 0; }
.contact-info__item{ padding: 16px 0; }
.contact-info__item + .contact-info__item{ border-top: 1px solid var(--border); }
.contact-info__item:first-child{ padding-top: 0; }
.contact-info__item:last-child{ border-bottom: 1px solid var(--border); }

/* Send a message: no card background or shadow (border kept). */
.contact-form{ background: #fff; box-shadow: none; }
.contact-form{ border-radius: var(--radius-md); } /* same 8px corners as the header button */

/* Send message: no shadow; same red as the header "Learn More" button. */
.contact-form button[type="submit"]{
  box-shadow: none;
  background: #9d2433;
  color: #fff;
  border-color: #9d2433;
}
.contact-form button[type="submit"]:hover{ background: #b02a3c; border-color: #b02a3c; }
.page--contact .page__title{ font-size: clamp(1.6rem, 3.4vw, 2.4rem); } /* smaller than the default page title */

/* Contact form: shorter input boxes. */
.contact-form__row input,
.contact-form__row select,
.contact-form__row textarea{ padding-block: 9px; }
.contact-form__row input,
.contact-form__row select{ min-height: 40px; }
.contact-form__row textarea{ min-height: 96px; }

/* Contact intro band: plain black background. */
.page--contact .page__head{ background: #000; }

/* Send Message: identical to the header "Learn More" button (size, colour,
   corners, hover). */
.contact-form button[type="submit"]{
  justify-self: start;
  width: auto;
  min-height: 43px;
  margin-top: 4px;
  padding: 0 var(--space-5);
  gap: var(--space-2);
  border: 1px solid #9d2433;
  border-radius: var(--radius-md);
  background: #9d2433;
  color: #fff;
  font-size: .8125rem;
  font-weight: var(--fw-semibold);
  line-height: 1;
  box-shadow: none;
}
.contact-form button[type="submit"]:hover{ background: #b02a3c; border-color: #b02a3c; transform: translateY(-1px); }
.contact-form button[type="submit"]:active{ transform: translateY(0); }

/* Contact form: trimmed from the left (stays flush right); 500px = a touch wider than the old 470px. */
@media (min-width: 761px){
  .contact-split__form{ width: min(100%, 500px); justify-self: end; }
}

/* Contact info values (email, WhatsApp, hours, address): same text style as the
   header nav links. */
.contact-info__value{
  font-size: .85rem;
  font-weight: 400;
  line-height: 1.5;
  color: var(--text-muted);
}
a.contact-info__item:hover .contact-info__value{ color: var(--text); }
.contact-info__label{ color: var(--text); } /* white titles */
.contact-info__icon{ color: var(--text); }

/* Contact Form: more compact overall height. */
.contact-form{ gap: 14px; padding: clamp(18px, 2.6vw, 28px); }
.contact-form__head{ gap: 4px; margin-bottom: 0; }
.contact-form__row textarea{ min-height: 80px; }
.contact-form button[type="submit"]{ margin-top: 0; }

/* Phones: info -> form -> "Follow us" (social icons move below the form). */
@media (max-width: 760px){
  .contact-split__info{ display: contents; }
  .contact-info{ order: 1; }
  .contact-split__form{ order: 2; }
  .contact-follow{ order: 3; }
}

/* Social icons: a bit smaller. */
.contact-follow__icons{ gap: 12px; }
.contact-follow__icons a{ width: 40px; height: 40px; }

/* Dropdown placeholder ("What can we help with?") - smaller, muted; the chosen
   option goes back to normal size. */
.contact-form__row select:required:invalid{ font-size: .85rem; color: var(--text-muted); }
.contact-form__row select option{ font-size: var(--fs-body); }

/* All contact form placeholders (Name, Email, Phone, dropdown, Message): one size, one colour. */
.contact-form__row input::placeholder,
.contact-form__row textarea::placeholder{
  font-size: .85rem;
  color: var(--text-muted);
  opacity: 1;
}
.contact-form__row select:required:invalid{ font-size: .85rem; color: var(--text-muted); }

/* Validation errors show inside the field (as the placeholder), in red. */
.contact-form__row .is-invalid{ border-color: var(--danger); }
.contact-form__row .is-invalid::placeholder{ color: var(--danger); opacity: 1; }
.contact-form__row select.is-invalid{ color: var(--danger); }

/* Focused fields: neutral grey border, no red glow. */
.contact-form__row input:focus,
.contact-form__row select:focus,
.contact-form__row textarea:focus,
.contact-form__row input:focus-visible,
.contact-form__row select:focus-visible,
.contact-form__row textarea:focus-visible,
.contact-form__row .is-invalid:focus{
  border-color: #a8a8b8;
  box-shadow: none;
  outline: none;
}

/* Error state colour. */
.contact-form__row .is-invalid,
.contact-form__row .is-invalid:focus{ border-color: #9d2433; }
.contact-form__row .is-invalid::placeholder{ color: #9d2433; opacity: 1; }
.contact-form__row select.is-invalid{ color: #9d2433; }

/* Send Message: full width of the form. */
.contact-form button[type="submit"]{ justify-self: stretch; width: 100%; }

/* Buttons use the same corner radius as the contact form card. */
.nav__connect,
.contact-form button[type="submit"]{ border-radius: var(--radius-md); }

/* Buttons everywhere: slightly shorter (44px -> 34px). */
.nav .nav__connect,
.nav__connect,
.page__cta,
.cta__btn,
.faq__cta-btn,
.contact-form button[type="submit"]{ min-height: 34px; }

/* ---- "What I do" card grid ------------------------------------------------ */
.services{
  position: relative;
  z-index: 2;
  padding-block: clamp(56px, 8vw, 100px);
  padding-inline: var(--gutter);
  background: var(--bg);
}
.services__head{ text-align: center; margin-bottom: clamp(32px, 5vw, 56px); }
.services__grid{
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 2.2vw, 28px);
  max-width: var(--container);
  margin-inline: auto;
}
.services__card{
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: clamp(22px, 2.6vw, 32px);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  transition: border-color .3s var(--ease-out), transform .3s var(--ease-out);
}
.services__card:hover{ border-color: var(--border-strong); box-shadow: 0 30px 60px rgba(0, 0, 0, .5); }
/* 3D: pointer tilt (js/depth-scroll.js writes --tilt-x/--tilt-y) with the text
   floating on separate depth layers. Compound selector so it outranks
   [data-depth-reveal].is-in's "transform: none" reset. */
.services__card.tilt-card{
  transform-style: preserve-3d;
  transform: perspective(1000px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
  transition: transform .15s ease-out, border-color .3s var(--ease-out), box-shadow .3s var(--ease-out), opacity .85s var(--ease-out);
}
.services__card.tilt-card:hover{ transform: perspective(1000px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg)) translateZ(14px); }
.services__card .services__num{ transform: translateZ(18px); }
.services__card .services__title{ transform: translateZ(40px); }
.services__card .services__desc{ transform: translateZ(24px); }
@media (prefers-reduced-motion: reduce){
  .services__card .services__num,
  .services__card .services__title,
  .services__card .services__desc{ transform: none; }
}
.services__num{ font-size: var(--fs-small); font-weight: var(--fw-semibold); color: #9d2433; letter-spacing: .08em; }
.services__title{ margin: 0; font-size: clamp(1rem, 2.4vw, 1.15rem); font-weight: var(--fw-bold); line-height: 1.2; color: var(--text); }
.services__desc{ margin: 0; font-size: .875rem; line-height: 1.6; color: var(--text-muted); }
@media (max-width: 960px){ .services__grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px){ .services__grid{ grid-template-columns: 1fr; } }

/* Mobile hero photo: the photo itself sits a little smaller inside the same
   frame (frame width/height unchanged) - whole photo shown, anchored to the bottom. */
@media (max-width: 900px){
  .hero-split__reveal-image img{ object-fit: contain; object-position: center bottom; }
}

/* Mobile hero photo frame: a little shorter (60vh/560px -> 54vh/500px). */
@media (max-width: 900px){
  .hero-split__reveal-image{ height: min(54vh, 500px); }
}
@media (max-width: 900px) and (max-height: 700px){
  .hero-split__reveal-image{ height: min(42vh, 300px); }
}

/* ---- One button height everywhere (43px) ---------------------------------- */
.nav__connect,
.hero-split__cta--outline,
.page__cta,
.faq__cta-btn,
.cta__btn,
.contact-form button[type="submit"]{
  box-sizing: border-box;
  min-height: 43px;
  height: 43px;
  padding-block: 0;
  align-items: center;
  justify-content: center;
}

/* Contact form: every field and the submit button 1px taller. */
.contact-form__row input{ padding-block: 13.5px; }
.contact-form__row .cselect__btn{ min-height: 45px; }
.contact-form__row textarea{ min-height: 81px; }
.contact-form button[type="submit"]{ min-height: 44px; height: 44px; }

/* ---- Contact form: custom dropdown (js/contact-select.js) ------------------ */
.cselect{ position: relative; }
.contact-form__row .cselect > select{
  position: absolute; left: 0; top: 0; width: 1px; height: 1px; min-height: 0;
  padding: 0; border: 0; opacity: 0; pointer-events: none;
}
.cselect__btn{
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; min-height: 44px; padding: 0 16px;
  border: 1px solid #d4d4de; border-radius: var(--radius-md);
  background: #fff; color: #14141c;
  font: inherit; font-size: var(--fs-body); text-align: left; cursor: pointer;
  transition: border-color var(--dur-base) var(--ease-out);
}
.cselect__btn:hover{ border-color: #a8a8b8; }
.cselect__btn:focus-visible,
.cselect.is-open .cselect__btn{ border-color: #a8a8b8; outline: none; }
.cselect__btn.is-placeholder{ font-size: .8125rem; color: #5b5b6e; }
.cselect__btn.is-invalid{ border-color: #9d2433; color: #9d2433; }
.cselect__btn::after{
  content: ""; flex: none; width: 16px; height: 16px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235b5b6e' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform .2s var(--ease-out);
}
.cselect.is-open .cselect__btn::after{ transform: rotate(180deg); }
.cselect__list{
  position: absolute; z-index: 20; left: 0; right: 0; top: calc(100% + 4px);
  margin: 0; padding: 4px; list-style: none;
  background: #fff; border: 1px solid #e2e2ea; border-radius: 12px;
  box-shadow: 0 18px 40px -12px rgba(0, 0, 0, .35);
  max-height: 280px; overflow-y: auto;
  animation: cselectIn .16s var(--ease-out);
}
.cselect__list[hidden]{ display: none; }
@keyframes cselectIn{ from{ opacity: 0; transform: translateY(-6px); } }
.cselect__option{
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 34px; padding: 0 12px; border-radius: 6px;
  color: #14141c; font-size: .8125rem; cursor: pointer;
}
.cselect__option.is-active{ background: #f3f3f7; }
.cselect__option.is-selected{ font-weight: 700; color: #9d2433; }
.cselect__option.is-selected::after{
  content: ""; flex: none; width: 16px; height: 16px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%239d2433' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
}
@media (prefers-reduced-motion: reduce){ .cselect__list{ animation: none; } }

/* ---- My Skills (redesign): editorial accordion ------------------------------
   Other versions: includes/skills-classic.php (original), includes/skills-cards.php. */
.skx{
  position: relative;
  z-index: 2;
  background: var(--bg);
  padding-block: clamp(32px, 4.5vw, 56px) clamp(64px, 9vw, 120px); /* heading sits higher */
  padding-inline: var(--gutter);
}
.skx__head{ text-align: center; margin-bottom: clamp(32px, 5vw, 56px); }
.skx__desc{
  max-width: clamp(46ch, 70vw, 88ch);
  margin: 14px auto 0;
  color: var(--text-muted);
  font-size: .875rem;
  line-height: 1.6;
}
.skx__list{ max-width: var(--container); margin-inline: auto; border-bottom: 1px solid var(--border-strong); }
.skx__item{ border-top: 1px solid var(--border-strong); }
/* Scroll 3D entrance: each row swings up from a tilted-back plane, staggered
   by --n. One-shot via [data-depth-reveal] (.is-in). Specificity beats the
   generic reveal so the 3D start pose isn't flattened. */
.skx__list{ perspective: 1200px; perspective-origin: 50% 30%; }
.skx__item[data-depth-reveal]{
  transform-origin: 50% 0;
  transform: rotateX(-60deg) translateZ(-140px) translateY(24px);
  transition: opacity 1s var(--ease-out), transform 1.1s var(--ease-out);
  transition-delay: calc(var(--n, 0) * 110ms);
}
.skx__item[data-depth-reveal].is-in{ transform: none; }
@media (max-width: 640px){
  .skx__item[data-depth-reveal]{ transform: rotateX(-40deg) translateZ(-80px) translateY(16px); transition-delay: calc(var(--n, 0) * 70ms); }
  .skx__item[data-depth-reveal].is-in{ transform: none; }
}
@media (prefers-reduced-motion: reduce){
  .skx__item[data-depth-reveal]{ opacity: 1; transform: none; transition: none; }
}
.skx__summary{
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) 40px;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: clamp(14px, 2vw, 20px) 4px;
  border: 0;
  background: none;
  font: inherit;
  text-align: left;
  color: inherit;
  cursor: pointer;
  transition: padding-left .4s var(--ease-out);
}
.skx__summary:focus-visible{ outline: 2px solid #9d2433; outline-offset: 2px; }
.skx__num{ font-size: var(--fs-small); font-weight: var(--fw-semibold); letter-spacing: .08em; color: #9d2433; }
.skx__name{
  font-size: clamp(1.1rem, 2vw, 1.35rem);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -.01em;
  color: var(--text-muted);
  transition: color .2s ease;
}
.skx__icon{
  position: relative; width: 36px; height: 36px;
  border: 1px solid var(--border-strong); border-radius: 50%;
  transition: background-color .3s ease, border-color .3s ease, transform .5s cubic-bezier(.22, 1, .36, 1);
}
.skx__item.is-open .skx__icon{ transform: rotate(180deg); }
.skx__icon::before, .skx__icon::after{
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 14px; height: 2px; margin: -1px 0 0 -7px; border-radius: 2px;
  background: var(--text);
  transition: transform .45s var(--ease-out);
}
.skx__icon::after{ transform: rotate(90deg); }
.skx__summary:hover .skx__name,
.skx__item.is-open .skx__name{ color: var(--text); }
.skx__item.is-open .skx__summary{ padding-left: 12px; }
.skx__summary:hover .skx__icon{ border-color: var(--text-muted); }
.skx__item.is-open .skx__icon{ background: var(--text); border-color: var(--text); }
.skx__item.is-open .skx__icon::before, .skx__item.is-open .skx__icon::after{ background: var(--bg); }
.skx__item.is-open .skx__icon::after{ transform: rotate(0deg); }
/* Expand / collapse motion: animate the row height (0fr -> 1fr) plus a fade. */
.skx__panel{
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows .6s cubic-bezier(.22, 1, .36, 1), opacity .45s ease .1s;
}
.skx__item.is-open .skx__panel{ grid-template-rows: 1fr; opacity: 1; transition-delay: 0s, 0s; }
.skx__tags{
  display: flex; flex-wrap: wrap; gap: 10px;
  min-height: 0; overflow: hidden;
  margin: 0; padding: 0 4px 0 68px; list-style: none;
  transition: padding-bottom .6s cubic-bezier(.22, 1, .36, 1);
}
.skx__item.is-open .skx__tags{ padding-bottom: clamp(18px, 2.4vw, 26px); }
.skx__tag{
  padding: 6px 14px;
  border: 1px solid var(--surface);
  border-radius: var(--radius-full);
  font-size: .875rem; line-height: 1.3;
  background: var(--surface);  /* same card colour + text as the CTA card (.cta__inner) */
  color: var(--text);
  /* Closed: tags leave quickly, last one first (reverse stagger). */
  opacity: 0; transform: translateY(14px) scale(.96);
  transition: opacity .25s ease calc((14 - var(--i, 0)) * 12ms), transform .3s ease calc((14 - var(--i, 0)) * 12ms), border-color .25s, background-color .25s;
}
/* Open: tags rise in one by one after the row starts growing. */
.skx__item.is-open .skx__tag{
  opacity: 1; transform: none;
  transition: opacity .5s ease calc(.15s + var(--i, 0) * 45ms), transform .6s cubic-bezier(.22, 1, .36, 1) calc(.15s + var(--i, 0) * 45ms), border-color .25s, background-color .25s;
}
.skx__tag:hover{ border-color: var(--border-strong); }

@media (max-width: 640px){
  .skx__summary{ grid-template-columns: 34px minmax(0, 1fr) 36px; }
  .skx__tags{ padding-left: 4px; }
}
@media (prefers-reduced-motion: reduce){
  .skx__panel, .skx__summary, .skx__icon, .skx__icon::before, .skx__icon::after, .skx__tag,
  .skx__item.is-open .skx__panel, .skx__item.is-open .skx__tag{ transition: none; }
  .skx__item.is-open .skx__icon{ transform: none; }
  .skx__tag{ opacity: 1; transform: none; }
}

/* ---- Home CTA card: white theme (includes/cta.php) ----------------------
   Re-scopes the text tokens so title/copy read on white, and flips the
   primary button to dark. The accent (red) button is left as is. */
.cta__inner{
  --text: #14141c;
  --text-muted: #5b5b6e;
  background: #fff;
  color: var(--text);
}
.cta__btn.cta__btn--primary:not(.cta__btn--accent){ background: #14141c; color: #fff; }
.cta__btn.cta__btn--primary:not(.cta__btn--accent):hover{ background: #2a2a38; }
.cta__btn:focus-visible{ outline-color: #14141c; }

/* ---- About Me (includes/about-me.php): content + sticky photo ----------- */
.aboutme{
  position: relative;
  z-index: 2;
  padding-block: clamp(56px, 8vw, 100px);
  padding-inline: var(--gutter);
  background: var(--bg);
}
.aboutme__inner{
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: clamp(28px, 5vw, 72px);
  align-items: start;
  max-width: var(--container);
  margin-inline: auto;
}
.aboutme__heading{
  margin: 0 0 clamp(24px, 3vw, 36px);
  font-size: var(--fs-h2);
  font-weight: 800;
  letter-spacing: -.01em;
  line-height: var(--lh-heading);
}
.aboutme__block{ padding-block: clamp(18px, 2.4vw, 26px); border-top: 1px solid var(--border-strong); }
.aboutme__label{ margin: 0 0 12px; font-size: var(--fs-small); font-weight: var(--fw-semibold); letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted); }
.aboutme__text{ margin: 0; font-size: 1.05rem; line-height: 1.7; color: var(--text); }
.aboutme__timeline{ margin: 0; padding: 0; list-style: none; display: grid; gap: 18px; }
.aboutme__timeline li{ display: grid; gap: 4px; padding-left: 18px; border-left: 1px solid var(--border-strong); }
.aboutme__period{ font-size: .78rem; font-weight: var(--fw-semibold); letter-spacing: .06em; color: #9d2433; }
.aboutme__role{ font-size: 1.05rem; font-weight: var(--fw-bold); color: var(--text); }
.aboutme__role span{ font-weight: 500; color: var(--text-muted); }
.aboutme__timeline p{ margin: 0; font-size: .95rem; line-height: 1.6; color: var(--text-muted); }
.aboutme__chips{ margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 10px; }
.aboutme__chips li{ padding: 6px 14px; border-radius: var(--radius-full); background: var(--surface); font-size: .8125rem; line-height: 1.3; color: var(--text); }
.aboutme__media{
  position: sticky;
  top: calc(var(--nav-h, 64px) + 24px);
  margin: 0;
}
.aboutme__media img{
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 430 / 580;
  object-fit: cover;
  object-position: center top;
  border-radius: var(--radius-md);
  background: var(--surface);
}
@media (max-width: 800px){
  .aboutme__inner{ grid-template-columns: 1fr; }
  .aboutme__media{ position: relative; top: auto; order: -1; max-width: 420px; margin-inline: auto; }
  .aboutme__content{ order: 1; }
}

/* Experience: each role is a click-to-expand row (About Me). */
.aboutme__timeline{ gap: 0; }
.aboutme__timeline .aboutme__exp{ display: block; gap: 0; padding-left: 18px; border-left: 1px solid var(--border-strong); transition: border-color .25s var(--ease-out); }
.aboutme__exp.is-open{ border-left-color: var(--text); }
.aboutme__exp-btn{
  display: grid; grid-template-columns: minmax(0, 1fr) 28px; align-items: center; gap: 12px;
  width: 100%; padding: 12px 0; border: 0; background: none;
  font: inherit; text-align: left; color: inherit; cursor: pointer;
}
.aboutme__exp-btn:focus-visible{ outline: 2px solid var(--text-muted); outline-offset: 2px; }
.aboutme__exp-text{ display: grid; gap: 4px; }
.aboutme__exp-icon{
  position: relative; width: 28px; height: 28px;
  border: 1px solid var(--border-strong); border-radius: 50%;
  transition: background-color .2s ease, border-color .2s ease;
}
.aboutme__exp-icon::before, .aboutme__exp-icon::after{
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 10px; height: 2px; margin: -1px 0 0 -5px; border-radius: 2px;
  background: var(--text);
  transition: transform .25s var(--ease-out);
}
.aboutme__exp-icon::after{ transform: rotate(90deg); }
.aboutme__exp-btn:hover .aboutme__exp-icon{ border-color: var(--text-muted); }
.aboutme__exp.is-open .aboutme__exp-icon{ background: var(--text); border-color: var(--text); }
.aboutme__exp.is-open .aboutme__exp-icon::before,
.aboutme__exp.is-open .aboutme__exp-icon::after{ background: var(--bg); }
.aboutme__exp.is-open .aboutme__exp-icon::after{ transform: rotate(0deg); }
.aboutme__exp-panel{
  display: grid; grid-template-rows: 0fr; opacity: 0;
  transition: grid-template-rows .28s var(--ease-out), opacity .2s ease;
}
.aboutme__exp.is-open .aboutme__exp-panel{ grid-template-rows: 1fr; opacity: 1; }
.aboutme__exp-panel p{ margin: 0; padding-right: 40px; font-size: .95rem; line-height: 1.6; color: var(--text-muted); }
@media (prefers-reduced-motion: reduce){
  .aboutme__exp, .aboutme__exp-icon, .aboutme__exp-icon::before, .aboutme__exp-icon::after, .aboutme__exp-panel{ transition: none; }
}

/* While one role is open, the other companies are hidden; collapsing brings them back. */
.aboutme__timeline.has-open .aboutme__exp:not(.is-open){ display: none; }
.aboutme__timeline .aboutme__exp{ animation: aboutExpIn .3s var(--ease-out) backwards; }
@keyframes aboutExpIn{ from{ opacity: 0; transform: translateY(6px); } }
@media (prefers-reduced-motion: reduce){ .aboutme__timeline .aboutme__exp{ animation: none; } }

/* Experience rows with dates: small type so the whole row fits (About Me). */
.aboutme__total{ margin-left: 8px; font-weight: 500; letter-spacing: 0; text-transform: none; font-size: .75rem; opacity: .8; }
.aboutme__timeline .aboutme__role{ font-size: .95rem; }
.aboutme__timeline .aboutme__period{ font-size: .72rem; }
.aboutme__exp-body{ min-height: 0; overflow: hidden; }
.aboutme__exp-body p{ padding-right: 40px; }
.aboutme__exp.is-open .aboutme__exp-body{ padding-bottom: 12px; }
.aboutme__exp-dates{ display: flex; flex-wrap: wrap; gap: 8px 22px; margin: 0; padding-right: 40px; }
.aboutme__exp-body p + .aboutme__exp-dates{ margin-top: 10px; }
.aboutme__exp-dates div{ display: grid; gap: 2px; }
.aboutme__exp-dates dt{ font-size: .68rem; font-weight: var(--fw-semibold); letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted); }
.aboutme__exp-dates dd{ margin: 0; font-size: .82rem; line-height: 1.4; color: var(--text); }

/* Key Responsibility Areas list inside an expanded role (About Me). */
.aboutme__exp-panel .aboutme__kra-title{ margin: 10px 0 6px; padding-right: 0; font-size: .68rem; font-weight: var(--fw-semibold); letter-spacing: .06em; text-transform: uppercase; color: var(--text-muted); }
.aboutme__kra{ margin: 0 0 10px; padding: 0 40px 0 18px; display: grid; gap: 6px; font-size: .82rem; line-height: 1.5; color: var(--text); }
.aboutme__kra li::marker{ color: #9d2433; }

/* About Me photo: a bit smaller, aligned to the right edge of the column. */
.aboutme__media{ width: min(100%, 340px); justify-self: end; }
@media (max-width: 800px){ .aboutme__media{ width: min(100%, 300px); justify-self: center; } }

/* About Me: give the text column the width the photo no longer needs. */
.aboutme__inner{ grid-template-columns: minmax(0, 1fr) 340px; gap: clamp(28px, 4vw, 56px); }
@media (max-width: 800px){ .aboutme__inner{ grid-template-columns: 1fr; } }
.aboutme__exp-body p, .aboutme__exp-dates, .aboutme__kra{ padding-right: 12px; }
.aboutme__kra{ padding-left: 18px; }

/* ---- About Me > Experience: premium rows ---------------------------------
   Hairline dividers between rows, between the row header and its details,
   and between dates and KRA. The open row lifts onto a surface card. */
.aboutme__timeline .aboutme__exp{
  padding: 0 14px;
  border-left: 0;
  border-top: 1px solid var(--border-strong);
  border-radius: 0;
  transition: background-color .25s var(--ease-out), border-radius .25s var(--ease-out);
}
.aboutme__timeline .aboutme__exp:last-child{ border-bottom: 1px solid var(--border-strong); }
.aboutme__timeline .aboutme__exp.is-open{ background: var(--surface); border-radius: var(--radius-md); border-color: transparent; }
.aboutme__timeline .aboutme__exp.is-open + .aboutme__exp{ border-top-color: transparent; }
.aboutme__timeline .aboutme__exp:not(.is-open):hover{ background: rgba(255, 255, 255, .03); }
.aboutme__timeline .aboutme__exp-btn{ padding: 14px 0; }
.aboutme__timeline .aboutme__exp-text{ gap: 5px; }

/* Details: children own their dividers, so the collapsed panel (height 0, clipped) shows none. */
.aboutme__timeline .aboutme__exp-body{ padding: 0; }
.aboutme__timeline .aboutme__exp.is-open .aboutme__exp-body{ padding-bottom: 14px; }
.aboutme__timeline .aboutme__exp-body > :first-child{ border-top: 1px solid var(--border-strong); padding-top: 14px; }
.aboutme__timeline .aboutme__exp-body > p{ padding-right: 0; }

.aboutme__timeline .aboutme__exp-dates{
  display: grid; grid-template-columns: repeat(3, minmax(0, auto)); justify-content: start;
  gap: 0; margin: 0; padding: 14px 0 14px; border-bottom: 1px solid var(--border-strong);
}
.aboutme__timeline .aboutme__exp-body > .aboutme__exp-dates:first-child{ padding-top: 14px; }
.aboutme__timeline .aboutme__exp-dates div{ padding: 0 22px; border-left: 1px solid var(--border-strong); }
.aboutme__timeline .aboutme__exp-dates div:first-child{ padding-left: 0; border-left: 0; }
.aboutme__timeline .aboutme__exp-body p + .aboutme__exp-dates{ margin-top: 14px; border-top: 1px solid var(--border-strong); }

.aboutme__timeline .aboutme__kra-title{ margin: 14px 0 10px; }
.aboutme__timeline .aboutme__kra{ counter-reset: kra; list-style: none; margin: 0; padding: 0; gap: 8px; }
.aboutme__timeline .aboutme__kra li{
  counter-increment: kra;
  display: grid; grid-template-columns: 26px minmax(0, 1fr); align-items: baseline;
}
.aboutme__timeline .aboutme__kra li::before{
  content: counter(kra, decimal-leading-zero);
  font-size: .68rem; font-weight: var(--fw-semibold); letter-spacing: .06em; color: #9d2433;
}
@media (max-width: 520px){
  .aboutme__timeline .aboutme__exp-dates{ grid-template-columns: 1fr; gap: 10px; }
  .aboutme__timeline .aboutme__exp-dates div,
  .aboutme__timeline .aboutme__exp-dates div:first-child{ padding: 0; border-left: 0; }
}
/* KRA items are <li> inside .aboutme__timeline - drop the timeline-row border/padding they inherited. */
.aboutme__timeline .aboutme__kra li{ padding-left: 0; border-left: 0; gap: 0; }
.aboutme__timeline .aboutme__kra{ padding-right: 0; }

/* No line above the first role or below the last one. */
.aboutme__timeline .aboutme__exp:first-child{ border-top: 0; }
.aboutme__timeline .aboutme__exp:last-child{ border-bottom: 0; }

/* Focus Areas: smaller chips so the whole set sits neatly inside the column. */
.aboutme__chips{ gap: 8px; }
.aboutme__chips li{ padding: 5px 11px; font-size: .75rem; white-space: nowrap; }

/* About Me: wider text column - photo 340px -> 300px, tighter gap. */
.aboutme__inner{ grid-template-columns: minmax(0, 1fr) 380px; gap: clamp(24px, 3vw, 40px); }
.aboutme__media{ width: min(100%, 380px); }
@media (max-width: 800px){ .aboutme__inner{ grid-template-columns: 1fr; } }

/* Mobile order: "About Me" heading, then photo, then the rest of the content.
   .aboutme__content is flattened (display: contents) so its heading and blocks
   can be ordered around the photo. Desktop layout is untouched. */
@media (max-width: 800px){
  .aboutme__inner{ gap: 0; }
  .aboutme__content{ display: contents; }
  .aboutme__content > .aboutme__heading{ order: 1; }
  .aboutme__media{ order: 2; width: min(100%, 300px); justify-self: center; margin: 0 0 clamp(18px, 4vw, 26px); }
  .aboutme__content > .aboutme__block{ order: 3; }
}

/* Focus Areas: roomier chips, slightly larger text. */
.aboutme__chips{ gap: 10px; }
.aboutme__chips li{ padding: 8px 18px; font-size: .8125rem; }

/* ---- About Me: align type + colour with the rest of the site ---------------
   Same tokens as Services / Skills: h2 = --fs-h2 / 800, copy = muted body,
   card titles = bold --text, labels = --fs-small caps with --ls-label,
   captions = --fs-caption, accent = --accent, chips = --fs-small on --surface. */
.aboutme__heading{ font-size: var(--fs-h2); font-weight: var(--fw-black); line-height: var(--lh-heading); }
.aboutme__label{ font-size: var(--fs-small); font-weight: var(--fw-semibold); letter-spacing: var(--ls-label); color: var(--text-muted); }
.aboutme__total{ font-size: var(--fs-caption); font-weight: var(--fw-medium); }
.aboutme__text{ font-size: var(--fs-body); line-height: var(--lh-body); color: var(--text-muted); }
.aboutme__timeline .aboutme__period{ font-size: var(--fs-caption); font-weight: var(--fw-semibold); letter-spacing: var(--ls-label); color: var(--accent); }
.aboutme__timeline .aboutme__role{ font-size: var(--fs-body); font-weight: var(--fw-bold); line-height: 1.2; color: var(--text); }
.aboutme__timeline .aboutme__role span{ font-weight: var(--fw-medium); color: var(--text-muted); }
.aboutme__exp-panel p{ font-size: var(--fs-small); line-height: var(--lh-body); color: var(--text-muted); }
.aboutme__timeline .aboutme__exp-dates dt,
.aboutme__timeline .aboutme__kra-title{ font-size: var(--fs-caption); font-weight: var(--fw-semibold); letter-spacing: var(--ls-label); color: var(--text-muted); }
.aboutme__timeline .aboutme__exp-dates dd{ font-size: var(--fs-small); color: var(--text); }
.aboutme__timeline .aboutme__kra{ font-size: var(--fs-small); line-height: 1.5; color: var(--text-muted); }
.aboutme__timeline .aboutme__kra li::before{ font-size: var(--fs-caption); color: var(--accent); }
.aboutme__chips li{ font-size: .8125rem; font-weight: var(--fw-regular); color: var(--text); background: var(--surface); }

/* About Me photo: shorter frame (was 430/580); crops from the bottom, face stays in view. */
.aboutme__media img{ aspect-ratio: 430 / 530; }
/* Phones: photo spans the same 16px-gutter width as the "What I do" cards. */
@media (max-width: 600px){
  .aboutme__media{ width: 100%; max-width: none; justify-self: stretch; }
}

/* Homepage About Me bio: 3 stacked paragraphs. */
.aboutme__bio{ display: grid; gap: 16px; }

/* "Overall: ..." next to the Experience label: same 14px size as the label, sentence case. */
.aboutme__label{ display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 12px; row-gap: 2px; }
.aboutme__total{ margin-left: 0; font-size: var(--fs-small); font-weight: var(--fw-medium); letter-spacing: 0; text-transform: none; opacity: 1; color: var(--text); }

/* Line above Focus Areas sits closer to the last role (Experience block = 2nd .aboutme__block). */
.aboutme__content .aboutme__block:nth-of-type(2){ padding-bottom: 6px; }

/* ===== About page as a CV (about.php) =====
   Two columns on desktop: Summary + Experience on the left, Skills + Links on
   the right. Stacks on tablets/phones. Uses the shared tokens only. */
.cv__role{ margin: 0 0 14px; font-size: var(--fs-h4); font-weight: var(--fw-semibold); color: var(--text); }
.cv__facts{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
  margin: 26px 0 22px;
}
.cv__facts > div{
  display: grid;
  gap: 4px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
}
.cv__fact-num{ font-size: .875rem; font-weight: var(--fw-bold); color: var(--text); line-height: 1.35; }
.cv__fact-label{ font-size: var(--fs-caption); color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em; }
.cv__grid{
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: clamp(28px, 5vw, 64px);
  align-items: start;
}
.cv__main, .cv__side{ min-width: 0; }
.cv__section:first-child{ margin-top: 0; }
.cv__job{ padding: 20px 0; border-top: 1px solid var(--border); }
.cv__job:first-of-type{ border-top: 0; padding-top: 4px; }
.cv__job-head{ display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 4px 16px; margin-bottom: 8px; }
.cv__job-role{ margin: 0; font-size: .95rem; font-weight: var(--fw-bold); color: var(--text); }
.cv__job-role span{ font-weight: 500; color: var(--text-muted); }
.cv__job-period{ margin: 0; display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: var(--fs-caption); font-weight: var(--fw-semibold); letter-spacing: .04em; color: #9d2433; }
.cv__job-period span{ color: var(--text-muted); font-weight: 500; }
.page__section p.cv__job-desc{ margin-bottom: 10px; }
.cv__skill-group{ margin-bottom: 20px; }
.cv__skill-group:last-child{ margin-bottom: 0; }
.cv__skill-group h3{ margin: 0 0 8px; font-size: var(--fs-caption); font-weight: var(--fw-semibold); letter-spacing: .08em; text-transform: uppercase; color: var(--text-muted); }
.cv__tags{ display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.cv__tags li{ padding: 4px 10px; border-radius: var(--radius-full); background: var(--surface); border: 1px solid var(--border); font-size: .75rem; line-height: 1.3; color: var(--text); }

@media (min-width: 901px){
  .cv__side{ position: sticky; top: calc(var(--nav-h, 64px) + 24px); }
}
@media (max-width: 900px){
  .cv__grid{ grid-template-columns: 1fr; }
}

/* ===== "Let's work together" block (includes/lets-work.php, About page) =====
   Vanilla port of the supplied React component (hover-only; no JS). */
.letswork{ margin-top: clamp(48px, 8vw, 96px); border-top: 1px solid var(--border); }
.letswork__inner{
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(28px, 5vw, 48px);
  min-height: clamp(420px, 62vh, 560px);
  padding-block: clamp(40px, 6vw, 72px);
  text-align: center;
}
.letswork__status{
  display: flex; align-items: center; gap: 12px;
  font-size: .75rem; font-weight: 500; letter-spacing: .22em; text-transform: uppercase; color: var(--text-muted);
  margin-bottom: calc(-1 * clamp(10px, 1.6vw, 16px));
  transition: opacity .5s, transform .5s;
}
.letswork__dot{ position: relative; display: inline-flex; width: 8px; height: 8px; }
.letswork__dot span{ position: absolute; inset: 0; border-radius: 50%; background: #10b981; }
.letswork__dot span:first-child{ background: #34d399; opacity: .75; animation: letsworkPing 1.6s cubic-bezier(0,0,.2,1) infinite; }
@keyframes letsworkPing{ 75%, 100%{ transform: scale(2.4); opacity: 0; } }

.letswork__trigger{
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 24px;
  color: var(--text); text-decoration: none;
}
.letswork__headline{
  /* Same type as every .section-heading on the site */
  margin: 0;
  font-size: var(--fs-h2);
  font-weight: 800;
  line-height: var(--lh-heading);
  letter-spacing: -0.01em;
  /* "Let's work" and "together" sit on one line (they wrap only on very narrow screens) */
  display: flex; flex-wrap: wrap; justify-content: center; column-gap: .28em;
  transition: opacity .7s var(--ease-out), transform .7s var(--ease-out);
}
.letswork__mask{ display: block; overflow: hidden; padding-bottom: .22em; margin-bottom: -.14em; }
.letswork__text{ display: block; transition: transform .7s var(--ease-out); }
.letswork__text--2{ transition-delay: .075s; }
.letswork__dim{ color: inherit; }
.letswork__trigger:hover .letswork__text,
.letswork__trigger:focus-visible .letswork__text{ transform: translateY(-8%); }

.letswork__foot{
  max-width: 44ch; margin: 8px 0 0;
  font-size: .8125rem; line-height: 1.7; color: var(--text-muted);
  transition: opacity .5s .1s, transform .5s .1s;
}

@media (prefers-reduced-motion: reduce){
  .letswork__dot span:first-child{ animation: none; }
}

/* About: tighten the space under the closing "Let's work together" text */
.page--cv .letswork__inner{ padding-bottom: clamp(8px, 1.5vw, 16px); min-height: 0; }
.page--cv{ padding-bottom: clamp(28px, 4vw, 48px); }

.letswork__cta{ transition: opacity .5s, transform .5s var(--ease-out); }
.contact-form{ scroll-margin-top: calc(var(--nav-h, 64px) + 16px); }

/* "Let's work together" as a card - same look as the home page CTA card (.cta__inner):
   white surface, 8px corners, dark text, dark primary button. */
.letswork{ border-top: 0; }
.page--cv .letswork__inner{
  --text: #14141c;
  --text-muted: #5b5b6e;
  --border: #e2e2ea;
  --border-strong: #d4d4de;
  max-width: var(--container);
  margin-inline: auto;
  padding: clamp(36px, 6vw, 72px) clamp(20px, 5vw, 64px);
  border-radius: var(--radius-md);
  background: #fff;
  color: var(--text);
}
.letswork .page__cta--primary.letswork__cta{ background: #14141c; color: #fff; }
.letswork .page__cta--primary.letswork__cta:hover{ background: #2a2a38; color: #fff; }
.letswork__trigger, .letswork__trigger:hover{ color: var(--text); }
