:root {
  --bg: #0a0a0a;
  --fg: #f2f2ee;
  --fg-2: #a8a8a4;
  --fg-3: #8a8a86; /* muted text; >= 4.5:1 on --bg (was #666, 3.4:1) */
  --line: #1f1f1f;
  /* accent tokens: mirrored in content/Palette.kt */
  --accent: #5b6bff;
  --accent-ink: #0a0a0a;
  --accent-glow: rgba(91, 107, 255, .35);
  /* accent at fixed alphas for glows, tints and borders (CSS only, not mirrored) */
  --accent-a03: rgba(91, 107, 255, .03);
  --accent-a12: rgba(91, 107, 255, .12);
  --accent-a14: rgba(91, 107, 255, .14);
  --accent-a16: rgba(91, 107, 255, .16);
  --accent-a45: rgba(91, 107, 255, .45);
  --accent-a50: rgba(91, 107, 255, .5);
  --accent-a55: rgba(91, 107, 255, .55);
  --accent-a60: rgba(91, 107, 255, .6);
  /* over the frame budget (Quality chart only): bar fill and the "before" caption (>= 4.5:1 on --bg) */
  --danger: #ff4d55;
  --danger-ink: #ff7a7f;
  /* project colours, sampled from the app screens; used only in project chapters */
  --pepco-a: #0a6cdc;
  --pepco-b: #e6006e;
  --zappka: #12a04a;
  --gigaset: #f59a0c;
  --surface: #0d0d0d;
  --ease-out: cubic-bezier(.2, .8, .2, 1);
  --gutter: clamp(16px, 4vw, 96px);
  --frame-w: 1600px;
}
@media (min-width: 2400px) { :root { --frame-w: 2200px; } }
@media (min-width: 3000px) { :root { --frame-w: 3400px; } }

html { scroll-behavior: smooth; scroll-padding-top: 88px; }

body {
  margin: 0;
  background-color: var(--bg);
  color: var(--fg);
  font-family: 'Inter Tight', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

:focus-visible { outline: 2px solid var(--fg); outline-offset: 3px; }

.cv-container { width: min(100% - 2 * var(--gutter), var(--frame-w)); margin-inline: auto; }

.cv-section { padding-block: clamp(96px, 12vw, 240px); }

.cv-h1 { font-size: clamp(44px, 6vw, 168px); line-height: .98; font-weight: 800; letter-spacing: -.04em; margin: 0; text-wrap: balance; }
.cv-h2 { font-size: clamp(36px, 4.2vw, 112px); line-height: 1; font-weight: 800; letter-spacing: -.035em; margin: 0; text-wrap: balance; }
.cv-lead { font-size: clamp(17px, .55vw + 12px, 28px); line-height: 1.5; color: var(--fg-2); }
.cv-body { font-size: clamp(15px, .35vw + 11px, 22px); line-height: 1.6; }
.cv-mono {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: clamp(11px, .25vw + 8px, 16px);
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--fg-3);
}
.cv-serif-accent { font-family: 'Instrument Serif', serif; font-style: italic; font-weight: 400; letter-spacing: -.01em; color: var(--accent); }

.cv-grid-bg {
  --mask-at: 70% 45%;
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(255, 255, 255, .045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255, 255, 255, .045) 1px, transparent 1px);
  background-size: 80px 80px;
  -webkit-mask-image: radial-gradient(ellipse at var(--mask-at), #000 0%, transparent 70%);
  mask-image: radial-gradient(ellipse at var(--mask-at), #000 0%, transparent 70%);
}

.cv-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: .9em 1.6em;
  border-radius: 999px;
  font-family: inherit;
  font-weight: 600;
  font-size: clamp(14px, .3vw + 11px, 20px);
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform .25s var(--ease-out), background-color .25s var(--ease-out);
}
.cv-btn--primary { background: var(--accent); color: var(--accent-ink); }
.cv-btn--primary:hover { filter: brightness(1.08); }
.cv-btn--primary:focus-visible { outline-color: var(--fg); }
.cv-btn--ghost { background: transparent; color: var(--fg); border-color: #3a3a3a; }
.cv-btn:hover { transform: translateY(-2px); }
.cv-btn:focus-visible { outline: 2px solid var(--fg); outline-offset: 3px; }

/* One-shot reveal: hidden start only when scripts run and motion is allowed (see "Final state" at the end). */
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  .cv-reveal { opacity: 0; transform: translateY(24px); transition: opacity .8s var(--ease-out), transform .8s var(--ease-out); }
  .cv-reveal.is-in { opacity: 1; transform: none; }
}

.cv-phone {
  box-sizing: border-box;
  width: var(--phone-w);
  padding: 8px;
  background: #1a1a1a;
  border-radius: calc(var(--phone-w) * .155);
}
.cv-phone__screen {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  border-radius: calc(var(--phone-w) * .155 - 8px);
}

.cv-stat { display: flex; flex-direction: column; gap: 8px; }
.cv-stat__final { display: none; }
@media (scripting: none) { .cv-stat__final { display: inline; } .cv-stat__live { display: none; } }
.cv-stat__value { font-size: clamp(44px, 6vw, 168px); line-height: .98; font-weight: 800; letter-spacing: -.04em; font-variant-numeric: tabular-nums; color: var(--accent); }

@keyframes rise { from { transform: translateY(110%); } to { transform: translateY(0); } }
@keyframes fadeUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@keyframes phoneIn { from { opacity: 0; transform: translateY(90px); } to { opacity: 1; transform: none; } }
@keyframes floatA { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
@keyframes floatB { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(12px); } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  /* !important: ScrollTrigger restores an inline smooth value on <html>, and the static export snapshots it. */
  html { scroll-behavior: auto !important; }
}

/* Header navigation and mobile menu */
.cv-skip { position: fixed; top: 8px; left: 8px; z-index: 100; padding: 10px 16px; background: var(--fg); color: var(--bg); border-radius: 999px; text-decoration: none; transform: translateY(-200%); }
.cv-skip:focus-visible { transform: none; }

.cv-header { position: fixed; top: 0; left: 0; right: 0; height: 72px; z-index: 50; border-bottom: 1px solid transparent; background: transparent; }
.cv-header.is-scrolled { background: rgba(10, 10, 10, .8); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); border-bottom-color: var(--line); }
.cv-nav { height: 100%; width: min(100% - 2 * var(--gutter), var(--frame-w)); margin-inline: auto; display: flex; align-items: center; justify-content: space-between; gap: 24px; }
.cv-nav__logo { display: inline-flex; align-items: center; }
.cv-nav__logo img { display: block; }
.cv-nav__links, .cv-nav__lang { display: none; }
.cv-nav__links { align-items: center; gap: clamp(20px, 2.4vw, 40px); margin-left: auto; }
.cv-nav__link { color: var(--fg-2); text-decoration: none; font-size: 15px; transition: color .25s var(--ease-out); }
.cv-nav__link:hover { color: var(--fg); }
.cv-nav__menu-btn { width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center; background: transparent; border: 0; color: var(--fg); cursor: pointer; }
.cv-nav__burger, .cv-nav__burger::before { display: block; width: 22px; height: 2px; background: currentColor; position: relative; }
.cv-nav__burger::before { content: ""; position: absolute; top: -7px; left: 0; box-shadow: 0 14px 0 currentColor; }
.cv-nav__menu-btn[aria-expanded="true"] .cv-nav__burger { background: transparent; }
@media (min-width: 1024px) {
  .cv-nav__links { display: flex; }
  .cv-nav__lang { display: block; }
  .cv-nav__menu-btn { display: none; }
}

.cv-lang { display: inline-flex; align-items: center; gap: 6px; }
.cv-lang__btn { background: transparent; border: 0; text-decoration: none; padding: 6px 4px; font: inherit; letter-spacing: inherit; color: var(--fg-3); cursor: pointer; transition: color .25s var(--ease-out); }
.cv-lang__btn.is-active { color: var(--accent); }
.cv-lang__btn:hover { color: var(--fg); }
.cv-lang__sep { color: var(--fg-3); }

.cv-menu { position: fixed; inset: 0; z-index: 60; background: var(--bg); display: flex; flex-direction: column; justify-content: center; gap: 40px; padding: 96px var(--gutter) 40px; overflow-y: auto; animation: fadeUp .4s var(--ease-out); }
.cv-menu__close { position: absolute; top: 20px; right: var(--gutter); background: transparent; border: 0; color: var(--fg-2); cursor: pointer; padding: 10px 0; }
.cv-menu__links { display: flex; flex-direction: column; gap: 12px; }
.cv-menu__link { color: var(--fg); text-decoration: none; }
@media (min-width: 1024px) { .cv-menu { display: none; } }

/* Hero. The pointer glow is accent at .12 at its centre: --fg-2 stays 7.5:1, --fg-3 5.2:1 on it. */
.cv-hero { position: relative; isolation: isolate; box-sizing: border-box; min-height: 100svh; padding-top: 72px; display: flex; flex-direction: column; overflow: clip; }
.cv-hero__glow { position: absolute; left: 0; top: 0; z-index: 0; width: 620px; height: 620px; margin: -310px 0 0 -310px; border-radius: 50%; background: radial-gradient(circle, var(--accent-a12), transparent 65%); opacity: 0; pointer-events: none; will-change: transform, opacity; }
.cv-hero__inner { position: relative; z-index: 1; flex: 1; display: grid; grid-template-columns: minmax(0, 1fr); align-content: center; gap: clamp(48px, 8vw, 72px); padding-block: clamp(24px, 4vh, 96px) clamp(24px, 3vh, 72px); }
.cv-hero__text { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }

.cv-hero__fade { animation: fadeUp .6s var(--ease-out) both; animation-delay: var(--d, 0s); }
.cv-hero__fade--slow { animation-duration: .7s; }

.cv-hero__title { margin-top: clamp(18px, 1.4vw, 40px); font-size: min(max(44px, 9vw), 11.6vw); }
.cv-hero__line { display: block; overflow: hidden; white-space: nowrap; padding: 0 .12em .1em 0; margin-bottom: -.1em; }
.cv-hero__line-inner { display: inline-block; animation: rise .9s var(--ease-out) both; animation-delay: var(--d, 0s); }

.cv-hero__desc { margin: clamp(20px, 1.8vw, 44px) 0 0; max-width: 34em; }
.cv-hero__actions { margin-top: clamp(28px, 2.4vw, 56px); display: flex; flex-direction: column; align-items: flex-start; gap: clamp(16px, 1.2vw, 28px); }
.cv-hero__cta { display: flex; flex-wrap: wrap; gap: 12px; }
.cv-hero__hint { color: var(--fg-2); font-size: clamp(14px, .3vw + 10px, 20px); text-decoration: underline; text-decoration-color: #3a3a3a; text-underline-offset: .3em; text-decoration-thickness: 1px; transition: color .25s var(--ease-out), text-decoration-color .25s var(--ease-out); }
.cv-hero__hint:hover { color: var(--fg); text-decoration-color: var(--fg); }

.cv-hero__scene { --phone-w: clamp(96px, 26vw, 180px); display: flex; justify-content: center; perspective: 1600px; padding-bottom: calc(var(--phone-w) * .24); }
.cv-hero__stage { display: flex; align-items: flex-start; justify-content: center; transform-style: preserve-3d; will-change: transform; }
.cv-hero__slot--left { transform: translateY(calc(var(--phone-w) * .2)) translateZ(-140px) rotateY(20deg); filter: brightness(.75); margin-right: calc(var(--phone-w) * -.14); }
.cv-hero__slot--center { position: relative; z-index: 2; transform: translateZ(60px) scale(1.16); }
.cv-hero__slot--right { transform: translateY(calc(var(--phone-w) * .24)) translateZ(-140px) rotateY(-20deg); filter: brightness(.75); margin-left: calc(var(--phone-w) * -.14); }
.cv-hero__enter { animation: phoneIn .9s var(--ease-out) both; animation-delay: var(--d, 0s); }
.cv-hero__float { display: flex; flex-direction: column; align-items: center; animation: floatA 7s ease-in-out infinite; animation-delay: var(--fd, 0s); }
.cv-hero__float--b { animation-name: floatB; }
.cv-hero .cv-phone { box-shadow: 0 40px 80px rgba(0, 0, 0, .6), inset 0 0 0 1px rgba(255, 255, 255, .08); }
.cv-hero__caption { margin-top: clamp(12px, 1.2vw, 28px); white-space: nowrap; }

.cv-hero__bar { position: relative; z-index: 1; display: flex; flex-wrap: wrap; align-items: center; gap: 14px clamp(24px, 3vw, 72px); padding-block: clamp(18px, 1.6vw, 36px); border-top: 1px solid var(--line); animation: fadeUp .6s var(--ease-out) 1.2s both; }
.cv-hero__names { display: flex; flex-wrap: wrap; gap: 6px clamp(20px, 2.4vw, 56px); }
.cv-hero__name { color: var(--fg-3); text-decoration: none; font-weight: 800; letter-spacing: -.02em; font-size: clamp(17px, .5vw + 12px, 32px); transition: color .25s var(--ease-out); }
.cv-hero__name:hover { color: var(--fg); }
.cv-hero__stats { margin-left: auto; display: flex; flex-wrap: wrap; align-items: center; gap: 8px clamp(14px, 1.4vw, 32px); }
.cv-hero__stat { color: var(--fg); font-weight: 600; font-size: clamp(14px, .3vw + 10px, 22px); }
.cv-hero__stat-sep { width: 1px; height: 1.1em; background: #333; }
@media (max-width: 767px) {
  .cv-hero__stats { margin-left: 0; flex-basis: 100%; }
}

@media (min-width: 1024px) {
  /* The text column never gets narrower than the longest headline line. */
  .cv-hero__inner { grid-template-columns: minmax(min-content, 45fr) minmax(0, 55fr); align-items: center; gap: clamp(24px, 3vw, 96px); }
  .cv-hero__title { font-size: clamp(44px, 6vw, 168px); }
  .cv-hero__scene { --phone-w: clamp(150px, 15vw, 340px); }
}

@media (prefers-reduced-motion: reduce) {
  .cv-hero__fade, .cv-hero__line-inner, .cv-hero__enter, .cv-hero__float, .cv-hero__bar { opacity: 1; transform: none; }
  .cv-hero__glow { display: none; }
}

/* Projects: one chapter per project (spec v3 4.3). Base = static stack in the final state (phone
   without motion, reduced motion). Desktop with motion = 300svh track with a CSS sticky stage.
   Layers read --p and the helper variables written by Projects.kt with default 1 (final state). */
.cv-projects { position: relative; padding-top: clamp(96px, 12vw, 240px); }
.cv-projects__head { display: flex; flex-direction: column; align-items: flex-start; gap: clamp(14px, 1.2vw, 28px); margin-bottom: clamp(48px, 6vw, 96px); }

[data-project="pepco"] { --c1: var(--pepco-a); --c2: var(--pepco-b); }
[data-project="zappka"] { --c1: var(--zappka); --c2: color-mix(in srgb, var(--zappka) 30%, #0a0a0a); }
[data-project="gigaset"] { --c1: var(--gigaset); --c2: color-mix(in srgb, var(--gigaset) 30%, #0a0a0a); }

.cv-chapter { position: relative; }
.cv-chapter__stage {
  --inline: max(var(--gutter), (100% - var(--frame-w)) / 2);
  position: relative;
  overflow: hidden;
  isolation: isolate;
  box-sizing: border-box;
  padding: clamp(56px, 10vw, 96px) var(--inline);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(32px, 6vw, 56px);
}
.cv-chapter__flood {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(ellipse 95% 70% at 50% 38%, var(--c1) 0%, color-mix(in srgb, var(--c1) 45%, #0a0a0a) 60%, var(--c2) 135%);
  opacity: var(--p-flood, 1);
  transform: scale(calc(.6 + .4 * var(--p-flood, 1)));
  transform-origin: 50% 38%;
}
.cv-chapter__title, .cv-chapter__side, .cv-chapter__next { display: none; }

.cv-chapter__progress { align-self: flex-start; display: flex; align-items: center; gap: clamp(12px, 1.2vw, 28px); padding: 10px 18px; border-radius: 999px; background: rgba(10, 10, 10, .88); }
.cv-chapter__counter { color: var(--fg-2); font-variant-numeric: tabular-nums; }
.cv-chapter__bar { position: relative; width: clamp(80px, 10vw, 280px); height: 2px; overflow: hidden; background: #2e2e2e; }
.cv-chapter__bar-fill { position: absolute; inset: 0; background: var(--accent); transform-origin: left; transform: scaleX(calc((var(--i) + var(--p, 1)) / var(--n))); }

.cv-chapter__scene { position: relative; display: flex; justify-content: center; }
.cv-chapter__phone { --phone-w: clamp(200px, 50vw, 300px); transform: scale(calc(.82 + .18 * var(--p-grow, 1))); }
.cv-chapter .cv-phone { box-shadow: 0 40px 80px rgba(0, 0, 0, .45), inset 0 0 0 1px rgba(255, 255, 255, .08); }

.cv-chapter__info { width: 100%; max-width: 40em; opacity: var(--p-info, 1); transform: translateY(calc((1 - var(--p-info, 1)) * 32px)); }
.cv-chapter__card { box-sizing: border-box; display: flex; flex-direction: column; align-items: flex-start; padding: clamp(24px, 2.6vw, 56px); border-radius: clamp(20px, 1.6vw, 36px); background: rgba(10, 10, 10, .9); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .07); }
.cv-chapter__id { display: flex; align-items: center; gap: clamp(14px, 1.2vw, 24px); }
.cv-chapter__icon { display: block; flex: none; width: 56px; height: 56px; border-radius: 14px; object-fit: cover; background: #1a1a1a; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08); }
.cv-chapter__name { font-size: clamp(28px, 2.4vw, 64px); }
.cv-chapter__owner { display: block; margin-top: 8px; }
.cv-chapter__facts { list-style: none; padding: 0; margin: clamp(20px, 1.8vw, 40px) 0 0; display: flex; flex-direction: column; gap: 4px; }
.cv-chapter__role { color: var(--fg); font-weight: 600; }
.cv-chapter__context { color: var(--fg-2); }
.cv-chapter__scale, .cv-chapter__tenure { color: var(--fg); margin-top: 10px; padding-left: 14px; border-left: 2px solid var(--c1); }
.cv-chapter__summary { margin: clamp(16px, 1.4vw, 32px) 0 0; color: var(--fg-2); }
.cv-chapter__stores { display: flex; flex-wrap: wrap; gap: 12px; margin-top: clamp(20px, 1.8vw, 40px); }
.cv-chapter__store { gap: .6em; padding: .75em 1.4em; }
.cv-chapter__store:hover { border-color: var(--fg); }
.cv-chapter__store .cv-icon { font-size: 1.1em; }

@media (min-width: 768px) {
  .cv-chapter__stage { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: clamp(40px, 6vw, 120px); row-gap: 32px; }
  .cv-chapter__progress { grid-column: 1 / -1; justify-self: start; }
  .cv-chapter__info { justify-self: start; }
}

/* Must match CHAPTER_DESKTOP_QUERY in Projects.kt. Below 700px height the card would not fit.
   scripting: enabled - without JS nothing scrubs, so the static chapters keep their normal height (no dead scroll). */
@media (min-width: 1024px) and (min-height: 700px) and (prefers-reduced-motion: no-preference) and (scripting: enabled) {
  /* Two viewports of scroll per chapter (ScrubEffect: top top .. bottom bottom). */
  .cv-chapter { height: 300svh; }
  .cv-chapter__stage {
    --teaser-h: clamp(64px, 11svh, 160px);
    --dock-x: calc(-1 * min(22vw, var(--frame-w) * .25));
    position: sticky;
    top: 0;
    display: block;
    height: 100svh;
    padding: 0;
  }
  .cv-chapter__flood {
    inset: -10%;
    background: radial-gradient(circle at 50% 50%, var(--c1) 0%, color-mix(in srgb, var(--c1) 55%, #0a0a0a) 42%, var(--c2) 90%);
    transform: scale(calc(.15 + .85 * var(--p-flood, 1)));
    transform-origin: 50% 50%;
  }
  .cv-chapter__title {
    display: flex;
    position: absolute;
    inset: 0;
    z-index: 0;
    align-items: center;
    justify-content: center;
    padding-inline: var(--gutter);
    text-align: center;
    /* One line, sized to fit: --chars is the name length; .68em per uppercase glyph covers Inter Tight 800
       at -.05em plus the 1.06 end scale, so "Gigaset Elements" never wraps under the header. */
    white-space: nowrap;
    text-transform: uppercase;
    font-weight: 800;
    font-size: min(15vw, 30svh, (100vw - 2 * var(--gutter)) / (var(--chars, 8) * .68));
    line-height: .86;
    letter-spacing: -.05em;
    color: var(--fg);
    /* The ghost fades out completely while the details card comes in, so it never shows behind the card. */
    opacity: calc((1 - .82 * var(--p-title, 1)) * (1 - var(--p-info, 1)));
    transform: translateY(calc(-28svh * var(--p-title, 1))) scale(calc(1 + .06 * var(--p-title, 1)));
    pointer-events: none;
  }
  .cv-chapter__scene { position: absolute; inset: 0; z-index: 1; align-items: center; pointer-events: none; }
  .cv-chapter__scene, .cv-chapter__phone { --phone-w: clamp(220px, min(21vw, 34svh), 640px); }
  .cv-chapter__phone {
    position: relative;
    z-index: 2;
    transform: translateX(calc(var(--dock-x) * var(--p-dock, 1))) scale(calc(.55 + .45 * var(--p-grow, 1)));
    will-change: transform;
  }
  /* The side screens dock together with the main phone: the fan closes into a tighter stack behind it
     (offset .92 to .42 phone widths, tilt 8 to 6deg) and stays fully visible next to the details card. */
  .cv-chapter__side {
    --s: -1;
    display: block;
    position: absolute;
    left: 50%;
    top: 50%;
    opacity: var(--p-fan, 1);
    transform:
      translate(-50%, -50%)
      translateX(calc(var(--s) * var(--phone-w) * (.92 - .5 * var(--p-dock, 1)) * var(--p-fan, 1) + var(--dock-x) * var(--p-dock, 1)))
      translateY(calc(var(--phone-w) * .08 * var(--p-fan, 1)))
      rotate(calc(var(--s) * (8deg - 2deg * var(--p-dock, 1)) * var(--p-fan, 1)))
      scale(calc(.84 - .06 * var(--p-dock, 1)));
    will-change: transform, opacity;
  }
  .cv-chapter__side--right { --s: 1; }
  .cv-chapter__progress { position: absolute; z-index: 5; top: calc(72px + clamp(12px, 1.4vw, 32px)); left: var(--inline); }
  .cv-chapter__info {
    position: absolute;
    z-index: 3;
    top: 72px;
    bottom: var(--teaser-h);
    right: var(--inline);
    width: min(40em, 44%);
    max-width: none;
    display: flex;
    align-items: center;
    transform: translateX(calc((1 - var(--p-info, 1)) * 80px));
  }
  .cv-chapter__next {
    display: flex;
    position: absolute;
    z-index: 4;
    left: 0;
    right: 0;
    bottom: 0;
    height: var(--teaser-h);
    align-items: center;
    justify-content: center;
    gap: .9em;
    background: var(--c1);
    color: var(--accent-ink);
    border-radius: 50% 50% 0 0 / 70% 70% 0 0;
    transform: translateY(calc((1 - var(--p-next, 1)) * 100%));
  }
  .cv-chapter__next-label { color: var(--accent-ink); }
  .cv-chapter__next-name { font-weight: 800; letter-spacing: -.03em; font-size: clamp(20px, 1.8vw, 56px); }
}

/* Keyboard and screen reader focus inside a chapter shows the whole scene in its final state
   (the same variable list as the "Final state" block at the end of the file). */
.cv-chapter:focus-within .cv-chapter__stage {
  --p: 1 !important; --p-title: 1 !important; --p-grow: 1 !important; --p-flood: 1 !important;
  --p-fan: 1 !important; --p-dock: 1 !important; --p-info: 1 !important; --p-next: 1 !important;
}

/* Quality: frame-time chart, principles, facts */
.cv-quality { position: relative; overflow: hidden; }
.cv-quality .cv-grid-bg { z-index: 0; }
.cv-quality .cv-container { position: relative; z-index: 1; }
.cv-quality__top { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(40px, 6vw, 72px); align-items: center; }
.cv-quality__text { display: flex; flex-direction: column; align-items: flex-start; gap: clamp(14px, 1.2vw, 28px); min-width: 0; }
.cv-quality__lead { margin: 0; max-width: 34em; }
/* Frame-time chart: scroll-driven. Defaults (no --c / --lb / --la) are the final "after" state. */
.cv-fc { position: relative; margin-top: clamp(40px, 5vw, 96px); }
.cv-fc__title { margin: 0; font-size: clamp(28px, 4.4vw, 88px); font-weight: 800; letter-spacing: -.035em; line-height: 1; }
.cv-fc__states { display: grid; margin-top: clamp(14px, 1.4vw, 28px); min-height: 3.2em; }
.cv-fc__state { grid-area: 1 / 1; margin: 0; font-size: clamp(15px, 1.2vw, 30px); line-height: 1.4; max-width: 40em; }
.cv-fc__state--before { color: var(--danger-ink); opacity: var(--lb, 0); }
.cv-fc__state--after { color: var(--fg); opacity: var(--la, 1); }
.cv-fc__axis-title { margin-top: clamp(14px, 1.6vw, 32px); font-size: 12px; color: var(--fg-3); letter-spacing: .08em; text-transform: uppercase; }
.cv-fc__frame { --plot-h: clamp(220px, calc(100svh - 400px), 640px); position: relative; margin-top: 12px; padding-left: clamp(28px, 3vw, 56px); height: var(--plot-h); }
.cv-fc__ticks { position: absolute; left: 0; top: 0; bottom: 0; width: clamp(28px, 3vw, 56px); }
.cv-fc__tick { position: absolute; left: 0; transform: translateY(50%); font-size: 11px; color: var(--fg-3); }
.cv-fc__plot { position: relative; height: 100%; border-bottom: 1px solid #333; }
.cv-fc__grid { position: absolute; left: 0; right: 0; height: 1px; background: var(--line); }
.cv-fc__bars { position: absolute; inset: 0; display: flex; align-items: stretch; gap: clamp(2px, .5vw, 12px); }
.cv-fc__bar { flex: 1 1 0; min-width: 0; position: relative; transform-origin: bottom; transform: scaleY(var(--s, 1)); will-change: transform; }
.cv-fc__fill { position: absolute; inset: 0; }
.cv-fc__fill--before { background: #5d5d59; opacity: calc(1 - var(--c, 1)); }
/* Over-budget bars: a red layer whose opacity (--hot, written per frame) is 1 only while the bar is above the line. */
.cv-fc__fill--before.is-over::after { content: ""; position: absolute; inset: 0; background: var(--danger); opacity: var(--hot, 1); }
.cv-fc__fill--after { background: var(--accent); opacity: var(--c, 1); }
.cv-fc__budget { position: absolute; left: 0; right: 0; height: 0; border-top: 2px dashed var(--accent); z-index: 2; pointer-events: none; }
/* Phone: a legend at the top right, above the plot (the bars reach almost to the top), with a dashed swatch.
   --at is the budget height as a fraction of the axis (written next to the line's bottom). */
.cv-fc__budget-label { position: absolute; right: 0; bottom: calc(var(--plot-h) * (1 - var(--at, .46)) + 8px); display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; color: var(--accent); font-size: clamp(12px, .9vw, 20px); font-weight: 600; }
.cv-fc__budget-label::before { content: ""; width: 18px; border-top: 2px dashed var(--accent); }
@media (min-width: 768px) {
  .cv-fc__frame { padding-left: clamp(64px, 5vw, 110px); }
  .cv-fc__ticks { width: clamp(64px, 5vw, 110px); }
  .cv-fc__budget-label { right: 100%; bottom: auto; top: 0; transform: translateY(-50%); margin-right: 10px; }
  .cv-fc__budget-label::before { display: none; }
}
.cv-fc__caption { margin: 16px 0 0; font-size: clamp(13px, .9vw, 20px); color: var(--fg-3); }
.cv-quality__lower { margin-top: clamp(64px, 8vw, 140px); display: flex; flex-direction: column; gap: clamp(40px, 5vw, 96px); }
.cv-quality__principles { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: minmax(0, 1fr); border: 1px solid var(--line); }
.cv-quality__principle { padding: clamp(24px, 2.4vw, 56px); border-bottom: 1px solid var(--line); background: var(--surface); }
.cv-quality__principle:last-child { border-bottom: 0; }
.cv-quality__principle-title { margin: 0; font-size: clamp(20px, 1.6vw, 40px); font-weight: 700; letter-spacing: -.02em; }
.cv-quality__principle-text { margin: 12px 0 0; color: var(--fg-2); }
.cv-quality__stats { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 3vw, 64px); }
@media (min-width: 768px) {
  .cv-quality__principles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cv-quality__principle { border-bottom: 1px solid var(--line); }
  .cv-quality__principle:nth-child(odd) { border-right: 1px solid var(--line); }
  .cv-quality__principle:nth-last-child(-n+2) { border-bottom: 0; }
  .cv-quality__stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.cv-quality__title .cv-serif-accent { display: block; }

/* AI in practice: a scroll-driven pipeline (AI writes, Review, Tests, Store) with the role split, then two layers.
   Scene variables (--bar, --open, --store, --a0..3, --m0..3, --c0..4) default to 1 = final state. */
.cv-ai { position: relative; overflow: clip; }
.cv-ai .cv-grid-bg { z-index: 0; }
.cv-ai .cv-container { position: relative; z-index: 1; }
.cv-ai__head { display: flex; flex-direction: column; align-items: flex-start; gap: clamp(14px, 1.2vw, 28px); }
.cv-ai__title .cv-serif-accent { display: block; }
.cv-ai__lead { margin: 0; max-width: 34em; }

.cv-ai-scene { position: relative; margin-top: clamp(48px, 6vw, 112px); }
.cv-ai-flow { display: flex; flex-direction: column; }

/* Pipeline. Phone: rows of equal height on a vertical rail, so each node sits at (k - .5) / 4 of the rail. */
.cv-ai-pipe { --rail: 32px; position: relative; }
.cv-ai-steps { list-style: none; margin: 0; padding: 0 0 0 var(--rail); display: grid; grid-auto-rows: 1fr; }
.cv-ai-step {
  --on: 1;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  padding: 18px 0 18px 16px;
  border-bottom: 1px solid var(--line);
}
.cv-ai-step:last-child { border-bottom: 0; }
/* Desktop only: an accent line on top of each lit stage (the phone has the rail for that). */
.cv-ai-step::before {
  content: "";
  display: none;
  position: absolute;
  top: -1px;
  left: -1px;
  right: -1px;
  height: 2px;
  background: var(--accent);
  transform: scaleX(var(--on));
  transform-origin: left;
  transition: transform .5s var(--ease-out);
}
.cv-ai-step__num { font-size: 12px; color: color-mix(in srgb, var(--accent) calc(var(--on) * 100%), var(--fg-3)); }
.cv-ai-step__tag { color: inherit; }
.cv-ai-step__title { margin: 0; font-size: clamp(20px, 1.5vw, 44px); font-weight: 700; letter-spacing: -.02em; line-height: 1.15; color: color-mix(in srgb, var(--fg) calc(var(--on) * 100%), var(--fg-3)); }
.cv-ai-step__text { margin: 0; font-size: clamp(14px, .3vw + 11px, 22px); line-height: 1.5; color: color-mix(in srgb, var(--fg-2) calc(var(--on) * 100%), var(--fg-3)); }
/* Review (while the panel is open) and Store (once shipped) get the accent ring. */
.cv-ai-step[data-k="2"]::after, .cv-ai-step[data-k="4"]::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px var(--accent), 0 0 48px -8px var(--accent-glow);
  opacity: var(--open, 1);
}
.cv-ai-step[data-k="4"]::after { opacity: var(--store, 1); }

/* Not lit yet: only while a scrub is bound (desktop: on the stage, phone: on the pipeline), never with focus inside. */
.cv-ai-scene:not(:focus-within) [data-scrub][data-lit="1"] :is([data-k="2"], [data-k="3"], [data-k="4"]),
.cv-ai-scene:not(:focus-within) [data-scrub][data-lit="2"] :is([data-k="3"], [data-k="4"]),
.cv-ai-scene:not(:focus-within) [data-scrub][data-lit="3"] [data-k="4"] { --on: 0; }

.cv-ai-track { position: absolute; left: calc(var(--rail) / 2 - 1px); top: 0; bottom: 0; width: 2px; background: #2a2a2a; }
.cv-ai-track__fill { position: absolute; inset: 0; background: var(--accent); transform: scaleY(var(--bar, 1)); transform-origin: top; will-change: transform; }
.cv-ai-track__node {
  --on: 1;
  position: absolute;
  left: 50%;
  top: calc((var(--k) - .5) * 25%);
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--bg);
  box-shadow: inset 0 0 0 2px #3a3a3a;
  transform: translate(-50%, -50%);
}
.cv-ai-track__node::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 18px var(--accent-glow);
  transform: scale(var(--on));
  transition: transform .45s var(--ease-out);
}
.cv-ai-track__run { position: absolute; inset: 0; transform: translateY(calc(var(--bar, 1) * 100%)); will-change: transform; opacity: calc(1 - var(--store, 1)); }
.cv-ai-track__head { position: absolute; left: 50%; top: 0; width: 10px; height: 10px; border-radius: 50%; background: var(--fg); box-shadow: 0 0 0 4px var(--accent-a45), 0 0 28px 6px var(--accent-glow); transform: translate(-50%, -50%); }
.cv-ai-track__drop { display: none; }

/* Review panel. Wide screens: the whole panel unfolds from the top with clip-path. Phone: the panel is
   taller than the screen, so its accent edge draws in and the AI column unfolds; the other blocks animate their items. */
.cv-ai-panel {
  position: relative;
  margin-top: clamp(24px, 3vw, 40px);
  border: 1px solid var(--line);
  background: var(--surface);
}
.cv-ai-panel::before { content: ""; position: absolute; z-index: 2; top: -1px; left: -1px; right: -1px; height: 2px; background: var(--accent); transform: scaleX(var(--open, 1)); transform-origin: left; }
.cv-ai-col--ai { clip-path: inset(0 0 calc((1 - var(--open, 1)) * 100%) 0); }
.cv-ai-panel__cols { display: grid; grid-template-columns: minmax(0, 1fr); }
.cv-ai-col { position: relative; padding: clamp(20px, 2vw, 48px); min-width: 0; }
.cv-ai-col__title { position: relative; margin: 0 0 clamp(12px, 1vw, 24px); font-size: 12px; font-weight: 500; }
.cv-ai-col__list { position: relative; list-style: none; margin: 0; padding: 0; display: grid; grid-auto-rows: 1fr; }
.cv-ai-col__item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 2.6em;
  border-top: 1px solid var(--line);
  font-size: clamp(16px, .45vw + 11px, 28px);
  line-height: 1.3;
}
/* The row lines stay put; only the content of each row moves in. */
.cv-ai-col__row { position: relative; display: flex; align-items: center; gap: 14px; opacity: var(--s, 1); }
.cv-ai-col__row::before { content: ""; flex: none; width: 8px; height: 8px; }
.cv-ai-col--ai .cv-ai-col__item { color: #cfcfca; }
.cv-ai-col--ai .cv-ai-col__row { transform: translateX(calc((1 - var(--s, 1)) * -48px)); }
.cv-ai-col--ai .cv-ai-col__row::before { background: #3a3a3a; }
/* "What I do": slower, one by one, each item flares with the accent as it lands. */
.cv-ai-col--me { --me-ink: #9aa4ff; border-top: 1px solid var(--line); box-shadow: inset 2px 0 0 var(--accent); }
.cv-ai-col--me::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(90deg, var(--accent-a14), var(--accent-a03) 70%);
  opacity: var(--m0, 1);
}
.cv-ai-col--me .cv-ai-col__title { color: var(--me-ink); } /* >= 7:1 on the tinted column; plain accent would drop below 4.5:1 */
.cv-ai-col--me .cv-ai-col__item { color: var(--fg); font-weight: 600; }
.cv-ai-col--me .cv-ai-col__row { transform: translateY(calc((1 - var(--s, 1)) * 18px)); }
.cv-ai-col--me .cv-ai-col__row::before { border-radius: 50%; background: var(--accent); box-shadow: 0 0 14px 2px var(--accent-glow); transform: scale(var(--s, 1)); }
.cv-ai-col--me .cv-ai-col__row::after {
  content: "";
  position: absolute;
  inset: -10px -16px;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(ellipse 60% 90% at 12% 50%, var(--accent-a50), transparent 70%);
  opacity: calc(var(--s, 1) * (1 - var(--s, 1)) * 4);
}
.cv-ai-col--me .cv-ai-col__list { isolation: isolate; }

.cv-ai-catches { padding: clamp(20px, 2vw, 48px); border-top: 1px solid var(--line); }
.cv-ai-catches__title { margin: 0 0 clamp(12px, 1vw, 24px); font-size: 12px; font-weight: 500; }
.cv-ai-catches__list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; }
.cv-ai-chip {
  padding: .5em 1.05em;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: var(--accent-a12);
  color: var(--fg);
  font-size: clamp(14px, .3vw + 11px, 22px);
  line-height: 1.2;
  opacity: var(--s, 1);
  transform: translateY(calc((1 - var(--s, 1)) * -18px)) scale(calc(.6 + .4 * var(--s, 1)));
  position: relative;
}
/* Pop glow: a fixed shadow whose opacity peaks while the chip lands (no animated box-shadow). */
.cv-ai-chip::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: 0 0 32px 4px var(--accent-a60);
  opacity: calc(var(--s, 1) * (1 - var(--s, 1)) * 4);
}

@media (min-width: 768px) {
  .cv-ai-panel__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cv-ai-col--me { border-top: 0; }
}

/* Desktop: the stages in one row, the bar under them with each node at the middle of its column. */
@media (min-width: 1024px) {
  .cv-ai-pipe { --gap: clamp(28px, 3vw, 56px); padding-bottom: var(--gap); }
  .cv-ai-steps { grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-rows: auto; padding: 0; border: 1px solid var(--line); background: var(--surface); }
  .cv-ai-step { justify-content: flex-start; gap: clamp(8px, .6vw, 14px); padding: clamp(20px, 1.8vw, 44px); border-bottom: 0; border-left: 1px solid var(--line); }
  .cv-ai-step:first-child { border-left: 0; }
  .cv-ai-step::before { display: block; }
  .cv-ai-step__num { font-size: clamp(11px, .25vw + 8px, 16px); }
  .cv-ai-track { position: relative; left: 0; top: auto; bottom: auto; width: auto; height: 4px; margin-top: clamp(20px, 2vw, 40px); border-radius: 2px; }
  .cv-ai-track__fill { transform: scaleX(var(--bar, 1)); transform-origin: left; border-radius: 2px; }
  .cv-ai-track__node { top: 50%; left: calc((var(--k) - .5) * 25%); width: 18px; height: 18px; }
  .cv-ai-track__run { transform: translateX(calc(var(--bar, 1) * 100%)); }
  .cv-ai-track__head { left: 0; top: 50%; }
  .cv-ai-track__drop { display: block; position: absolute; left: calc(37.5% - 1px); top: 100%; width: 2px; height: calc(var(--gap) + clamp(24px, 3vw, 40px)); background: var(--accent); transform: scaleY(var(--open, 1)); transform-origin: top; }
  .cv-ai-panel { clip-path: inset(0 0 calc((1 - var(--open, 1)) * 100%) 0); transform: translateY(calc((1 - var(--open, 1)) * -24px)); }
  .cv-ai-col--ai { clip-path: none; }
  .cv-ai-panel::before { left: 25%; right: auto; width: 25%; transform: scaleX(var(--open, 1)); }
  .cv-ai-catches { display: flex; align-items: center; gap: clamp(16px, 2vw, 48px); }
  .cv-ai-catches__title { margin: 0; flex: none; }
}

/* Must match CHAPTER_DESKTOP_QUERY (incl. scripting: enabled): 250svh track, the stage sticks for 150svh of scroll. */
@media (min-width: 1024px) and (min-height: 700px) and (prefers-reduced-motion: no-preference) and (scripting: enabled) {
  .cv-ai-scene { height: 250svh; }
  .cv-ai-stage { position: sticky; top: 0; box-sizing: border-box; height: 100svh; padding-top: 72px; display: flex; align-items: center; }
  .cv-ai-flow { width: min(100% - 2 * var(--gutter), var(--frame-w)); }
}

.cv-ai__layers { margin-top: clamp(64px, 8vw, 140px); display: grid; grid-template-columns: minmax(0, 1fr); border: 1px solid var(--line); }
.cv-ai__layer { padding: clamp(24px, 2.8vw, 64px); background: var(--surface); border-bottom: 1px solid var(--line); min-width: 0; }
.cv-ai__layer:last-child { border-bottom: 0; }
.cv-ai__layer-title { margin: 0 0 clamp(20px, 2vw, 40px); color: var(--fg); font-weight: 500; }
.cv-ai__tools, .cv-ai__facts { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: clamp(16px, 1.4vw, 32px); }
.cv-ai__tool { display: flex; flex-direction: column; gap: 4px; }
.cv-ai__tool-name { color: var(--fg); font-size: clamp(15px, .5vw + 11px, 24px); }
.cv-ai__tool-text { margin: 0; color: var(--fg-2); }
.cv-ai__facts li { padding-left: 16px; border-left: 1px solid var(--line); color: var(--fg-2); }
.cv-ai__closing { margin: clamp(24px, 2.4vw, 56px) 0 0; font-size: clamp(20px, 1.6vw, 40px); font-weight: 700; letter-spacing: -.02em; line-height: 1.25; }
@media (min-width: 1024px) {
  .cv-ai__layers { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cv-ai__layer { border-bottom: 0; }
  .cv-ai__layer:first-child { border-right: 1px solid var(--line); }
}

/* Experience: company cards on one scroll-drawn accent axis, sticky year counter on desktop */
/* The cards slide in from the side (translateX): clip them so they never widen the page (as .cv-collab). clip, not hidden, keeps sticky working. */
.cv-exp { overflow-x: clip; }
.cv-exp__head { display: flex; flex-direction: column; align-items: flex-start; gap: clamp(14px, 1.2vw, 28px); margin-bottom: clamp(40px, 5vw, 96px); }
.cv-exp__counter { display: none; }
.cv-exp__tl { --rail: 28px; --pad: clamp(18px, 1.8vw, 44px); --dot: 14px; position: relative; padding-left: var(--rail); }
.cv-exp__axis { position: absolute; left: calc(var(--rail) / 2 - 1px); top: 0; bottom: 0; width: 2px; background: #2a2a2a; }
.cv-exp__fill { position: absolute; inset: 0; background: var(--accent); transform-origin: top; }
.cv-exp__run { position: absolute; inset: 0; display: none; }
.cv-exp__head-dot { position: absolute; left: 50%; top: 0; width: 8px; height: 8px; border-radius: 50%; background: var(--fg); box-shadow: 0 0 0 4px var(--accent-a45), 0 0 24px 6px var(--accent-glow); transform: translate(-50%, -50%); }
.cv-exp__jobs { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: clamp(20px, 2vw, 48px); }

.cv-exp__card { position: relative; padding: var(--pad); }
.cv-exp__card::before { content: ""; position: absolute; inset: 0; border: 1px solid var(--line); border-radius: 16px; pointer-events: none; }
.cv-exp__card--current::before { border-color: var(--accent-a45); }
.cv-exp__card-head { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }
.cv-exp__logo { display: block; flex: none; width: 40px; height: 40px; object-fit: contain; border-radius: 8px; filter: grayscale(1); }
.cv-exp__logo--invert { filter: grayscale(1) invert(1); }
.cv-exp__company { margin: 0; font-size: clamp(20px, 1.4vw, 36px); font-weight: 700; letter-spacing: -.01em; line-height: 1.2; }
.cv-exp__name { color: var(--fg); text-decoration: none; }
.cv-exp__name:hover { text-decoration: underline; text-underline-offset: 4px; }
.cv-exp__span { flex-basis: 100%; color: var(--fg-3); }

.cv-exp__ms-list { list-style: none; margin: clamp(16px, 1.4vw, 32px) 0 0; padding: 0; display: flex; flex-direction: column; gap: clamp(14px, 1.2vw, 28px); }
.cv-exp__ms { position: relative; }
/* The point sits on the axis: back across the card padding and half the rail. */
.cv-exp__dot { position: absolute; z-index: 1; top: calc(.75em - var(--dot) / 2); left: calc(-1 * (var(--pad) + var(--rail) / 2 + var(--dot) / 2)); width: var(--dot); height: var(--dot); border-radius: 50%; background: var(--bg); border: 2px solid #3a3a3a; }
.cv-exp__dot::before { content: ""; position: absolute; inset: -2px; border-radius: 50%; background: var(--accent); transform: scale(1); transition: transform .45s var(--ease-out); }
.cv-exp__dot--pulse::after { content: ""; position: absolute; inset: -2px; border-radius: 50%; border: 2px solid var(--accent); opacity: 0; animation: cvExpPulse 1.8s var(--ease-out) infinite; }
@keyframes cvExpPulse { 0% { transform: scale(1); opacity: .9; } 100% { transform: scale(2.6); opacity: 0; } }
.cv-exp__ms-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; }
.cv-exp__period { color: var(--fg-3); line-height: 1.5; }
.cv-exp__ms--current .cv-exp__period { color: var(--accent); }
.cv-exp__role { margin: 0; color: var(--fg); font-weight: 600; font-size: clamp(17px, 1.1vw, 28px); line-height: 1.35; }
.cv-exp__role-end { white-space: nowrap; }
.cv-exp__now { display: inline-block; margin-left: 4px; padding: 2px 8px; border: 1px solid currentColor; border-radius: 999px; color: var(--accent); font-size: 11px; vertical-align: .15em; }
.cv-exp__note { margin: 2px 0 0; color: var(--fg-2); font-size: clamp(14px, .3vw + 11px, 20px); }
.cv-exp__summary { position: relative; margin: clamp(16px, 1.4vw, 32px) 0 0; color: var(--fg-2); max-width: 44em; }

/* Scrubbed: the line draws and every part slides in from the side once the line reaches its point.
   Gated by scripting: the static export snapshots data-scrub, --p and the flags, and no-JS must show the final state. */
@media (scripting: enabled) {
  .cv-exp__fill { transform: scaleY(var(--p, 1)); will-change: transform; }
  .cv-exp__tl[data-scrub] .cv-exp__run { display: block; transform: translateY(calc(var(--p, 1) * 100%)); will-change: transform; }
  .cv-exp__card::before, .cv-exp__card-head, .cv-exp__ms-body, .cv-exp__summary { transition: opacity .6s var(--ease-out), transform .6s var(--ease-out); }
  .cv-exp__tl[data-scrub]:not(:focus-within) .cv-exp__card:not([data-on])::before { opacity: 0; transform: translateX(32px); }
  .cv-exp__tl[data-scrub]:not(:focus-within) .cv-exp__card:not([data-on]) .cv-exp__card-head,
  .cv-exp__tl[data-scrub]:not(:focus-within) .cv-exp__ms:not([data-on]) .cv-exp__ms-body,
  .cv-exp__tl[data-scrub]:not(:focus-within) .cv-exp__card:not([data-done]) .cv-exp__summary { opacity: 0; transform: translateX(56px); }
  .cv-exp__tl[data-scrub]:not(:focus-within) .cv-exp__ms:not([data-on]) .cv-exp__dot::before { transform: scale(0); }
  .cv-exp__tl[data-scrub]:not(:focus-within) .cv-exp__ms:not([data-on]) .cv-exp__dot--pulse::after { animation: none; }
}
@media (min-width: 1024px) {
  .cv-exp__tl { --rail: 40px; --dot: 16px; }
  .cv-exp__span { flex-basis: auto; margin-left: auto; }
  .cv-exp__ms-body { grid-template-columns: clamp(150px, 16vw, 320px) minmax(0, 1fr); gap: 0 clamp(20px, 2vw, 48px); align-items: baseline; }
}
/* Desktop scene: counter column on the left, sticky in the middle of the viewport. */
@media (min-width: 1024px) and (min-height: 700px) and (prefers-reduced-motion: no-preference) {
  .cv-exp__layout { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: clamp(32px, 4vw, 120px); }
  .cv-exp__counter { display: block; }
  .cv-exp__yr { position: sticky; top: calc(50svh - .5em); height: 1em; overflow: hidden; font-size: clamp(112px, 11vw, 400px); font-weight: 800; line-height: 1; letter-spacing: -.06em; font-variant-numeric: tabular-nums; }
  .cv-exp__roll { display: flex; flex-direction: column; transform: translateY(calc(var(--yl) * -1em)); }
  @media (scripting: enabled) { .cv-exp__roll { transform: translateY(calc(var(--yi, var(--yl)) * -1em)); transition: transform .7s var(--ease-out); will-change: transform; } }
  .cv-exp__year { display: block; height: 1em; color: var(--fg); }
  .cv-exp__year--now { color: var(--accent); }
}
@media (prefers-reduced-motion: reduce) {
  .cv-exp__dot--pulse::after { animation: none; }
  .cv-exp__card::before, .cv-exp__card-head, .cv-exp__ms-body, .cv-exp__summary, .cv-exp__dot::before { transition: none; }
}

/* Collaboration */
.cv-collab__head { display: flex; flex-direction: column; align-items: flex-start; gap: clamp(14px, 1.2vw, 28px); margin-bottom: clamp(40px, 5vw, 96px); }
.cv-collab__head .cv-serif-accent { display: block; }
.cv-collab__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(16px, 2vw, 40px); }
.cv-collab { overflow-x: clip; }
.cv-collab__card { position: relative; isolation: isolate; display: flex; flex-direction: column; gap: clamp(14px, 1.2vw, 24px); padding: clamp(24px, 2.6vw, 64px); border: 1px solid var(--line); background: var(--surface); border-radius: 4px; min-width: 0; }
.cv-collab__card > * { position: relative; z-index: 1; }
.cv-collab__top { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.cv-collab__audience { color: var(--fg-2); padding-top: .2em; }
.cv-stroke-icon { flex: none; width: clamp(44px, 3.6vw, 96px); height: auto; aspect-ratio: 1; overflow: visible; }
.cv-stroke-icon__shape { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 0; }
.cv-collab__title { margin: 0; font-size: clamp(28px, 2.6vw, 64px); line-height: 1.05; font-weight: 800; letter-spacing: -.03em; color: var(--fg); }
.cv-collab__points { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; color: var(--fg-2); }
.cv-collab__points li { padding-block: 10px; border-top: 1px solid var(--line); }
.cv-collab__points li:last-child { border-bottom: 1px solid var(--line); }
.cv-collab__cta { margin-top: auto; padding-top: clamp(8px, 1vw, 24px); }
/* Spotlight: a fixed radial gradient whose centre follows --mx/--my (written on the card). Only its opacity changes.
   Peak alpha .16 keeps --fg-2 body text above 4.5:1 at the brightest point. */
.cv-collab__card::before { content: ""; position: absolute; inset: 0; z-index: 0; border-radius: inherit; pointer-events: none; opacity: 0; transition: opacity .35s var(--ease-out);
  background: radial-gradient(circle clamp(220px, 26vw, 520px) at var(--mx, 50%) var(--my, 50%), var(--accent-a16), transparent 70%); }
@media (hover: hover) and (pointer: fine) {
  .cv-collab__card { transition: border-color .35s var(--ease-out); }
  .cv-collab__card:hover { border-color: var(--accent-a55); }
  .cv-collab__card:hover::before { opacity: 1; }
}
/* One-shot entrance: hidden start only when scripts run and motion is allowed; otherwise everything is in its final state. */
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  .cv-collab__card { opacity: 0; transition: opacity .7s var(--ease-out), transform 1s var(--ease-out), border-color .35s var(--ease-out); }
  .cv-collab__card--left { transform: translateX(-60px) rotate(-3deg); }
  .cv-collab__card--right { transform: translateX(60px) rotate(3deg); }
  .cv-collab__card.is-in { opacity: 1; transform: none; }
  /* Keyboard focus reaches the CTA before the card is in view: show the card at once. */
  .cv-collab__card:focus-within, .cv-collab__card:focus-within .cv-collab__points li { opacity: 1; transform: none; transition: none; }
  .cv-collab__card:focus-within .cv-stroke-icon__shape { stroke-dashoffset: 0; opacity: 1; transition: none; }
  .cv-collab__points li { opacity: 0; transform: translateY(10px); transition: opacity .6s var(--ease-out), transform .6s var(--ease-out); }
  .cv-collab__card.is-in .cv-collab__points li { opacity: 1; transform: none; transition-delay: calc(.55s + var(--i, 0) * .14s); }
  .cv-collab__card .cv-stroke-icon__shape { stroke-dashoffset: 1; opacity: 0; transition: stroke-dashoffset 1.2s var(--ease-out), opacity .2s linear; }
  .cv-collab__card.is-in .cv-stroke-icon__shape { stroke-dashoffset: 0; opacity: 1; transition-delay: .35s; }
  .cv-collab__card.is-in .cv-stroke-icon__shape:nth-child(2) { transition-delay: .65s; }
  .cv-collab__card.is-in .cv-stroke-icon__shape:nth-child(3) { transition-delay: .9s; }
}
@media (min-width: 1024px) {
  .cv-collab__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; }
}

/* Contact: the finale. An ultramarine "sunset" rises from the bottom (opacity of a fixed gradient only),
   the one-line headline settles into place, the e-mail underline draws, the form slides in once. */
.cv-contact { position: relative; isolation: isolate; overflow: clip; }
.cv-contact__wash { position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(120% 80% at 50% 115%, var(--accent) 0%, #2a2f8f 30%, #0f1030 62%, var(--bg) 100%); }
.cv-contact__inner { display: flex; flex-direction: column; gap: clamp(40px, 5vw, 120px); }
/* Width container for the headline: the no-JS / first-paint size is the container width over the measured
   width-to-size ratio of the text (Inter Tight 800: "Porozmawiajmy." 7.13, "Let's talk." 4.08, plus a margin),
   so it is one line before any script runs. JS then refines it to the exact width (--fit). */
.cv-contact__fit { container-type: inline-size; min-width: 0; --fit-ratio: 7.4; }
:root:lang(en) .cv-contact__fit { --fit-ratio: 4.3; }
.cv-contact__headline { margin: 0; font-weight: 800; letter-spacing: -.05em; line-height: .95; padding-bottom: .08em;
  font-size: calc(100cqi / var(--fit-ratio)); white-space: nowrap; hyphens: none; -webkit-hyphens: none; overflow-wrap: normal; word-break: keep-all; text-wrap: nowrap; }
.cv-contact__headline-text { display: inline-block; white-space: nowrap; transform-origin: left bottom; }
.cv-contact__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(48px, 6vw, 140px); align-items: start; }
.cv-contact__intro { display: flex; flex-direction: column; gap: clamp(20px, 2vw, 40px); min-width: 0; }
.cv-contact__lead { margin: 0; max-width: 32em; color: var(--fg); }
.cv-contact__channels { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
/* Text on the wash uses light inks: --fg-2 would drop below 4.5:1 on the bright part of the gradient. */
.cv-contact__label { color: var(--contact-ink-2); }
.cv-contact { --contact-ink-2: #e2e3f4; }
.cv-contact__email { position: relative; color: var(--fg); font-weight: 700; letter-spacing: -.02em; font-size: clamp(18px, 2.4vw, 56px); line-height: 1.15; overflow-wrap: anywhere; text-decoration: none; padding-bottom: .12em; }
.cv-contact__email::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: max(2px, .06em); background: currentColor; transform-origin: left; transform: scaleX(1); }
.cv-contact__actions { display: flex; flex-wrap: wrap; gap: 12px; }
.cv-contact__actions .cv-btn { gap: .6em; }
.cv-contact .cv-btn--ghost { border-color: rgba(242, 242, 238, .55); }
/* The accent button sits on an accent-tinted wash: a light ring keeps its edge visible. */
.cv-contact .cv-btn--primary { box-shadow: 0 0 0 2px var(--fg); }
.cv-contact__copied { min-height: 1.5em; color: var(--contact-ink-2); font-size: clamp(14px, .3vw + 11px, 20px); }
.cv-contact__form { display: flex; flex-direction: column; gap: clamp(16px, 1.4vw, 32px); min-width: 0; }
.cv-contact__field { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.cv-contact__input { width: 100%; box-sizing: border-box; background: var(--surface); color: var(--fg); border: 1px solid #3a3a3a; border-radius: 4px; padding: .85em 1em; font: inherit; font-size: clamp(16px, .35vw + 12px, 22px); transition: border-color .25s var(--ease-out); }
.cv-contact__input::placeholder { color: var(--fg-3); }
.cv-contact__input:hover { border-color: #5a5a5a; }
.cv-contact__input:focus { border-color: var(--fg); }
.cv-contact__input:focus-visible { outline: 2px solid var(--fg); outline-offset: 2px; }
.cv-contact__input[aria-invalid="true"] { border-color: var(--fg-2); }
.cv-contact__textarea { resize: vertical; min-height: 9em; }
.cv-contact__error { min-height: 1.4em; color: var(--contact-ink-2); font-size: clamp(13px, .25vw + 10px, 18px); }
.cv-contact__submit .cv-btn[disabled] { opacity: .6; cursor: progress; transform: none; }
.cv-contact__status { min-height: 1.6em; color: var(--contact-ink-2); margin: 0; }
.cv-contact__status.is-error { color: var(--fg); }
@media (min-width: 1024px) {
  .cv-contact__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Scrubbed and one-shot states. Gated by scripting: the static export snapshots --p, --u, --fit and is-in,
   and no-JS must show the final state (full wash, fallback headline size, drawn underline, form in place). */
@media (scripting: enabled) {
  .cv-contact__headline { font-size: var(--fit, calc(100cqi / var(--fit-ratio))); }
  .cv-contact__wash { opacity: var(--p, 1); }
}
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  /* --p here is the headline's own scrub on the h2: scale and fade both finish when half of it is visible.
     Quadratic fade: the overflowing (clipped) frames stay faint. */
  .cv-contact__headline { opacity: calc(var(--p, 1) * var(--p, 1)); }
  .cv-contact__headline-text { transform: scale(calc(1 + (1 - var(--p, 1)) * .35)); will-change: transform; }
  .cv-contact__email::after { transform: scaleX(var(--u, 1)); }
  .cv-contact__email:hover::after, .cv-contact__email:focus-visible::after { transform: scaleX(1); transition: transform .3s var(--ease-out); }
  .cv-contact__intro { opacity: 0; transform: translateY(24px); transition: opacity .8s var(--ease-out), transform .8s var(--ease-out); }
  .cv-contact__form { opacity: 0; transform: translateX(72px); transition: opacity .8s var(--ease-out), transform 1s var(--ease-out); }
  .cv-contact__intro.is-in, .cv-contact__form.is-in, .cv-contact__intro:focus-within, .cv-contact__form:focus-within { opacity: 1; transform: none; }
}

/* About: scene (watermark, glow, cut-out portrait, statement) and the v2 copy under it */
.cv-about { padding-top: 0; }
.cv-about-scene { position: relative; isolation: isolate; box-sizing: border-box; min-height: 100svh; display: flex; align-items: flex-end; overflow: clip; }
/* Depth: with scroll the watermark drifts sideways and the portrait lifts (--p from ScrubEffect, .5 = neutral). */
.cv-about-scene__wm {
  --wm-y: -50%;
  position: absolute; z-index: 0; left: -6%; top: 30%; width: 112%; aspect-ratio: 1080 / 240.75;
  background: #fff; opacity: .05; pointer-events: none;
  -webkit-mask: url("/logo_white_simple.svg") center / contain no-repeat; mask: url("/logo_white_simple.svg") center / contain no-repeat;
  transform: translateY(var(--wm-y)) translateX(calc((var(--p, .5) - .5) * -10%)); will-change: transform;
}
.cv-about-scene__photo {
  position: absolute; z-index: 1; top: 72px; left: 50%; width: min(100%, 520px); margin-left: max(-50%, -260px);
  transform: translateY(calc((var(--p, .5) - .5) * -6%)); will-change: transform;
}
.cv-about-scene__photo img {
  position: relative; display: block; width: 100%; height: auto; aspect-ratio: 900 / 1457;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
}
/* Phones and tablets: the portrait covers the middle of the scene, so the watermark sits above the head,
   centred and brighter, and the portrait moves down by about its height. No text overlaps it. */
@media (max-width: 1023.98px) {
  .cv-about-scene { --wm-w: min(84vw, 480px); }
  .cv-about-scene__wm { --wm-y: 0%; left: calc((100% - var(--wm-w)) / 2); top: 88px; width: var(--wm-w); opacity: .14; }
  .cv-about-scene__photo { top: calc(72px + var(--wm-w) * .16); }
}
/* Fixed gradient; only opacity and transform pulse. */
.cv-about-scene__glow {
  position: absolute; left: 50%; top: 24%; width: 120%; aspect-ratio: 1; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, var(--accent-a55), var(--accent-a16) 38%, transparent 66%);
  opacity: .6; transform: translate(-50%, -50%) scale(.94); will-change: transform, opacity;
}
.cv-about-scene.is-in .cv-about-scene__glow { animation: cvAboutGlow 9s ease-in-out infinite; }
@keyframes cvAboutGlow {
  0%, 100% { opacity: .45; transform: translate(-50%, -50%) scale(.9); }
  50% { opacity: .95; transform: translate(-50%, -50%) scale(1.06); }
}
/* Bottom of the portrait melts into the page; on phones it also darkens the area behind the statement. */
.cv-about-scene__fade {
  position: absolute; z-index: 1; left: 0; right: 0; bottom: 0; height: 62%; pointer-events: none;
  background: linear-gradient(to bottom, rgba(10, 10, 10, 0), rgba(10, 10, 10, .88) 38%, var(--bg) 58%);
}
.cv-about-scene__content { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: flex-start; gap: clamp(16px, 1.4vw, 32px); padding-block: 96px clamp(40px, 6vh, 96px); }
.cv-about-statement { font-size: clamp(30px, 8.8vw, 48px); line-height: 1.04; text-wrap: initial; }
.cv-about-line { display: block; width: fit-content; }
/* Room for italic overhang and descenders inside the box (Safari clamps negative clip-path insets to the box),
   cancelled by negative margins so the text does not move. */
.cv-about-line { padding: .2em .35em .3em .35em; margin: -.2em -.35em -.3em -.35em; }
.cv-about-line .cv-serif-accent { font-size: 1.12em; line-height: .95; }
.cv-about-sig { display: flex; align-items: center; gap: clamp(8px, .6vw, 16px); margin: clamp(8px, 1.2vw, 28px) 0 0; }
/* The logo SVG carries empty space on its right (about one logo height); the negative margin keeps the gap to the divider even. */
.cv-about-sig { --logo-h: clamp(22px, 1.5vw, 40px); }
.cv-about-sig img { display: block; height: var(--logo-h) !important; width: auto; margin-right: calc(var(--logo-h) * -.9); }
.cv-about-sig__name { padding-left: clamp(12px, 1vw, 24px); border-left: 1px solid #3a3a3a; color: var(--fg-2); font-size: clamp(14px, .3vw + 11px, 22px); }
/* Line reveal: hidden start only when scripts run and motion is allowed; otherwise lines are simply there. */
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  /* Insets stay >= 0: the padding above already holds the italic overhang ("dobrych decyzji.") and the descenders. */
  .cv-about-line { clip-path: inset(0 100% 0 0); opacity: 0; transition: clip-path 1.1s var(--ease-out), opacity .5s var(--ease-out); transition-delay: calc(var(--i) * .25s + .1s); }
  .cv-about-scene.is-in .cv-about-line { clip-path: inset(0); opacity: 1; }
  .cv-about-sig { opacity: 0; transform: translateY(12px); transition: opacity .7s var(--ease-out) .9s, transform .7s var(--ease-out) .9s; }
  .cv-about-scene.is-in .cv-about-sig { opacity: 1; transform: none; }
}
.cv-about__body { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(32px, 4vw, 96px); margin-top: clamp(32px, 5vw, 120px); }
.cv-about__copy { display: flex; flex-direction: column; gap: 1em; max-width: 38em; }
.cv-about__copy .cv-lead { margin: 0; }
.cv-about__stack { display: flex; flex-direction: column; gap: 12px; }
.cv-about__stack > .cv-mono { color: var(--fg-2); }
/* Separator sits in the column gap before each item; the list clips its own left edge,
   so the first item on every wrapped line hides its "/" and no line ends with one. */
.cv-about__list { --sep-w: 2.2em; list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px var(--sep-w); overflow: hidden; color: var(--fg-2); }
.cv-about__list li { position: relative; }
.cv-about__list li::before { content: "/"; content: "/" / ""; position: absolute; right: 100%; width: var(--sep-w); text-align: center; color: var(--fg-3); }
@media (min-width: 1024px) {
  .cv-about-scene { align-items: center; }
  /* Bottom edge just above the scene centre: the watermark sits behind the eyebrow, the two white lines and the head,
     never behind the accent line (accent on the watermark tint would drop below 4.5:1). */
  .cv-about-scene__wm { --wm-y: -100%; top: calc(50% - 1.2vw); }
  /* Right edge aligned with the container; bottom starts below the scene so the lift never shows the cut edge. */
  .cv-about-scene__photo { top: auto; left: auto; bottom: -3%; margin-left: 0; right: max(var(--gutter), (100% - var(--frame-w)) / 2); width: auto; height: 96%; max-width: 44%; }
  .cv-about-scene__photo img { width: auto; height: 100%; max-width: 100%; object-fit: contain; object-position: bottom; }
  .cv-about-scene__fade { height: 30%; background: linear-gradient(to bottom, rgba(10, 10, 10, 0), var(--bg) 85%); }
  .cv-about-scene__content { padding-block: 120px; }
  .cv-about-statement { font-size: clamp(44px, 4.6vw, 128px); max-width: 56%; }
  /* The statement is centred in a full-height scene, so the scene's lower part is only the fading portrait.
     The body moves up into that fade instead of starting after it (about 100px below the signature) and stays
     in the left column under the statement (copy, then stack), so nothing sits on the portrait. */
  .cv-about__body { grid-template-columns: minmax(0, 54%); gap: clamp(28px, 2.4vw, 56px); position: relative; z-index: 3; margin-top: calc(-1 * clamp(80px, 28svh - 64px, 320px)); }
}
@media (prefers-reduced-motion: reduce) {
  .cv-about-scene__wm { transform: translateY(var(--wm-y)); }
  .cv-about-scene__photo { transform: none; }
  .cv-about-scene__glow { opacity: .7; }
}

/* Footer */
.cv-footer { border-top: 1px solid var(--line); padding-block: clamp(32px, 3.5vw, 72px); }
.cv-footer__inner { display: flex; flex-direction: column; gap: clamp(24px, 2.4vw, 48px); }
.cv-footer__top { display: flex; flex-direction: column; align-items: flex-start; gap: 24px; }
.cv-footer__logo { display: inline-flex; }
.cv-footer__logo img { display: block; }
.cv-footer__nav { display: flex; flex-wrap: wrap; gap: 4px 24px; }
.cv-footer__link { color: var(--fg-2); text-decoration: none; font-size: clamp(14px, .3vw + 11px, 20px); padding-block: 6px; transition: color .25s var(--ease-out); }
.cv-footer__link:hover { color: var(--fg); }
.cv-footer__copy { margin: 0; padding-top: clamp(20px, 2vw, 40px); border-top: 1px solid var(--line); color: var(--fg-2); text-transform: none; letter-spacing: .06em; }
@media (min-width: 1024px) {
  .cv-footer__top { flex-direction: row; align-items: center; justify-content: space-between; gap: 40px; }
}

/* Icons: CSS masks tinted with currentColor. Brand paths from Simple Icons (CC0). */
.cv-icon { display: inline-block; flex: none; width: 1em; height: 1em; background-color: currentColor; -webkit-mask: var(--icon) center / contain no-repeat; mask: var(--icon) center / contain no-repeat; }
@media (forced-colors: active) { .cv-icon { forced-color-adjust: none; background-color: CanvasText; } }
.cv-icon--google-play { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M22.018 13.298l-3.919 2.218-3.515-3.493 3.543-3.521 3.891 2.202a1.49 1.49 0 0 1 0 2.594zM1.337.924a1.486 1.486 0 0 0-.112.568v21.017c0 .217.045.419.124.6l11.155-11.087L1.337.924zm12.207 10.065l3.258-3.238L3.45.195a1.466 1.466 0 0 0-.946-.179l11.04 10.973zm0 2.067l-11 10.933c.298.036.612-.016.906-.183l13.324-7.54-3.23-3.21z'/%3E%3C/svg%3E"); }
.cv-icon--apple { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.220-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701'/%3E%3C/svg%3E"); }
.cv-icon--linkedin { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z'/%3E%3C/svg%3E"); }
.cv-icon--copy { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'%3E%3Crect x='8' y='8' width='13' height='13' rx='2'/%3E%3Cpath d='M16 8V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h3'/%3E%3C/g%3E%3C/svg%3E"); }

/* Final state: one convention for the whole page.
   - One-shot reveals keep their hidden start inside @media (scripting: enabled) and (prefers-reduced-motion: no-preference),
     so reduced motion and no-JS never hide anything.
   - Scrubbed scenes read var(--x, 1), 1 = final state. Under reduced motion (also when it is switched on while the page
     is open: GSAP reverts the trigger and the writers' inline values stay behind) and without JS (the static export
     snapshots the start values), every scrub variable is forced to its final value here, once per scene. */
@media (prefers-reduced-motion: reduce), (scripting: none) {
  [data-scrub] { --p: 1 !important; }
  .cv-chapter__stage {
    --p: 1 !important; --p-title: 1 !important; --p-grow: 1 !important; --p-flood: 1 !important;
    --p-fan: 1 !important; --p-dock: 1 !important; --p-info: 1 !important; --p-next: 1 !important;
  }
  .cv-ai-stage {
    --p: 1 !important; --bar: 1 !important; --open: 1 !important; --store: 1 !important;
    --a0: 1 !important; --a1: 1 !important; --a2: 1 !important; --a3: 1 !important;
    --m0: 1 !important; --m1: 1 !important; --m2: 1 !important; --m3: 1 !important;
    --c0: 1 !important; --c1: 1 !important; --c2: 1 !important; --c3: 1 !important; --c4: 1 !important;
  }
  .cv-fc { --c: 1 !important; --lb: 0 !important; --la: 1 !important; }
  .cv-fc__bar { --s: var(--s-end, 1) !important; }
}

/* Language suggestion banner. Client-only, fixed, so it causes no layout shift. Below the menu (60). */
.cv-langbar { position: fixed; left: var(--gutter); bottom: 16px; z-index: 55; box-sizing: border-box; max-width: min(420px, calc(100vw - 2 * var(--gutter))); display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; padding: 14px 44px 14px 16px; background: var(--surface); border: 1px solid var(--line); border-radius: 12px; color: var(--fg-2); font-size: 13px; line-height: 1.5; }
.cv-langbar__link { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; font-size: 13px; }
.cv-langbar__link:hover { color: var(--accent); }
.cv-langbar__close { position: absolute; top: 4px; right: 4px; width: 36px; height: 36px; background: transparent; border: 0; color: var(--fg-2); font-size: 18px; line-height: 1; cursor: pointer; }
.cv-langbar__close:hover { color: var(--fg); }
@media (prefers-reduced-motion: no-preference) {
  .cv-langbar { animation: fadeUp .4s var(--ease-out); }
}

/* Legal pages and footer legal line */
.cv-footer__bottom { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; padding-top: clamp(20px, 2vw, 40px); border-top: 1px solid var(--line); }
.cv-footer__bottom .cv-footer__copy { padding-top: 0; border-top: 0; }
.cv-footer__legal { padding-block: 6px; }
.cv-legal { padding-block: calc(72px + clamp(40px, 6vw, 120px)) clamp(64px, 8vw, 160px); }
.cv-legal__inner { max-width: 46rem; display: flex; flex-direction: column; align-items: flex-start; gap: clamp(12px, 1.2vw, 20px); }
.cv-legal__title { overflow-wrap: anywhere; }
.cv-legal__meta { margin: 0; }
.cv-legal__h { margin: clamp(20px, 2.4vw, 40px) 0 0; font-size: clamp(22px, 1.4vw + 14px, 36px); font-weight: 700; letter-spacing: -.02em; line-height: 1.15; }
.cv-legal__p { margin: 0; color: var(--fg-2); overflow-wrap: anywhere; }
.cv-legal__list { margin: 0; padding-left: 1.25em; color: var(--fg-2); display: flex; flex-direction: column; gap: 10px; overflow-wrap: anywhere; }
.cv-404__inner { display: flex; flex-direction: column; gap: clamp(20px, 3vw, 40px); align-items: center; text-align: center; min-height: 50vh; justify-content: center; }
.cv-404__code { margin: 0; font-size: clamp(96px, 22vw, 320px); line-height: 1; font-weight: 700; letter-spacing: -.04em; color: var(--fg-2); }
@media (min-width: 1024px) {
  .cv-footer__bottom { flex-direction: row; align-items: center; gap: 32px; }
}
