/* ===================================================================
   Mihai Chirila — Portfolio  (v3)
   Full-bleed illustration · glass chip-stats · scene transitions
   =================================================================== */

:root {
  /* Surface */
  --bg:           #FAF2EB;
  --bg-2:         #F4EADC;
  --bg-blur:      rgba(250, 242, 235, 0.78);
  --surface:      #FFFFFF;
  --surface-2:    #F8F1E4;

  /* Ink */
  --ink:          #1B2433;
  --ink-2:        #404A60;
  --ink-mute:     #6B7488;
  --ink-line:     #C5B89C;
  --ink-line-soft:#E2D9C4;

  /* Magenta primary — brand colour #C04AA1.
     WCAG audit (white text on these fills):
       --accent       #C04AA1 → 4.43:1   passes AA-Large + UI 3:1, fails AA-normal text (4.5:1)
       --accent-btn   #B0408F → 5.20:1   passes AA-normal — used for pill buttons (.btn--primary, .linkedin-link, .game-popup__cta)
       --accent-deep  #8C3375 → 7.10:1   passes AAA — used for body-text accents (proj__cta, cozy-sub-accent, driver strong)
     Order is brand → button → text, each darker than the last so the
     palette still feels like one colour but every text use clears AA. */
  --accent:       #C04AA1;
  --accent-btn:   #B0408F;
  --accent-deep:  #8C3375;
  --accent-2:     #D26AB5;
  --accent-soft:  rgba(192, 74, 161, 0.12);
  --accent-pale:  rgba(192, 74, 161, 0.07);
  --accent-glow:  rgba(192, 74, 161, 0.32);
  --on-accent:    #FFFFFF;

  /* Secondary chip palette */
  --blue:         #2E5BFF;
  --blue-deep:    #1E3FCC;
  --blue-soft:    rgba(46, 91, 255, 0.10);

  --green:        #2D9D6F;
  --green-deep:   #1F7A55;
  --green-soft:   rgba(45, 157, 111, 0.14);

  --violet:       #7C3AED;
  --violet-deep:  #6D2FCC;
  --violet-soft:  rgba(124, 58, 237, 0.10);

  --muted:        #6B7488;

  /* Hairlines & shadows */
  --hairline:     rgba(27, 36, 51, 0.10);
  --hairline-2:   rgba(27, 36, 51, 0.18);
  --shadow-card:  0 1px 0 rgba(27,36,51,.04), 0 8px 24px -12px rgba(27,36,51,.18);
  --shadow-pop:   0 1px 0 rgba(255,255,255,.7), 0 14px 30px -14px rgba(27,36,51,.28);
  --shadow-pin:   0 6px 22px -6px rgba(27,36,51,.24), 0 1px 0 rgba(255,255,255,.65);
  --shadow-tip:   0 4px 14px -2px rgba(27,36,51,.18);

  /* Type — sleek, modern sans-serif system.
     `--font-display` swapped from a serif (Fraunces) to Inter, the
     industry standard for clean editorial UI. Inter ships with a
     variable optical-size axis that adapts the letterforms to the
     rendered size — small text gets slightly wider counters, big
     display text gets tighter aperture and crisper joints. Manrope
     handles the body, JetBrains Mono the eyebrow labels. */
  --font-display: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-sans:    'Manrope', system-ui, sans-serif;
  --font-mono:    'JetBrains Mono', ui-monospace, Menlo, monospace;

  /* Layout */
  --side-pad:    clamp(20px, 3.6vw, 64px);
  --col-text:    clamp(360px, 44vw, 600px);
  --topbar-h:    72px;
  --radius:      16px;
  --radius-sm:   10px;
  --radius-lg:   22px;

  /* Unified type scale — shared by .hero__title (home), .lab-title (lab),
     .hero--cozy .hero__title (cozy). Keeping the size, line-height,
     letter-spacing and weight identical means the three pages feel
     part of the same system.
     The clamp() uses a calc(REM + VW) midpoint so the curve is linear
     between viewports — no harsh inflection at the floor/ceiling. */
  --title-size:    clamp(34px, calc(1.5rem + 3.2vw), 78px);
  /* Tighter rhythm for a sleek sans-serif display feel — Inter at
     large sizes likes a hair tighter tracking and slightly shorter
     leading than the previous serif setup. */
  --title-leading: 1.02;
  --title-tracking: -0.025em;
  --title-weight: 500;
  --sub-size:      clamp(14.5px, calc(0.85rem + 0.25vw), 17px);
  --sub-leading:   1.6;

  /* Spacing rhythm — fluid scale used across the column to keep
     vertical breathing room consistent at every viewport. */
  --gap-xs:  clamp(8px, 0.5rem + 0.3vw, 14px);
  --gap-sm:  clamp(12px, 0.75rem + 0.4vw, 18px);
  --gap-md:  clamp(18px, 1rem + 0.6vw, 28px);
  --gap-lg:  clamp(28px, 1.5rem + 1vw, 44px);
  --gap-xl:  clamp(44px, 2rem + 2vw, 72px);

  /* Motion — shared easing and durations so micro-interactions
     across the whole site feel like one designed system. */
  --ease-out:    cubic-bezier(0.2, 0.7, 0.2, 1);
  --ease-spring: cubic-bezier(0.34, 1.36, 0.64, 1);
  --t-fast:   0.18s;
  --t-mid:    0.3s;
  --t-slow:   0.55s;
}

/* ---------------- RESET ---------------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html {
  -webkit-text-size-adjust: 100%;
  /* Smooth in-page scroll; reduced-motion users get instant jumps
     because the @media (prefers-reduced-motion) rule below kills
     animations + transitions globally. */
  scroll-behavior: smooth;
}
body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.55;
  font-weight: 400;
  letter-spacing: 0.005em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}
img, video, svg { display: block; max-width: 100%; }
button { font-family: inherit; cursor: pointer; }
a { color: inherit; text-decoration: none; }
/* Unified focus ring across every interactive element — same colour,
   same offset, same radius. Visual consistency reads as quality. */
a:focus-visible, button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 6px;
}
::selection { background: var(--accent-soft); color: var(--ink); }

/* Skip-to-content — keyboard users land on this on Tab. Hidden
   off-screen until focused, then snaps into view at the top-left
   of the viewport with full visibility. */
.skip-link {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 200;
  padding: 10px 16px;
  border-radius: 8px;
  background: var(--ink);
  color: #fff;
  font-family: var(--font-sans);
  font-size: 13.5px;
  font-weight: 600;
  text-decoration: none;
  box-shadow: 0 8px 22px -8px rgba(27, 36, 51, 0.4);
  transform: translateY(-200%);
  transition: transform var(--t-fast) var(--ease-out);
}
.skip-link:focus-visible {
  transform: translateY(0);
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* =================== CORNER DECO =================== */
.deco-frame {
  position: fixed; inset: 14px;
  pointer-events: none; z-index: 60;
}
.deco-frame__corner {
  position: absolute; width: 22px; height: 22px;
}
.deco-frame__corner::before,
.deco-frame__corner::after {
  content: ""; position: absolute; background: var(--ink-line);
}
.deco-frame__corner::before { width: 22px; height: 1px; }
.deco-frame__corner::after  { width: 1px;  height: 22px; }
.deco-frame__corner--tl { top: 0; left: 0; }
.deco-frame__corner--tr { top: 0; right: 0; }
.deco-frame__corner--tr::before { right: 0; }
.deco-frame__corner--tr::after  { right: 0; }
.deco-frame__corner--bl { bottom: 0; left: 0; }
.deco-frame__corner--bl::before { bottom: 0; }
.deco-frame__corner--br { bottom: 0; right: 0; }
.deco-frame__corner--br::before { bottom: 0; right: 0; }
.deco-frame__corner--br::after  { bottom: 0; right: 0; }

.deco-frame__plus {
  position: absolute; width: 8px; height: 8px; color: var(--ink-line);
}
.deco-frame__plus::before, .deco-frame__plus::after {
  content: ""; position: absolute; background: currentColor;
}
.deco-frame__plus::before { left: 0; right: 0; top: 50%; height: 1px; }
.deco-frame__plus::after  { top: 0; bottom: 0; left: 50%; width: 1px; }
.deco-frame__plus--tl { top: 30px;    left: 30px; }
.deco-frame__plus--tr { top: 30px;    right: 30px; }
.deco-frame__plus--bl { bottom: 30px; left: 30px; }
.deco-frame__plus--br { bottom: 30px; right: 30px; }

/* =================== STICKY TOPBAR =================== */
.topbar {
  position: fixed; top: 0; left: 0; right: 0;
  z-index: 100; height: var(--topbar-h);
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 24px;
  padding: 0 var(--side-pad);
  background: var(--bg-blur);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid var(--hairline);
}

.topbar__brand {
  display: inline-flex; align-items: center; gap: 12px;
  font-family: var(--font-mono);
  font-size: 13px; letter-spacing: 0.04em; color: var(--ink);
  padding: 4px;
  margin: -4px;
  border-radius: 10px;
  transition: opacity .2s ease;
}
.topbar__brand:hover { opacity: 0.7; }
.topbar__brand:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.topbar__brand-mark {
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--ink); border-radius: 8px;
  font-family: var(--font-mono); font-size: 13px;
  font-weight: 600; letter-spacing: 0.05em;
  background: var(--surface);
  transition: background .2s ease, border-color .2s ease;
}
.topbar__brand:hover .topbar__brand-mark {
  background: var(--accent-soft);
  border-color: var(--accent-deep);
}
.topbar__domain { color: var(--ink); }

/* scale bar — "20 M" centered between the two line segments */
.topbar__scale {
  display: flex; align-items: center; justify-content: center;
}
.topbar__scale svg { color: var(--ink-line); }
.topbar__scale-text {
  font-family: var(--font-mono);
  font-size: 11px; letter-spacing: 0.18em;
  color: var(--ink-mute);
  margin: 0 14px;
}

/* topbar nav — proper CTA-style buttons matching hero buttons */
.topbar__nav {
  display: inline-flex; align-items: center; gap: 12px;
}
.topbar__btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 16px;
  border-radius: 10px;
  border: 1px solid var(--hairline-2);
  background: transparent;
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 13.5px; font-weight: 600;
  letter-spacing: 0.005em;
  position: relative;
  transition: transform .18s ease, background .2s ease, border-color .2s ease, color .2s ease, box-shadow .2s ease;
}
.topbar__btn:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-deep);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px -8px rgba(192,74,161,0.45);
}
.topbar__btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-color: var(--accent);
}
.topbar__btn:active {
  transform: translateY(0);
  box-shadow: 0 1px 3px rgba(27,36,51,0.08) inset;
  background: var(--accent-soft);
}
.topbar__btn-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-pale);
}
/* Long/short label toggle — long shown by default, short shown on
   the smallest phones where space is tight. CSS-controlled so we
   never have a flash of wrong text. */
.topbar__btn-short { display: none; }
.topbar__btn-long  { display: inline; }
/* Active / current-page state — used on standalone pages to indicate
   which section the user is currently viewing. Subtle accent fill,
   no transform, no hover glow. */
.topbar__btn.is-active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-deep);
}
.topbar__btn.is-active:hover {
  transform: none;
  box-shadow: none;
}
.topbar__btn--soon {
  color: var(--ink-mute);
  cursor: not-allowed;
}
.topbar__btn--soon:hover {
  background: transparent;
  border-color: var(--hairline-2);
  color: var(--ink-mute);
  transform: none;
  box-shadow: none;
}
.topbar__btn--soon:active {
  transform: none;
  box-shadow: none;
  background: transparent;
}
/* Functional Lab button — slight emphasis to differentiate from disabled state */
.topbar__btn--lab {
  cursor: pointer;
}

/* =================== APP =================== */
.app {
  position: relative; min-height: 100vh;
  padding-top: var(--topbar-h);
}

/* =================== STAGE — illustration anchored top/right/bottom ===================
   The stage occupies the right portion of the viewport, below the topbar.
   The illustration sits flush against the bottom of the topbar (not under it).
   Inside it, a centered media-frame holds the video at its natural 16:9 aspect —
   no zoom, no parallax, no wobble. The video's own cream background blends
   seamlessly with the page bg, so the left edge of the illustration appears
   as a soft, natural transition into the text column.
   A barely-perceptible mask softens the left ~2% of the stage. */
.stage {
  position: fixed;
  top: var(--topbar-h);
  right: 0;
  bottom: 0;
  left: var(--col-text);
  z-index: 1;
  pointer-events: none;
  overflow: hidden;
  background: var(--bg);
}

.stage__layer {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .55s cubic-bezier(.2,.7,.2,1);
}
.stage__layer.is-active { opacity: 1; }
.stage__layer--transition {
  opacity: 0; z-index: 5;
  background: transparent; pointer-events: none;
}
.stage__layer--transition.is-playing { opacity: 1; }
.stage__layer--transition.is-fading {
  transition: opacity .65s ease-out;
}

/* Cozy transition layer — uses #EEDED5 background so any visible
   gap between the video frame and the layer edges matches the cozy
   page bg seamlessly. */
.stage__layer--transition-cozy {
  background: #EEDED5;
}

/* Inside the cozy transition layer: static image preview underneath,
   transition video on top. Both are absolutely positioned so they
   stack. The preview is hidden until the video starts revealing it. */
.stage__cozy-preview,
.stage__cozy-video {
  position: absolute;
  inset: 0;
}
.stage__cozy-preview {
  z-index: 1;
  opacity: 0;
  transition: opacity .9s ease-out;
}
.stage__cozy-video {
  z-index: 2;
  opacity: 1;
  transition: opacity .9s ease-out;
}
/* When the JS adds .is-revealing, crossfade: preview in, video out */
.stage__layer--transition-cozy.is-revealing .stage__cozy-preview {
  opacity: 1;
}
.stage__layer--transition-cozy.is-revealing .stage__cozy-video {
  opacity: 0;
}

/* visual fills the stage edge-to-edge (top, bottom, right) */
.stage__visual {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

/* center container — flex centers the media-frame within the stage */
.stage__media-fit {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;   /* anchor to right edge — matches concept */
}

/* media-frame — the actual video container at natural 16:9.
   It fills as much of the stage as possible while maintaining aspect ratio.
   When the stage is taller than 16:9, the frame is width-constrained;
   when it's wider, the frame is height-constrained. */
.stage__media-frame {
  position: relative;
  /* Natural aspect of the illustrations — 16:9 */
  aspect-ratio: 16 / 9;
  /* Fill height first; width auto from aspect-ratio */
  height: 100%;
  width: auto;
  /* If width-from-aspect exceeds parent, max-width caps it
     and aspect-ratio keeps height in step */
  max-width: 100%;
}

.stage__media-frame video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  background: var(--bg);
}

/* Subtle left-edge mask — barely perceptible. Just enough to soften the
   transition where the illustration meets the page background of the
   text column. Uses --bg so the mask color follows the current page bg
   automatically (cream on home/lab, plinth-warm on cozy). */
.stage__edge-mask {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
  background: linear-gradient(to right,
    var(--bg) 0%,
    var(--bg) 1%,
    transparent 6%
  );
}

/* =================== PINS =================== */
.pin {
  position: absolute;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 0; margin: 0;
  background: transparent; border: 0;
  pointer-events: auto; cursor: pointer;
  font-family: inherit; color: inherit;
  z-index: 4;
  transform: translate(-12px, -12px);
}
.pin[disabled] { cursor: not-allowed; }

.pin__anchor {
  position: relative; width: 24px; height: 24px;
  flex: 0 0 24px;
  display: inline-flex; align-items: center; justify-content: center;
}
.pin__anchor::before {
  content: ""; position: absolute;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--pin-color, var(--accent));
  opacity: .22;
  animation: pinPulse 2.4s ease-out infinite;
}
.pin__anchor::after {
  content: ""; position: absolute;
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--pin-color, var(--accent));
  box-shadow: 0 0 0 3px #fff, var(--shadow-pin);
}
@keyframes pinPulse {
  0%   { transform: scale(1);   opacity: .35; }
  70%  { transform: scale(2.4); opacity: 0; }
  100% { transform: scale(2.4); opacity: 0; }
}

.pin__leader {
  width: 22px; height: 1px;
  background: var(--pin-color, var(--accent));
  opacity: .55;
}
.pin__card {
  display: inline-flex; align-items: center; gap: 12px;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  border: 1px solid var(--hairline);
  border-radius: 999px;
  box-shadow: var(--shadow-pop);
  transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
  white-space: nowrap;
}
.pin:hover:not([disabled]) .pin__card {
  transform: translateY(-1px);
  box-shadow: 0 1px 0 rgba(255,255,255,.7), 0 18px 40px -16px rgba(27,36,51,.32);
  border-color: var(--accent-soft);
}
.pin:focus-visible {
  outline: none;
}
.pin:focus-visible .pin__card {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-color: var(--accent-soft);
}
.pin:active:not([disabled]) .pin__card {
  transform: translateY(0);
  box-shadow: 0 1px 4px rgba(27,36,51,0.12) inset, var(--shadow-pop);
  transition-duration: .08s;
}
.pin__icon {
  width: 26px; height: 26px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--pin-color, var(--accent));
  color: #fff; flex: 0 0 26px;
}
.pin__icon svg { width: 14px; height: 14px; }
.pin__text {
  display: inline-flex; flex-direction: column;
  align-items: flex-start; text-align: left; line-height: 1.15;
}
.pin__eyebrow {
  font-family: var(--font-mono);
  font-size: 9.5px; letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute); font-weight: 500;
}
.pin__name {
  font-family: var(--font-sans);
  font-size: 14px; font-weight: 600; color: var(--ink);
}
.pin__chev {
  margin-left: 4px; color: var(--ink-mute);
  font-size: 14px; line-height: 1;
}

/* per-pin colors + position (inside the 16:9 media-frame, so % values
   map directly to positions on the video frame itself).
   - Lab pin sits on the Gherkin building (upper-right)
   - Pad pin sits on the residential row houses (lower-left) */
.pin--lab { --pin-color: var(--accent); top: 32%; left: 54%; }
.pin--pad { --pin-color: var(--muted);  top: 72%; left: 26%; }

/* Cozy-page game pins — anchored as % of the 4:3 cozy-pad image.
   The same percentages map identically across all viewports because
   the .stage__media-frame--cozy keeps its 4:3 aspect ratio
   regardless of size. Coordinates were tuned against the artwork:
   - Fly pin sits on the TV (the cityscape display) inside the cutaway
   - Play pin sits next to Poky & Hygge on the rug */
.pin--fly  { --pin-color: var(--accent); top: 38%; left: 49%; }
.pin--play { --pin-color: var(--accent); top: 59%; left: 62%; }

/* Mobile / tablet: hide the Flight Sim pin entirely — that game is
   keyboard-only with a heavy cockpit and isn't usable on touch.
   Ferret Racers has built-in touch controls so its pin stays. */
@media (max-width: 1024px) {
  .pin--fly { display: none; }
}

/* =================== GAME POPUP — cozy mini-game launcher ===================
   Centered modal with a soft scrim backdrop. One DOM, two panels —
   the visible one is toggled via [data-popup-panel] matching the
   value JS sets on the dialog. Stays compact on mobile, wide enough
   to breathe on desktop. */
.game-popup {
  position: fixed; inset: 0; z-index: 200;
  display: none;
  align-items: center; justify-content: center;
  padding: 20px;
}
.game-popup.is-open { display: flex; }
.game-popup__backdrop {
  position: absolute; inset: 0;
  background: rgba(27, 36, 51, 0.42);
  backdrop-filter: blur(6px) saturate(140%);
  -webkit-backdrop-filter: blur(6px) saturate(140%);
  animation: popupFade .25s ease both;
}
.game-popup__card {
  position: relative;
  width: min(420px, 100%);
  background: #FFFFFF;
  border: 1px solid var(--hairline);
  border-radius: 18px;
  padding: 28px 26px 26px;
  box-shadow: 0 24px 60px -16px rgba(27, 36, 51, 0.32),
              0 1px 0 rgba(255, 255, 255, 0.7) inset;
  animation: popupRise .3s cubic-bezier(.2,.7,.2,1) both;
}
.game-popup__close {
  position: absolute; top: 12px; right: 12px;
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  color: var(--ink-mute);
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.game-popup__close:hover {
  background: var(--accent-soft);
  color: var(--accent-deep);
  border-color: var(--accent-soft);
}
.game-popup__close:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.game-popup__panel { display: none; }
.game-popup.is-open[data-active="ferret-racers"] [data-popup-panel="ferret-racers"],
.game-popup.is-open[data-active="flight-sim"]    [data-popup-panel="flight-sim"] {
  display: block;
}
.game-popup__chip {
  display: inline-flex; align-items: center;
  padding: 4px 11px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent-deep);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 600;
}
.game-popup__title {
  margin: 14px 0 8px;
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--ink);
  letter-spacing: -0.018em;
  font-optical-sizing: auto;
}
.game-popup__desc {
  margin: 0 0 20px;
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-2);
}
.game-popup__cta {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 11px 20px;
  border-radius: 10px;
  background: var(--accent-btn);
  color: var(--on-accent);
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.005em;
  text-decoration: none;
  border: 1px solid transparent;
  box-shadow: 0 1px 0 rgba(255,255,255,0.18) inset, 0 8px 22px -10px var(--accent-glow);
  transition: transform .18s ease, background .25s ease, box-shadow .2s ease;
}
.game-popup__cta:hover {
  background: var(--accent-deep);
  transform: translateY(-1px);
  box-shadow: 0 1px 0 rgba(255,255,255,0.18) inset, 0 14px 30px -12px var(--accent-glow);
}
.game-popup__cta:active {
  transform: translateY(0);
}
.game-popup__cta:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
@keyframes popupFade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes popupRise {
  from { opacity: 0; transform: translateY(10px) scale(.97); }
  to   { opacity: 1; transform: translateY(0)    scale(1); }
}
@media (max-width: 480px) {
  .game-popup__card { padding: 22px 20px 20px; }
  .game-popup__title { font-size: 21px; }
}

.pin[data-tooltip] { position: absolute; }

/* =================== VIEW =================== */
.view {
  display: none;
  position: relative;
  z-index: 2;
  pointer-events: none;
}
.view.is-active { display: block; }
.view > .col,
.view > .lab-work,
.view .col *,
.view .lab-work * { pointer-events: auto; }

.col {
  width: var(--col-text);
  max-width: 100%;
  padding: var(--gap-md) var(--side-pad) var(--gap-xl);
  /* compensate for stage going to top:0 */
  position: relative;
}

/* =================== HOME HERO =================== */
.hero { display: flex; flex-direction: column; }

.hero__eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--font-mono);
  font-size: 11px; letter-spacing: 0.22em;
  text-transform: uppercase; color: var(--ink-mute);
  margin: 0 0 var(--gap-sm);
}
.hero__eyebrow-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-pale);
}

.hero__title {
  font-family: var(--font-display);
  font-weight: var(--title-weight);
  font-size: var(--title-size);
  line-height: var(--title-leading);
  letter-spacing: var(--title-tracking);
  color: var(--ink);
  margin: 0;
  /* Inter ships an opsz axis (14..32). `auto` lets the browser
     pick the right letterforms for the rendered size — no manual
     value needed. */
  font-optical-sizing: auto;
  position: relative;
  /* Balance line lengths visually if the browser supports it.
     Falls back gracefully — older browsers honour the explicit
     <br> tags in markup. Words wrap at word-boundaries only. */
  text-wrap: balance;
  overflow-wrap: break-word;
  word-break: keep-all;
}
.hero__title .accent {
  /* Magenta colour at a slightly heavier weight carries the
     emphasis cleanly — no italic, no serif, just a confident
     punch of brand colour against the ink-deep title. */
  color: var(--accent);
  font-weight: 600;
  position: relative;
  display: inline-block;
}

/* =================== SPARKLE — radial fan (8 lines) ===================
   Built with conic-gradient stripes mask. Ships as inline element so
   it sits next to a word. */
.sparkle {
  display: inline-block;
  width: 1em; height: 1em;
  position: relative;
  vertical-align: middle;
  color: var(--accent);
  flex-shrink: 0;
}
.sparkle--lg { width: 1.1em; height: 1.1em; }
.sparkle__line {
  position: absolute;
  left: 50%; top: 50%;
  width: 2px;
  height: 30%;
  background: currentColor;
  border-radius: 2px;
  transform-origin: 50% 0%;
  transform: translate(-50%, 0%) rotate(var(--r));
  /* dash position outward from center */
  margin-top: 22%;
}
/* eight rays, 45° apart */
.sparkle__line:nth-child(1) { --r:   0deg; }
.sparkle__line:nth-child(2) { --r:  45deg; }
.sparkle__line:nth-child(3) { --r:  90deg; }
.sparkle__line:nth-child(4) { --r: 135deg; }
.sparkle__line:nth-child(5) { --r: 180deg; }
.sparkle__line:nth-child(6) { --r: 225deg; }
.sparkle__line:nth-child(7) { --r: 270deg; }
.sparkle__line:nth-child(8) { --r: 315deg; }

/* mini sparkle on lab title — appears after "experiences" */
.sparkle--inline {
  position: relative;
  margin-left: -0.15em;
  margin-right: 0.12em;
  top: -0.45em;
}

/* The ink-mark / asterisk treatment was retired. Accent emphasis
   now comes purely from colour + weight (see .hero__title .accent
   and .lab-title .accent above). The .ink-mark and .ink-mark--badge
   classes are kept as no-op visibility resets so any leftover
   markup renders silently if it slips through. */
.ink-mark, .ink-mark--badge { display: none; }

.hero__sub {
  margin: var(--gap-md) 0 0;
  font-size: var(--sub-size);
  line-height: var(--sub-leading);
  color: var(--ink-2);
  /* 50ch sits in the comfortable 45–75 character reading range,
     keeping the paragraph from feeling like a wall of text on
     wide viewports while still allowing natural rhythm. */
  max-width: 50ch;
  text-wrap: pretty;
}
.hero__sub strong { color: var(--ink); font-weight: 600; }
/* Modifier — italic display-font lead-in tone, used on cozy &
   optionally elsewhere. With Inter, the italic at light weight
   gives a softer "narrator" voice next to the regular body copy. */
.hero__sub--lead {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(17px, 1.4vw, 21px);
  color: var(--ink);
  line-height: 1.45;
  max-width: 36ch;
  font-optical-sizing: auto;
}
.hero__sub--lead strong {
  color: var(--accent-deep);
  font-weight: 600;
  font-style: normal;
}

.facts {
  list-style: none; margin: var(--gap-md) 0 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--gap-xs);
}
.facts li {
  display: grid; grid-template-columns: 22px 1fr;
  align-items: start; gap: 12px;
  font-size: 14px; color: var(--ink-2); line-height: 1.5;
  text-wrap: pretty;
}
.facts li svg { width: 17px; height: 17px; color: var(--accent); margin-top: 2px; }
.facts li strong { color: var(--ink); font-weight: 600; }

.cta-row {
  display: flex; flex-wrap: wrap; gap: 12px;
  margin: var(--gap-md) 0 0;
}
.btn {
  --btn-bg: var(--accent);
  --btn-fg: var(--on-accent);
  --btn-bd: transparent;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 12px 22px;
  border-radius: 12px;
  border: 1px solid var(--btn-bd);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-sans);
  font-size: 14.5px; font-weight: 600;
  letter-spacing: 0.005em;
  transition: transform var(--t-fast) var(--ease-out),
              background var(--t-fast) var(--ease-out),
              box-shadow var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out);
  position: relative;
  cursor: pointer;
  /* Stop iOS from adding its own tap highlight */
  -webkit-tap-highlight-color: transparent;
}
.btn:hover { transform: translateY(-1px); }
.btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.btn:active {
  transform: translateY(0);
  transition-duration: 0.08s;
}
.btn--primary {
  /* WCAG: --accent-btn (#B0408F) gives 5.29:1 white-on-bg, passes
     AA-normal for the 14.5px button label. Hover deepens to
     --accent-deep (7.1:1) which is AAA-strong. */
  --btn-bg: var(--accent-btn);
  --btn-fg: var(--on-accent);
  box-shadow: 0 1px 0 rgba(255,255,255,0.18) inset, 0 8px 22px -10px var(--accent-glow);
}
.btn--primary:hover {
  --btn-bg: var(--accent-deep);
  box-shadow: 0 1px 0 rgba(255,255,255,0.18) inset, 0 14px 30px -12px var(--accent-glow);
}
.btn--primary:active {
  --btn-bg: var(--accent-deep);
  box-shadow: 0 1px 2px rgba(27,36,51,0.12) inset, 0 2px 6px -4px var(--accent-glow);
}
.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  --btn-bd: var(--hairline-2);
}
.btn--ghost:hover {
  --btn-bg: var(--accent-soft);
  --btn-bd: var(--accent);
}
.btn--ghost:active {
  --btn-bg: var(--accent-soft);
  box-shadow: 0 1px 3px rgba(27,36,51,0.08) inset;
}
.btn--ghost.is-soon { --btn-fg: var(--ink-mute); cursor: not-allowed; }
.btn--ghost.is-soon:hover {
  --btn-bg: transparent; transform: none; --btn-bd: var(--hairline-2);
}
.btn--ghost.is-soon:active {
  transform: none; box-shadow: none; --btn-bg: transparent;
}
.btn__arrow { display: inline-block; transition: transform .3s ease; }
.btn:hover .btn__arrow { transform: translateX(3px); }
.btn:active .btn__arrow { transform: translateX(2px); }

.driver {
  margin: var(--gap-md) 0 0;
  display: inline-flex; align-items: center; gap: 10px;
  padding: 9px 16px 9px 12px;
  background: var(--accent-pale);
  border: 1px solid var(--accent-soft);
  border-radius: 999px;
  font-size: 13.5px; color: var(--ink-2);
  align-self: flex-start;
}
.driver strong { color: var(--accent-deep); font-weight: 600; }

/* What I do */
.caps-block { margin: var(--gap-xl) 0 0; }
.caps-title {
  font-family: var(--font-display);
  font-style: normal;
  font-size: clamp(18px, 0.95rem + 0.4vw, 22px);
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 var(--gap-sm);
  letter-spacing: -0.015em;
  position: relative;
  display: inline-block;
  font-optical-sizing: auto;
}
.caps-title::after {
  content: ""; position: absolute;
  bottom: -6px; left: 0;
  width: 36px; height: 2px;
  background: var(--accent); border-radius: 2px;
}
.caps-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap-sm) var(--gap-md);
}
.cap {
  display: flex; align-items: flex-start; gap: 12px;
  /* Subtle row treatment so each capability reads as a unit on
     light backgrounds without pulling visual weight from the hero. */
  padding: 4px 0;
}
.cap__icon {
  flex: 0 0 38px; width: 38px; height: 38px;
  border-radius: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--c-soft, var(--accent-soft));
  color: var(--c, var(--accent));
  transition: transform var(--t-fast) var(--ease-out);
}
.cap:hover .cap__icon { transform: scale(1.06); }
.cap__icon svg { width: 18px; height: 18px; }
.cap--orange { --c: var(--accent); --c-soft: var(--accent-soft); }
.cap--blue   { --c: var(--blue);   --c-soft: var(--blue-soft); }
.cap--green  { --c: var(--green);  --c-soft: var(--green-soft); }
.cap--violet { --c: var(--violet); --c-soft: var(--violet-soft); }
.cap__name {
  font-size: 14px; font-weight: 600; color: var(--ink);
  margin: 0 0 2px; letter-spacing: -0.005em;
}
.cap__desc { font-size: 13px; color: var(--ink-mute); margin: 0; line-height: 1.5; }

/* =================== LAB VIEW =================== */
.col--lab-hero {
  min-height: calc(100vh - var(--topbar-h));
  padding-bottom: 32px;
  display: flex; flex-direction: column;
  justify-content: center;
}

/* lab badge — beaker ring + tracking-wide label + radial sparkle */
.lab-badge {
  display: inline-flex; align-items: center; gap: 14px;
  margin: 0 0 22px;
  align-self: flex-start;
}
.lab-badge__ring {
  width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid var(--ink);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--surface); color: var(--ink);
}
.lab-badge__ring svg { width: 20px; height: 20px; }
.lab-badge__label {
  font-family: var(--font-mono);
  font-size: 12.5px; letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink); font-weight: 500;
}

.lab-title {
  font-family: var(--font-display);
  font-size: var(--title-size);
  line-height: var(--title-leading);
  font-weight: var(--title-weight);
  letter-spacing: var(--title-tracking);
  color: var(--ink);
  margin: 0;
  font-optical-sizing: auto;
  /* Balance line breaks so a single short word never strands on
     its own line ("…tomorrow." dangling). */
  text-wrap: balance;
}
.lab-title .accent {
  color: var(--accent);
  font-weight: 600;
}

.lab-sub {
  margin: 22px 0 0;
  font-size: var(--sub-size);
  color: var(--ink-2);
  line-height: var(--sub-leading);
  max-width: 50ch;
}
.lab-sub strong { color: var(--ink); font-weight: 600; }

/* =================== CHIP-STATS — concept-style ===================
   Light icon tile + label, NO dividers between chips. Matches Concept 2.
   Spaced with gap, not separators. */
.lab-chips {
  display: inline-flex; flex-wrap: wrap;
  align-items: center;
  gap: 28px;
  margin: 32px 0 0;
}
.chip-stat {
  display: inline-flex; align-items: center;
  gap: 12px;
  padding: 0;
  position: relative;
}

.chip-stat__icon {
  width: 40px; height: 40px;
  border-radius: 11px;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--c-soft, var(--accent-soft));
  color: var(--c, var(--accent));
  flex: 0 0 40px;
}
.chip-stat__icon svg { width: 20px; height: 20px; }
.chip-stat__body {
  display: inline-flex; flex-direction: column; line-height: 1.2;
}
.chip-stat__name {
  font-family: var(--font-sans);
  font-size: 14.5px; font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.chip-stat__desc {
  font-size: 12px; color: var(--ink-mute);
  margin-top: 2px;
}
.chip-stat--orange { --c: var(--accent); --c-soft: var(--accent-soft); }
.chip-stat--blue   { --c: var(--blue);   --c-soft: var(--blue-soft); }
.chip-stat--green  { --c: var(--green);  --c-soft: var(--green-soft); }

.lab-driver {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 9px 16px 9px 12px;
  background: var(--accent-pale);
  border: 1px solid var(--accent-soft);
  border-radius: 999px;
  font-size: 13.5px; color: var(--ink-2);
  margin: var(--gap-md) 0 0;
  align-self: flex-start;
}
.lab-driver strong { color: var(--accent-deep); font-weight: 600; }

/* =================== LAB WORK — full-width breakout =================== */
.lab-work {
  position: relative;
  z-index: 2;
  width: 100%;
  background: transparent;
  padding: var(--gap-xl) var(--side-pad) calc(var(--gap-xl) + 32px);
}
.lab-work__inner { max-width: 1320px; margin: 0 auto; }

.work-title {
  font-family: var(--font-display);
  font-size: clamp(28px, 1.3rem + 1.5vw, 44px);
  font-style: normal;
  font-weight: 600;
  line-height: 1.1;
  color: var(--ink);
  margin: 0 0 var(--gap-md);
  display: inline-flex; align-items: center; gap: 14px;
  position: relative;
  letter-spacing: -0.022em;
  font-optical-sizing: auto;
}
.work-title__underline {
  position: absolute;
  left: 0; bottom: 4px;
  width: 92px; height: 3px;
  background: var(--accent); border-radius: 3px;
}

/* =================== PROJECT CARDS =================== */
.proj-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap-md);
}
@media (max-width: 980px) { .proj-grid { grid-template-columns: 1fr; } }

.proj {
  position: relative;
  display: flex; flex-direction: column;
  /* solid white surface — keeps cards crisp and high-contrast */
  background: #FFFFFF;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  padding: 28px;
  box-shadow: var(--shadow-card);
  overflow: hidden;
  transition: transform .35s cubic-bezier(.2,.7,.2,1),
              box-shadow .35s ease,
              border-color .25s ease,
              background .25s ease;
  text-decoration: none;
  color: inherit;
}
.proj.is-link { cursor: pointer; }
.proj.is-link:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-pop);
  border-color: var(--accent-soft);
  background: #FFFFFF;
}
.proj.is-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-color: var(--accent-soft);
}
.proj.is-link:active {
  transform: translateY(-1px);
  transition-duration: .12s;
  box-shadow: var(--shadow-card);
}

.proj__head {
  display: flex; align-items: center; gap: 12px;
  margin: 0 0 18px;
}
.proj__chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  font-family: var(--font-sans);
  font-size: 12px; font-weight: 600;
  letter-spacing: 0.01em;
  background: var(--c-soft, var(--accent-soft));
  color: var(--c-deep, var(--accent-deep));
}
.proj__chip svg { width: 12px; height: 12px; }
.proj__chip--blue   { --c-soft: var(--blue-soft);   --c-deep: var(--blue-deep); }
.proj__chip--violet { --c-soft: var(--violet-soft); --c-deep: var(--violet-deep); }
.proj__chip--green  { --c-soft: var(--green-soft);  --c-deep: var(--green-deep); }
.proj__chip--orange { --c-soft: var(--accent-soft); --c-deep: var(--accent-deep); }

.proj__body {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.3fr);
  gap: 24px; align-items: start;
}
@media (max-width: 720px) { .proj__body { grid-template-columns: 1fr; } }

.proj__thumb {
  border-radius: 14px; overflow: hidden;
  background: var(--surface-2);
  aspect-ratio: 4/3;
  display: flex; align-items: center; justify-content: center;
}
.proj__thumb img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .5s cubic-bezier(.2,.7,.2,1);
}
.proj.is-link:hover .proj__thumb img { transform: scale(1.04); }

.proj__copy { min-width: 0; }
.proj__title {
  font-family: var(--font-display);
  font-size: clamp(20px, 1.05rem + 0.5vw, 26px);
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 4px;
  letter-spacing: -0.02em;
  line-height: 1.2;
  font-optical-sizing: auto;
}
.proj__title .accent {
  color: var(--accent);
  font-weight: 700;
}
.proj__meta {
  font-family: var(--font-sans);
  font-size: 13px; color: var(--ink-mute);
  margin: 0 0 14px;
}
/* Meta row — sits below title, holds the (date) text and a small time chip */
.proj__meta-row {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 10px;
  margin: 0 0 14px;
}
.proj__meta-row .proj__meta {
  margin: 0;
}

/* Small time-emphasis chip — used inline next to project meta */
.time-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px 3px 8px;
  border-radius: 999px;
  background: var(--c-soft, var(--accent-soft));
  color: var(--c, var(--accent-deep));
  font-family: var(--font-sans);
  font-size: 11.5px; font-weight: 700;
  letter-spacing: 0.01em;
  border: 1px solid transparent;
  white-space: nowrap;
}
.time-chip svg { width: 13px; height: 13px; flex: 0 0 13px; }
.time-chip--orange { --c: var(--accent-deep); --c-soft: var(--accent-soft); }
.time-chip--blue   { --c: var(--blue-deep);   --c-soft: var(--blue-soft); }
.time-chip--green  { --c: var(--green-deep);  --c-soft: var(--green-soft); }
.time-chip--violet { --c: var(--violet-deep); --c-soft: var(--violet-soft); }

/* Tools row — small label sits ABOVE the chips on its own line so the
   layout looks identical regardless of how many chips wrap below. */
.proj__tools {
  margin: 18px 0 0;
  padding: 14px 0 0;
  border-top: 1px dashed var(--hairline);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}
.proj__tools-label {
  font-family: var(--font-mono);
  font-size: 10.5px; letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  font-weight: 500;
}
.proj__tools-list {
  display: inline-flex; flex-wrap: wrap; gap: 6px;
}

/* Tool chip — pill-style colored chip used for tools/tech */
.tool-chip {
  display: inline-flex; align-items: center;
  padding: 4px 11px;
  border-radius: 999px;
  font-family: var(--font-sans);
  font-size: 11.5px; font-weight: 600;
  letter-spacing: 0.005em;
  white-space: nowrap;
  background: var(--c-soft, var(--accent-soft));
  color: var(--c, var(--accent-deep));
  border: 1px solid transparent;
  transition: transform .15s ease, box-shadow .15s ease;
}
.tool-chip--orange { --c: var(--accent-deep); --c-soft: var(--accent-soft); }
.tool-chip--blue   { --c: var(--blue-deep);   --c-soft: var(--blue-soft); }
.tool-chip--green  { --c: var(--green-deep);  --c-soft: var(--green-soft); }
.tool-chip--violet { --c: var(--violet-deep); --c-soft: var(--violet-soft); }
.proj__desc {
  font-size: 14px; color: var(--ink-2); line-height: 1.55; margin: 0;
}
.proj__desc + .proj__desc { margin-top: 10px; }
.proj__desc strong { color: var(--ink); font-weight: 600; }
.proj__desc .accent { color: var(--accent-deep); font-weight: 600; }

.proj__footer {
  display: flex; align-items: center;
  justify-content: space-between;
  gap: 18px; flex-wrap: wrap;
  margin: 24px 0 0;
}
.proj__cta {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-sans);
  font-size: 14px; font-weight: 600;
  color: var(--accent-deep);
  text-decoration: none; position: relative;
}
.proj__cta::after {
  content: ""; position: absolute;
  left: 0; right: 0; bottom: -3px;
  height: 1.5px; background: var(--accent);
  border-radius: 2px;
  transform: scaleX(.4); transform-origin: left center;
  transition: transform .35s cubic-bezier(.2,.7,.2,1);
}
.proj__cta:hover::after { transform: scaleX(1); }

.proj__tags {
  display: inline-flex; flex-wrap: wrap; gap: 8px;
  margin-left: auto;
}
.tag {
  display: inline-flex; align-items: center;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 12px; font-weight: 500;
  background: var(--c-soft, var(--accent-soft));
  color: var(--c-deep, var(--accent-deep));
  letter-spacing: 0.005em;
}
.tag--orange { --c-soft: var(--accent-soft); --c-deep: var(--accent-deep); }
.tag--blue   { --c-soft: var(--blue-soft);   --c-deep: var(--blue-deep); }
.tag--green  { --c-soft: var(--green-soft);  --c-deep: var(--green-deep); }
.tag--violet { --c-soft: var(--violet-soft); --c-deep: var(--violet-deep); }

/* =================== WORK-IN-PROGRESS INLINE LINK ===================
   Subtle, low-visual-weight link tucked under the hero driver pill on
   the home page. Doesn't compete with the main CTA buttons or break
   the single-screen layout — just a quiet pulsing dot + label hinting
   at upcoming AI products. Hover lifts it gently with magenta accent. */
.wip-inline {
  display: inline-flex; align-items: center; gap: 12px;
  margin-top: var(--gap-sm);
  padding: 10px 16px 10px 14px;
  background: transparent;
  border: 1px dashed var(--accent-soft);
  border-radius: 12px;
  text-decoration: none;
  color: var(--ink-2);
  align-self: flex-start;
  transition: border-color .2s ease, background .2s ease, transform .25s ease;
}
.wip-inline:hover {
  background: var(--accent-pale);
  border-color: var(--accent);
  transform: translateX(2px);
}
.wip-inline:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.wip-inline__dot {
  position: relative;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
  box-shadow: 0 0 0 0 var(--accent-glow);
  animation: wipPulse 2.4s ease-out infinite;
}
.wip-inline__label {
  display: inline-flex; flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.wip-inline__eyebrow {
  font-family: var(--font-mono);
  font-size: 10.5px; letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent-deep);
  font-weight: 500;
}
.wip-inline__name {
  font-family: var(--font-sans);
  font-size: 13.5px; font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.005em;
}

@keyframes wipPulse {
  0%   { box-shadow: 0 0 0 0 var(--accent-glow); }
  70%  { box-shadow: 0 0 0 10px rgba(192,74,161,0); }
  100% { box-shadow: 0 0 0 0 rgba(192,74,161,0); }
}

/* =================== TOOLTIPS — smart side switching ===================
   By default tooltip renders above element pointing down. For elements
   on the right edge of viewport (topbar nav buttons), use the
   .has-tip-below modifier so they render below pointing up — keeps them
   visible in viewport. */
[data-tooltip] { position: relative; }
[data-tooltip]::before,
[data-tooltip]::after {
  position: absolute;
  pointer-events: none;
  opacity: 0;
  transition: opacity .18s ease, transform .18s ease;
  z-index: 110;
}
[data-tooltip]::before {
  content: attr(data-tooltip);
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: var(--ink); color: #fff;
  font-family: var(--font-mono);
  font-size: 11px; letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 7px 11px;
  border-radius: 8px;
  white-space: nowrap;
  box-shadow: var(--shadow-tip);
}
[data-tooltip]::after {
  content: "";
  bottom: calc(100% + 4px); left: 50%;
  transform: translateX(-50%) translateY(4px);
  border: 5px solid transparent;
  border-top-color: var(--ink);
}
[data-tooltip]:hover::before,
[data-tooltip]:focus-visible::before,
[data-tooltip]:hover::after,
[data-tooltip]:focus-visible::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* tooltip points DOWN (renders below element) — for top-right elements */
.has-tip-below[data-tooltip]::before {
  bottom: auto;
  top: calc(100% + 10px);
  transform: translateX(-50%) translateY(-4px);
}
.has-tip-below[data-tooltip]::after {
  bottom: auto;
  top: calc(100% + 4px);
  transform: translateX(-50%) translateY(-4px);
  border-top-color: transparent;
  border-bottom-color: var(--ink);
}
.has-tip-below[data-tooltip]:hover::before,
.has-tip-below[data-tooltip]:focus-visible::before {
  transform: translateX(-50%) translateY(0);
}
.has-tip-below[data-tooltip]:hover::after,
.has-tip-below[data-tooltip]:focus-visible::after {
  transform: translateX(-50%) translateY(0);
}

/* if tooltip is anchored near right edge, shift it left */
.has-tip-end[data-tooltip]::before {
  left: auto; right: 0;
  transform: translateX(0) translateY(4px);
}
.has-tip-end[data-tooltip]::after {
  left: auto; right: 18px;
  transform: translateX(0) translateY(4px);
}
.has-tip-end[data-tooltip]:hover::before {
  transform: translateX(0) translateY(0);
}
.has-tip-end[data-tooltip]:hover::after {
  transform: translateX(0) translateY(0);
}

/* combine: bottom + end (used for topbar's right-most button) */
.has-tip-below.has-tip-end[data-tooltip]::before {
  top: calc(100% + 10px); bottom: auto;
  transform: translateX(0) translateY(-4px);
}
.has-tip-below.has-tip-end[data-tooltip]::after {
  top: calc(100% + 4px); bottom: auto;
  transform: translateX(0) translateY(-4px);
}
.has-tip-below.has-tip-end[data-tooltip]:hover::before,
.has-tip-below.has-tip-end[data-tooltip]:hover::after {
  transform: translateX(0) translateY(0);
}

/* =================== SCENE TRANSITION ANIMATIONS ===================
   Home column elements stay fully visible while the transition video
   plays. The .is-exiting class is added by JS only in the final ~25%
   of the transition video, so the exit animation here is short and
   has minimal stagger — it needs to finish before the view swap. */
.view.is-exiting .col > *,
.view.is-exiting .col {
  animation: viewExit .35s cubic-bezier(.6,.01,.34,1) forwards;
}
.view.is-exiting .hero__eyebrow { animation-delay: 0s;    transform-origin: left top; }
.view.is-exiting .hero__title   { animation-delay: 0.02s; animation-name: viewExitTitle; }
.view.is-exiting .hero__sub     { animation-delay: 0.04s; }
.view.is-exiting .facts         { animation-delay: 0.06s; }
.view.is-exiting .cta-row       { animation-delay: 0.08s; animation-name: viewExitScale; }
.view.is-exiting .driver        { animation-delay: 0.1s; }
.view.is-exiting .caps-block    { animation-delay: 0.04s; }

@keyframes viewExit {
  from { opacity: 1; transform: translateY(0)   scale(1); filter: blur(0px); }
  to   { opacity: 0; transform: translateY(-30px) scale(.96); filter: blur(2px); }
}
@keyframes viewExitTitle {
  from { opacity: 1; transform: translateY(0) scale(1); filter: blur(0px); }
  to   { opacity: 0; transform: translateY(-50px) scale(1.04); filter: blur(3px); }
}
@keyframes viewExitScale {
  from { opacity: 1; transform: translateY(0)   scale(1); }
  to   { opacity: 0; transform: translateY(20px) scale(.85); }
}

/* =================== ENTRANCE ANIMATION SYSTEM ===================
   Each view (home on initial load, lab post-transition, cozy pad on
   load) shares a common animation vocabulary so the site feels
   coherent. Different elements use different motion personalities:
     • Eyebrow / tag      → soft slide-down + fade (intimate, confident)
     • Title              → word-by-word stagger, each word rises with
                            a slight scale-up and unblur (cinematic)
     • Subtitle / paragraphs → smooth fade-up with blur-out (calm)
     • Chips / cards      → individual pop-in with mini-spring (playful)
     • Driver / closing   → late, slow fade (settling)
     • Action button      → late, gentle scale-pop (an arrival) */

/* --- Reusable keyframes for all views --- */
@keyframes enterFadeUp {
  from { opacity: 0; transform: translateY(28px); filter: blur(6px); }
  to   { opacity: 1; transform: translateY(0);    filter: blur(0); }
}
@keyframes enterFadeDown {
  from { opacity: 0; transform: translateY(-12px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes enterWord {
  from {
    opacity: 0;
    transform: translateY(40px) scale(.9);
    filter: blur(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
    filter: blur(0);
  }
}
@keyframes enterPop {
  0%   { opacity: 0; transform: translateY(14px) scale(.88); }
  60%  { opacity: 1; transform: translateY(-2px) scale(1.04); }
  100% { opacity: 1; transform: translateY(0)   scale(1); }
}
@keyframes enterFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes enterPlate {
  from {
    opacity: 0;
    transform: translateY(18px) scale(.96);
    filter: blur(4px);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
    filter: blur(0);
  }
}

/* lab view enter — staggered, varied animations after transition */
.view--lab.is-entering .lab-badge {
  animation: enterFadeDown .55s cubic-bezier(.2,.7,.2,1) both;
  animation-delay: 0.05s;
}
.view--lab.is-entering .lab-title .word {
  display: inline-block;
  animation: enterWord .85s cubic-bezier(.2,.7,.2,1) both;
}
.view--lab.is-entering .lab-title .word:nth-child(1) { animation-delay: 0.15s; }
.view--lab.is-entering .lab-title .word:nth-child(2) { animation-delay: 0.23s; }
.view--lab.is-entering .lab-title .word:nth-child(3) { animation-delay: 0.31s; }
.view--lab.is-entering .lab-title .word:nth-child(4) { animation-delay: 0.39s; }
.view--lab.is-entering .lab-title .word:nth-child(5) { animation-delay: 0.47s; }
.view--lab.is-entering .lab-title .word:nth-child(6) { animation-delay: 0.55s; }
.view--lab.is-entering .lab-sub {
  animation: enterFadeUp .8s cubic-bezier(.2,.7,.2,1) both;
  animation-delay: 0.75s;
}
.view--lab.is-entering .lab-chips .chip-stat {
  animation: enterPop .7s cubic-bezier(.34,1.36,.64,1) both;
}
.view--lab.is-entering .lab-chips .chip-stat:nth-child(1) { animation-delay: 1.0s; }
.view--lab.is-entering .lab-chips .chip-stat:nth-child(2) { animation-delay: 1.12s; }
.view--lab.is-entering .lab-chips .chip-stat:nth-child(3) { animation-delay: 1.24s; }
.view--lab.is-entering .lab-driver {
  animation: enterFadeIn .8s ease-out both;
  animation-delay: 1.4s;
}

/* home view initial-load entrance — runs on first page load, never
   replays. Each element gets its own personality and the CTAs land
   last so the user's eye is led from headline → sub → action. */
.view--home.is-entering .hero__eyebrow {
  animation: enterFadeDown .6s cubic-bezier(.2,.7,.2,1) both;
  animation-delay: 0.15s;
}
.view--home.is-entering .hero__title .word {
  display: inline-block;
  animation: enterWord .85s cubic-bezier(.2,.7,.2,1) both;
}
.view--home.is-entering .hero__title .word:nth-child(1)  { animation-delay: 0.30s; }
.view--home.is-entering .hero__title .word:nth-child(2)  { animation-delay: 0.38s; }
.view--home.is-entering .hero__title .word:nth-child(3)  { animation-delay: 0.46s; }
.view--home.is-entering .hero__title .word:nth-child(4)  { animation-delay: 0.54s; }
.view--home.is-entering .hero__title .word:nth-child(5)  { animation-delay: 0.62s; }
.view--home.is-entering .hero__title .word:nth-child(6)  { animation-delay: 0.70s; }
.view--home.is-entering .hero__title .word:nth-child(7)  { animation-delay: 0.78s; }
.view--home.is-entering .hero__title .word:nth-child(8)  { animation-delay: 0.86s; }
.view--home.is-entering .hero__title .word:nth-child(n+9){ animation-delay: 0.94s; }
.view--home.is-entering .hero__sub {
  animation: enterFadeUp .8s cubic-bezier(.2,.7,.2,1) both;
  animation-delay: 1.15s;
}
.view--home.is-entering .facts li {
  animation: enterFadeUp .65s cubic-bezier(.2,.7,.2,1) both;
}
.view--home.is-entering .facts li:nth-child(1) { animation-delay: 1.45s; }
.view--home.is-entering .facts li:nth-child(2) { animation-delay: 1.55s; }
.view--home.is-entering .facts li:nth-child(3) { animation-delay: 1.65s; }
.view--home.is-entering .cta-row .btn {
  animation: enterPop .7s cubic-bezier(.34,1.36,.64,1) both;
}
.view--home.is-entering .cta-row .btn:nth-child(1) { animation-delay: 1.85s; }
.view--home.is-entering .cta-row .btn:nth-child(2) { animation-delay: 1.97s; }
.view--home.is-entering .driver {
  animation: enterFadeIn .9s ease-out both;
  animation-delay: 2.15s;
}

/* keep old keyframe name aliased for any leftover refs */
@keyframes viewEnter {
  from { opacity: 0; transform: translateY(24px); filter: blur(4px); }
  to   { opacity: 1; transform: translateY(0);    filter: blur(0); }
}

/* =================== COZY PAD PAGE ===================
   Standalone page (cozy-pad.html) that mirrors home/lab structure
   for visual consistency. Same topbar (with the same UX Lab + About
   Me buttons), same fixed-stage-on-the-right, same column on the
   left. Background is the warmer #EEDED5 of the illustration plinth
   so the seam between page bg and image edges is invisible. */
.page-cozy {
  --bg: #EEDED5;
  --bg-blur: rgba(238,222,213,0.78);
  background: var(--bg);
  min-height: 100vh;
  overflow-x: hidden;
}
.page-cozy .topbar {
  background: var(--bg-blur);
}

/* Cozy-specific bleed mask — fades the LEFT edge of the cozy
   illustration into the cozy page background. The page-cozy --bg
   is the warm plinth tone (#EEDED5), matching the image plinth
   exactly. Always visible across all viewports. */
.page-cozy .stage__edge-mask {
  display: block;
  background: linear-gradient(to right,
    #EEDED5 0%,
    #EEDED5 4%,
    rgba(238,222,213,0.85) 8%,
    rgba(238,222,213,0.4) 14%,
    rgba(238,222,213,0) 20%
  );
}

/* Cozy transition video — bridges the home column bg (#FAF2EB
   cream) on the left into the cozy transition layer bg (#EEDED5
   warm plinth) on the right. Without this two-stop bridge, the
   seam between column and stage shows up as a hard vertical line
   exactly at the column→stage edge. The mask is wider (~22%) and
   starts solid so the video's left edge is never visible.
   The mask's first stop tracks the body's animated bg via
   var(--cozy-trans-edge), so as the body crossfades to the cozy
   plinth tone, the mask follows in lock-step — column and mask
   stay flush throughout the transition. */
.stage__layer--transition-cozy .stage__edge-mask {
  display: block;
  background: linear-gradient(to right,
    var(--cozy-trans-edge, #FAF2EB) 0%,
    var(--cozy-trans-edge, #FAF2EB) 3%,
    rgba(244, 234, 220, 0.85) 7%,
    rgba(238, 222, 213, 0.55) 13%,
    rgba(238, 222, 213, 0.18) 18%,
    rgba(238, 222, 213, 0) 22%
  );
}

/* =================== COZY BG CROSSFADE ===================
   When the home → cozy transition starts, JS tags <body> with
   .is-cozy-bg-shift. The body bg, the topbar bg-blur, and the
   transition-layer mask edge all crossfade from the home cream
   palette into the cozy plinth palette over the duration of the
   transition video. By the time the user lands on cozy-pad.html,
   the page bg is already at the cozy tone — there's no colour
   pop on navigation, the seam is invisible.
   Duration matches the navigation timing in script.js (~88% of
   the 6s transition video ≈ 5.3s). */
@keyframes cozyBodyBgShift {
  from { background-color: #FAF2EB; }
  to   { background-color: #EEDED5; }
}
@keyframes cozyTopbarBgShift {
  from { background-color: rgba(250, 242, 235, 0.78); }
  to   { background-color: rgba(238, 222, 213, 0.78); }
}
@keyframes cozyEdgeShift {
  /* drives --cozy-trans-edge so the transition mask's solid stop
     follows the body bg colour exactly */
  from { --cozy-trans-edge: #FAF2EB; }
  to   { --cozy-trans-edge: #EEDED5; }
}
@property --cozy-trans-edge {
  syntax: '<color>';
  inherits: true;
  initial-value: #FAF2EB;
}
body.is-cozy-bg-shift {
  animation: cozyBodyBgShift 5.3s ease-in-out forwards,
             cozyEdgeShift   5.3s ease-in-out forwards;
}
body.is-cozy-bg-shift .topbar {
  animation: cozyTopbarBgShift 5.3s ease-in-out forwards;
}

/* Standalone topbar layout — middle section is just an empty spacer
   so the back button anchors right. */
.topbar--standalone .topbar__spacer { display: block; }

/* Cozy-specific stage — illustration is 4:3, has built-in cream
   background that matches the page bg exactly. No edge mask, no
   16:9 crop.
   On the standalone cozy page, suppress the .stage__layer fade-in
   transition so the image is fully visible the moment the page
   paints. Without this, the .stage__layer's default
   `opacity: 0; transition: opacity .55s` causes a brief gap
   right after navigation where the topbar covers a not-yet-faded-in
   image — the "image briefly covered" flash. */
.stage__layer--cozy { z-index: 1; }
.stage__layer--cozy.is-active { opacity: 1; }
.page-cozy .stage__layer { opacity: 1; transition: none; }
.stage__media-frame--cozy {
  aspect-ratio: 4 / 3;
  background: var(--bg);
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  overflow: hidden;
}
.stage__cozy-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center bottom;
  display: block;
  background: var(--bg);
}

/* Cozy hero column — uses the same .col / .hero base structure as
   home, with a small modifier to keep things spaced consistently. */
.hero--cozy {
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* Cozy title's accent period — matches the warm tone of "Cozy Pad" */
.hero--cozy .hero__title .accent {
  color: var(--accent);
  font-weight: 600;
}

/* Cozy subtitle — middle clause uses the display font + accent color
   to give the line a personal, hand-set feel. The bookending text and
   the closing word "on" stay in the default plain treatment. */
.hero__sub--cozy {
  font-size: clamp(15.5px, 0.9rem + 0.3vw, 18.5px);
  line-height: 1.55;
  max-width: 46ch;
  text-wrap: pretty;
}
.cozy-sub-accent {
  /* WCAG AA: --accent-deep on the cozy plinth bg is ~4.6:1 (passes
     AA-normal for ~19px text); --accent itself only clears 3.4:1
     here, which fails normal-weight body copy. */
  color: var(--accent-deep);
  font-family: var(--font-display);
  font-weight: 600;
  font-optical-sizing: auto;
}

/* Bio paragraphs */
.cozy-bio {
  display: flex;
  flex-direction: column;
  gap: var(--gap-xs);
  margin: var(--gap-md) 0 0;
  max-width: 50ch;
}
.cozy-para {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--sub-size);
  line-height: 1.65;
  color: var(--ink-2);
  text-wrap: pretty;
}
.cozy-para strong {
  color: var(--ink);
  font-weight: 600;
}

/* Hobby chips — pill row of pill-style tags with icons */
.cozy-hobbies {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: var(--gap-md) 0 0;
  max-width: 56ch;
}
.hobby-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px 7px 8px;
  border-radius: 999px;
  background: var(--c-soft, rgba(255,255,255,0.55));
  border: 1px solid var(--c-border, var(--hairline));
  color: var(--c, var(--ink));
  font-family: var(--font-sans);
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: 0.005em;
  white-space: nowrap;
  transition: transform .2s ease, box-shadow .2s ease, background .2s ease;
}
.hobby-chip:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 14px -8px rgba(0,0,0,0.18);
}
.hobby-chip__icon {
  width: 24px; height: 24px;
  flex: 0 0 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--c-soft-strong, rgba(255,255,255,0.7));
  color: inherit;
}
.hobby-chip__icon svg { width: 14px; height: 14px; }
.hobby-chip em {
  font-style: normal;
  font-weight: 400;
  color: var(--ink-mute);
  margin-left: 4px;
}
.hobby-chip--orange { --c: var(--accent-deep); --c-soft: var(--accent-soft); --c-soft-strong: rgba(192,74,161,0.18); --c-border: rgba(192,74,161,0.25); }
.hobby-chip--terra  { --c: #B85C3D;            --c-soft: rgba(184,92,61,0.10); --c-soft-strong: rgba(184,92,61,0.18); --c-border: rgba(184,92,61,0.25); }
.hobby-chip--violet { --c: var(--violet-deep); --c-soft: var(--violet-soft); --c-soft-strong: rgba(124,58,237,0.16); --c-border: rgba(124,58,237,0.25); }
.hobby-chip--blue   { --c: var(--blue-deep);   --c-soft: var(--blue-soft);   --c-soft-strong: rgba(46,91,255,0.16);  --c-border: rgba(46,91,255,0.25); }
.hobby-chip--green  { --c: var(--green-deep);  --c-soft: var(--green-soft);  --c-soft-strong: rgba(45,157,111,0.18); --c-border: rgba(45,157,111,0.28); }

/* Closing message + LinkedIn invite */
.cozy-closing {
  margin: var(--gap-md) 0 0;
  max-width: 50ch;
}
.cozy-closing__text {
  margin: 0 0 var(--gap-sm);
  font-family: var(--font-sans);
  font-size: var(--sub-size);
  line-height: 1.65;
  color: var(--ink-2);
  text-wrap: pretty;
}
.cozy-closing__text strong {
  color: var(--accent-deep);
  font-weight: 600;
}
.cozy-cta-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
}

/* LinkedIn link — primary CTA styled to match the homepage's
   "Mihai's UX Lab" button. Same AA-tuned accent fill (5.29:1 vs
   white at 14.5px), deepens to AAA on hover. */
.linkedin-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 22px;
  border-radius: 12px;
  background: var(--accent-btn);
  color: var(--on-accent);
  font-family: var(--font-sans);
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: 0.005em;
  border: 1px solid transparent;
  box-shadow: 0 1px 0 rgba(255,255,255,0.18) inset, 0 8px 22px -10px var(--accent-glow);
  transition: transform .18s ease, background .25s ease, box-shadow .2s ease;
}
.linkedin-link:hover {
  background: var(--accent-deep);
  transform: translateY(-1px);
  box-shadow: 0 1px 0 rgba(255,255,255,0.18) inset, 0 14px 30px -12px var(--accent-glow);
}
.linkedin-link:active {
  transform: translateY(0);
  background: var(--accent-deep);
  box-shadow: 0 1px 2px rgba(27,36,51,0.12) inset, 0 2px 6px -4px var(--accent-glow);
}
.linkedin-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.linkedin-link__icon {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  color: var(--on-accent);
}
.linkedin-link__arrow {
  flex: 0 0 12px;
  margin-left: 2px;
  opacity: 0.85;
  transition: transform .25s ease, opacity .2s ease;
}
.linkedin-link:hover .linkedin-link__arrow {
  transform: translate(2px, -2px);
  opacity: 1;
}


/* =================== COZY PAD — ENTRANCE ANIMATIONS ===================
   Reliable, simple sequence using the shared `enter*` keyframes from
   the entrance-animation system. Each element gets a different motion
   personality so the page doesn't feel mechanical, but the animations
   are NOT per-word so we avoid the rendering bug of stuck "from"
   states on inline-block fragments.

   Pre-paint hide: animated elements start at opacity:0 so there's no
   flash of fully-visible content before .is-entering applies. The
   .is-entering class stays on the view permanently so the animations'
   `both` fill mode keeps the final state — removing it would drop the
   animation declaration and re-expose the opacity:0 default. */
@media not (prefers-reduced-motion: reduce) {
  .view--cozy .hero__eyebrow,
  .view--cozy .hero__title,
  .view--cozy .hero__sub,
  .view--cozy .cozy-bio .cozy-para,
  .view--cozy .cozy-hobbies .hobby-chip,
  .view--cozy .cozy-closing,
  .view--cozy .driver {
    opacity: 0;
  }
}
.view--cozy.is-entering .hero__eyebrow {
  animation: enterFadeDown .6s cubic-bezier(.2,.7,.2,1) both;
  animation-delay: 0.1s;
}
.view--cozy.is-entering .hero__title {
  animation: enterFadeUp .9s cubic-bezier(.2,.7,.2,1) both;
  animation-delay: 0.25s;
}
.view--cozy.is-entering .hero__sub {
  animation: enterFadeUp .8s cubic-bezier(.2,.7,.2,1) both;
  animation-delay: 0.55s;
}
.view--cozy.is-entering .cozy-bio .cozy-para {
  animation: enterFadeUp .8s cubic-bezier(.2,.7,.2,1) both;
}
.view--cozy.is-entering .cozy-bio .cozy-para:nth-child(1) { animation-delay: 0.85s; }
.view--cozy.is-entering .cozy-bio .cozy-para:nth-child(2) { animation-delay: 1.0s; }
.view--cozy.is-entering .cozy-hobbies .hobby-chip {
  animation: enterPop .7s cubic-bezier(.34,1.36,.64,1) both;
}
.view--cozy.is-entering .cozy-hobbies .hobby-chip:nth-child(1) { animation-delay: 1.30s; }
.view--cozy.is-entering .cozy-hobbies .hobby-chip:nth-child(2) { animation-delay: 1.40s; }
.view--cozy.is-entering .cozy-hobbies .hobby-chip:nth-child(3) { animation-delay: 1.50s; }
.view--cozy.is-entering .cozy-hobbies .hobby-chip:nth-child(4) { animation-delay: 1.60s; }
.view--cozy.is-entering .cozy-hobbies .hobby-chip:nth-child(5) { animation-delay: 1.70s; }
.view--cozy.is-entering .cozy-hobbies .hobby-chip:nth-child(6) { animation-delay: 1.80s; }
.view--cozy.is-entering .cozy-closing {
  animation: enterFadeUp .9s cubic-bezier(.2,.7,.2,1) both;
  animation-delay: 2.05s;
}
.view--cozy.is-entering .driver {
  animation: enterFadeIn .9s ease-out both;
  animation-delay: 2.4s;
}


/* =================== SITE FOOTER ===================
   Two-part layout: copyright on the left, "built with" + tool chips
   anchored to the right. Wraps gracefully on narrow viewports. */
.site-footer {
  position: relative;
  z-index: 2;
  padding: 32px var(--side-pad) 40px;
  border-top: 1px solid var(--hairline);
  background: var(--bg);
  pointer-events: auto;
}
.site-footer__inner {
  max-width: 1400px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px 24px;
}
.site-footer__copy {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--ink-mute);
  line-height: 1.5;
  flex: 0 0 auto;
}
.site-footer__link {
  color: var(--ink-2);
  font-weight: 600;
  border-bottom: 1px solid var(--hairline);
  transition: color .2s ease, border-color .2s ease;
}
.site-footer__link:hover {
  color: var(--accent-deep);
  border-color: var(--accent);
}
.site-footer__link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
.site-footer__built {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 12px;
  margin-left: auto;
}
.site-footer__built-label {
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--ink-mute);
  line-height: 1.5;
}
.site-footer__tools {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* =================== RESPONSIVE ===================
   Breakpoint plan:
     ≥2400px  ultra-wide   – calmer scale, more breathing room
     ≥1800px  super-wide   – wider column, more side padding
     ≥1280px  desktop XL   – default fluid scale (already-set vars)
     ≥1025px  desktop      – default
     ≤1024px  tablet       – stage stacks above column, single nav
     ≤740px   small tablet – tighter spacing, project grid 1-col
     ≤520px   phone        – tightest scale, dot-only pins
     ≤380px   compact      – minimum-viable scale guarantees       */

/* super-wide */
@media (min-width: 1800px) {
  :root {
    --col-text: clamp(440px, 36vw, 720px);
    --side-pad: clamp(40px, 4vw, 96px);
  }
}

/* ultra-wide (4K, ultrawide monitors) — calmer scale, less aggressive */
@media (min-width: 2400px) {
  :root {
    --col-text: clamp(520px, 30vw, 820px);
    --title-size: clamp(56px, 3.5vw, 92px);
  }
}

/* desktop XL — refine spacing, allow grid to breathe */
@media (min-width: 1280px) {
  .caps-grid { gap: 18px 24px; }
}

/* tablet & below — stage stacks above text */
@media (max-width: 1024px) {
  :root {
    --col-text: 100%;
    --topbar-h: 64px;
  }
  .stage {
    position: relative;
    top: 0; left: 0; right: 0;
    height: auto;
    aspect-ratio: 16 / 9;
    /* Push stage below the fixed topbar so the illustration is not
       cropped behind the menu. */
    margin: var(--topbar-h) 0 var(--gap-sm);
    z-index: 2;
  }
  /* Cozy page uses a 4:3 illustration — give the stage matching
     aspect on mobile so the full image shows without being cropped
     to 16:9 (which would lop the rooftops off the top and make the
     image appear "covered" by the topbar). */
  .page-cozy .stage { aspect-ratio: 4 / 3; }
  .stage__media-fit {
    justify-content: center;
  }
  .stage__media-frame {
    width: 100%;
    max-width: 100%;
    height: 100%;
  }
  /* Cozy media frame keeps its 4:3 ratio on mobile so the image
     fills the cozy stage exactly without forced cover-cropping. */
  .page-cozy .stage__media-frame--cozy {
    aspect-ratio: 4 / 3;
  }
  /* Stage now sits under the topbar (margin-top above), so .app's
     padding-top compensation is no longer needed in this layout. */
  .app { padding-top: 0; }
  .stage__edge-mask { display: none; }
  /* Cozy bleed mask stays visible on tablet/mobile — the left edge
     fade keeps the image feeling integrated with the page bg even
     when the illustration sits at the top of the viewport. */
  .page-cozy .stage__edge-mask,
  .stage__layer--transition-cozy .stage__edge-mask {
    display: block;
  }
  /* Cap the reading column on tablet/medium so the title, subtitle,
     facts, bio and chips all share a consistent visual width.
     Without this cap, .col goes 100% — the title (which has
     explicit <br> tags) ends up much shorter than the long fact
     rows, producing the inconsistent ragged-right look reported
     on the home, lab and cozy pages. The column is centered
     horizontally; ~720px is a comfortable line-length on tablet. */
  .col {
    width: 100%;
    max-width: 720px;
    margin: 0 auto;
    padding: var(--gap-md) var(--side-pad) var(--gap-xl);
  }
  /* On tablet & below, suppress the editorial <br> line breaks
     inside the title — they're a desktop-layout convenience that
     created visually-narrow titles next to wide body copy. With
     the <br>s hidden, the title flows naturally and the
     `text-wrap: balance` rule on .hero__title / .lab-title
     distributes lines evenly across the column width. The result:
     title visual width matches subtitle, facts, bio, and chips. */
  .hero__title br,
  .hero--cozy .hero__title br { display: none; }
  .col--lab-hero { min-height: 0; justify-content: flex-start; }
  /* Lab work breakout (project grid) keeps its wide max-width so
     the cards have room to breathe — only the prose column above
     it is constrained. */
  .lab-work__inner { max-width: 1320px; margin: 0 auto; }
  .topbar { gap: 12px; padding: 0 16px; }
  .topbar__scale { display: none; }
  .topbar__nav { gap: 8px; }
  .topbar__btn { padding: 7px 12px; font-size: 13px; }
  .topbar__brand-mark { width: 32px; height: 32px; font-size: 12px; }
  .caps-grid { grid-template-columns: 1fr 1fr; gap: var(--gap-sm) var(--gap-md); }
  .lab-work { padding: var(--gap-xl) var(--side-pad) calc(var(--gap-xl) + 12px); }
  .lab-chips { gap: var(--gap-md); }
  .site-footer { padding: var(--gap-md) var(--side-pad) var(--gap-md); }
  /* cozy-specific responsive override */
  .stage__media-frame--cozy { aspect-ratio: 4 / 3; }
}

/* small tablet — stack the caps grid and project grid */
@media (max-width: 740px) {
  .caps-grid { grid-template-columns: 1fr; }
}

/* phones */
@media (max-width: 640px) {
  .topbar__domain { display: none; }
  /* Topbar nav stays visible on EVERY page including phones — both
     "Mihai's UX Lab" and "About Me" buttons are always reachable so
     navigation is one tap away no matter the viewport. */
  .topbar__nav { display: inline-flex; gap: 6px; }
  .topbar__btn {
    padding: 7px 11px;
    font-size: 12px;
    gap: 6px;
    border-radius: 8px;
  }
  .topbar__btn-dot { width: 5px; height: 5px; box-shadow: 0 0 0 3px var(--accent-pale); }
  .topbar__btn--back svg { width: 12px; height: 12px; }
  /* On the smallest phones, "Mihai's UX Lab" gets shortened via a
     CSS-level label swap — the data-label-short text takes over. */
  .topbar__btn--lab .topbar__btn-long { display: none; }
  .topbar__btn--lab .topbar__btn-short { display: inline; }
  .work-title { font-size: 32px; }
  .lab-chips { gap: 18px; }
  .chip-stat { gap: 10px; }
  .chip-stat__icon { width: 36px; height: 36px; flex: 0 0 36px; }
  .chip-stat__icon svg { width: 18px; height: 18px; }
  /* on small phones, collapse pins to dot only (popups handle nav).
     Generous tap target via padding+negative margin keeps the dot
     visible at 24px while the click area is ~48px. */
  .pin__leader, .pin__card { display: none; }
  .pin {
    padding: 12px;
    margin: -12px;
  }
  .proj { padding: 20px; }
  .site-footer__inner { gap: 12px; }
  .site-footer__copy { font-size: 12.5px; }
  .proj__tools { gap: 6px 10px; }
  /* cozy-specific phone tweaks */
  .hero__sub--cozy { font-size: 16px; }
  .cozy-hobbies { gap: 6px; }
  .hobby-chip { font-size: 11.5px; padding: 6px 12px 6px 7px; }
  .hobby-chip__icon { width: 20px; height: 20px; flex: 0 0 20px; }
  .hobby-chip__icon svg { width: 12px; height: 12px; }
  .linkedin-link { font-size: 13px; padding: 10px 18px; }
}

/* extra-narrow phones — guarantee both topbar buttons fit */
@media (max-width: 380px) {
  .topbar { padding: 0 12px; gap: 8px; }
  .topbar__btn { padding: 6px 9px; font-size: 11.5px; }
  .topbar__brand-mark { width: 28px; height: 28px; font-size: 11px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
  .pin__anchor::before { animation: none; }
}

.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;
}
