/* =========================================================
   Tokens
   ========================================================= */
:root {
  color-scheme: light;
  --bg: #f8f8f8;
  --black: #000;          /* strongest text (logo, name) — near-white in dark */
  --dark-2: #414141;      /* primary text / active */
  --grey: #808080;        /* secondary text */
  --line: rgba(0, 0, 0, 0.05);
  --separator: #c2c2c2;
  --fill: rgba(0, 0, 0, 0.05);          /* email pill */
  --fill-hover: rgba(0, 0, 0, 0.08);
  --fill-ring: rgba(0, 0, 0, 0.08);
  --inverse-fg: #fff;                   /* text on a var(--black) surface */
  --photo-bg: #ececec;
  --photo-border: rgba(0, 0, 0, 0.025); /* half the grid-line strength */
  --card-bg: #fff;                      /* Work cards */
  --label: #666;                        /* phone section labels */
  --figma-blue: #0091ff;
  --figma-label: #33aaff;

  --font: "SF Pro Display", -apple-system, BlinkMacSystemFont, "Inter", system-ui, "Segoe UI", Roboto, sans-serif;

  --shell-max: 1240px;
  --gutter: 32px;
  --shell: min(var(--shell-max), 100% - var(--gutter) * 2);
  --header-h: 80px;

  /* 6-column grid measured from the original: 212 | 204 ×4 | 212 */
  --cols: 212fr 204fr 204fr 204fr 204fr 212fr;

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Dark theme: light is the default; dark applies only when the visitor
   picks it with the header switch (data-theme="dark" on <html>, set by the
   inline script in <head> before first paint and by main.js). */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0f0f0f;
  --black: #f5f5f5;
  --dark-2: #c4c4c4;
  --grey: #9a9a9a;
  --active: #ececec;   /* current section link: almost white */
  --line: rgba(255, 255, 255, 0.07);
  --separator: #3a3a3a;
  --fill: rgba(255, 255, 255, 0.06);
  --fill-hover: rgba(255, 255, 255, 0.1);
  --fill-ring: rgba(255, 255, 255, 0.1);
  --inverse-fg: #0f0f0f;
  --photo-bg: #1c1c1c;
  --photo-border: rgba(255, 255, 255, 0.06);
  --card-bg: #161616;
  --label: #ababab;
}

/* =========================================================
   Base
   ========================================================= */
*,
*::before,
*::after { box-sizing: border-box; }

/* The page scrolls as usual, but without a visible scrollbar */
html { scrollbar-width: none; -ms-overflow-style: none; }
html::-webkit-scrollbar,
body::-webkit-scrollbar { display: none; width: 0; height: 0; }

html {
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;   /* no grey/blue flash on tap (iOS/Android) */
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-h);
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--black);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

p, h1, figure, ul { margin: 0; padding: 0; }
ul { list-style: none; }
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }

:focus-visible {
  outline: 2px solid var(--figma-blue);
  outline-offset: 3px;
  border-radius: 4px;
}
/* The focus ring is for keyboard users: after a tap or click (main.js
   sets .using-pointer until a key is pressed) it never shows */
.using-pointer :focus-visible,
.using-pointer *:focus-visible { outline: none !important; }

.shell {
  width: var(--shell);
  margin-inline: auto;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.skip-link {
  position: fixed;
  top: 12px; left: 12px;
  z-index: 100;
  padding: 10px 14px;
  border-radius: 6px;
  background: var(--black);
  color: var(--inverse-fg);
  font-size: 14px;
  transform: translateY(-200%);
  transition: transform 0.2s var(--ease-out);
}
.skip-link:focus { transform: none; }

/* Shared arrow icon (source points left) */
.arrow {
  width: 11px;
  height: 9px;
  flex: none;
  color: var(--dark-2);
  transition: opacity 0.25s var(--ease-out), transform 0.35s var(--ease-out);
}
.arrow--out { transform: rotate(135deg); }

/* =========================================================
   Background grid
   ========================================================= */
.grid-bg {
  position: fixed;
  /* As tall as the screen can get: when a phone's address bar slides away
     while scrolling, the lines still reach the bottom edge */
  inset: 0 0 auto;
  height: 100vh;
  height: 100lvh;
  z-index: -1;
  pointer-events: none;
}
.grid-bg__cols {
  position: relative;
  height: 100%;
  display: grid;
  grid-template-columns: var(--cols);
}
.grid-bg__cols span { position: relative; }
/* Each line is its own element so it can be drawn in during the intro:
   every column's left edge, plus the container's right edge.
   --l is the line's order (left → right). */
.grid-bg__cols span::before,
.grid-bg__cols::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--line);
  transform-origin: top;
}
.grid-bg__cols span::before { left: 0; }
.grid-bg__cols::after { right: 0; --l: 6; }
/* The outer edges use the header separator's colour. On desktop the header's
   side borders match so the edge lines run unbroken to the top (on mobile
   the header is full-width with no side borders). */
.grid-bg__cols span:first-child::before,
.grid-bg__cols::after { background: var(--separator); }
@media (min-width: 1000px) {
  .site-header .site-header__inner { border-inline-color: var(--separator); }
}
.grid-bg__cols span:nth-child(2) { --l: 1; }
.grid-bg__cols span:nth-child(3) { --l: 2; }
.grid-bg__cols span:nth-child(4) { --l: 3; }
.grid-bg__cols span:nth-child(5) { --l: 4; }
.grid-bg__cols span:nth-child(6) { --l: 5; }

/* =========================================================
   Header
   ========================================================= */
.site-header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 20;
  pointer-events: none;
}
.site-header__inner {
  position: relative;
  height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 33px 0 20px;
  background: var(--bg);
  border-bottom: 1px solid var(--separator);
  border-inline: 1px solid var(--line);
  pointer-events: auto;
}

.logo {
  font-size: 42px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--black);
  transition: opacity 0.2s;
}
.logo:hover { opacity: 0.7; }

.top-nav {
  display: flex;
  align-items: center;
  gap: 24px;
}

.top-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 40px;
  font-size: 18px;
  line-height: 1.2;
  color: var(--dark-2);
  white-space: nowrap;
  transition: color 0.2s;
}
.top-link .arrow { opacity: 0; }
.top-link .arrow--out { transform: rotate(135deg) translateX(4px); }
.top-link:hover .arrow,
.top-link:focus-visible .arrow { opacity: 1; }
.top-link:hover .arrow--out,
.top-link:focus-visible .arrow--out { transform: rotate(135deg) translateX(0); }

/* Desktop CV: the hover arrow doesn't reserve space, so the word sits
   centred between its two separators; the arrow appears in the gap */
.top-nav > .top-link.desktop-only {
  position: relative;
  transition: color 0.2s, transform 0.35s var(--ease-out);
}
/* On hover the visible group becomes "CV ↗" (~18px wider on the right),
   so slide left by half of that to keep the pair centred */
.top-nav > .top-link.desktop-only:hover,
.top-nav > .top-link.desktop-only:focus-visible { transform: translateX(-9px); }
.top-nav > .top-link.desktop-only .arrow {
  position: absolute;
  left: calc(100% + 6px);
  top: 50%;
  margin-top: -4.5px;
}

.divider {
  width: 1px;
  height: 40px;
  background: var(--separator);
  opacity: 0.5;
  flex: none;
}

/* Desktop: 30px from the separator to "Contacts", matching the 30px between
   its arrow and the header's edge (nav gap is 24px, so add 6px) */
.contacts-toggle { margin-left: 6px; }

/* Contacts toggle: "←" hints the panel opens leftwards, "→" closes it */
.contacts-toggle .arrow--toggle { transform: translateX(3px); }
.contacts-toggle:hover .arrow--toggle { transform: none; }
.contacts-toggle[aria-expanded="true"] .arrow--toggle { opacity: 1; transform: rotate(180deg); }

/* Expanding contacts panel */
.contacts {
  display: flex;
  align-items: center;
}
.contacts[hidden] { display: none; }
/* Desktop reveal: main.js animates this row's width from 0. Its right edge
   is the separator next to "Contacts" (kept outside the row, so it never
   moves or clips), and the links are anchored to the row's left edge — so
   as the width grows they travel left out from behind the separator,
   pushing CV ahead of them. */
.contacts__inner {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 20px;
  overflow: hidden;
}
.contacts__inner > * { flex-shrink: 0; }
.contacts__inner > :last-child { margin-right: 20px; }   /* space before the separator */
.contacts__socials { display: flex; gap: 20px; }
/* Desktop: the revealed social links also get wider targets (half their
   20px gap each side; the row's height already matches the email pill) */
@media (min-width: 1000px) {
  .contacts__socials .top-link { position: relative; }
  .contacts__socials .top-link::after {
    content: "";
    position: absolute;
    inset: 0 -10px;
  }
}

.email-pill {
  position: relative;
  display: inline-grid;
  /* Centre the content explicitly: Safari sizes a grid inside a <button> to
     its content and pins it to the top instead of stretching it */
  place-content: center;
  place-items: center;
  height: 40px;
  padding: 0 20px;
  border-radius: 6px;
  background: var(--fill);
  box-shadow: inset 0 0 0 1px var(--fill-ring);
  font-size: 16px;
  color: var(--black);
  /* Safari will otherwise break the address at "." / "@" inside a grid button */
  white-space: nowrap;
  transition: background-color 0.25s, color 0.25s, box-shadow 0.25s;
}
.email-pill:hover { background: var(--fill-hover); }
.email-pill > span {
  grid-area: 1 / 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: opacity 0.25s var(--ease-out), transform 0.35s var(--ease-spring);
}
.email-pill svg { width: 14px; height: 14px; flex-shrink: 0; fill: currentColor; }
.email-pill__copied svg { fill: none; }
.email-pill__copied { opacity: 0; transform: scale(0.6); }

.email-pill.is-copied { background: var(--black); color: var(--inverse-fg); box-shadow: none; }
.email-pill.is-copied .email-pill__default { opacity: 0; transform: scale(0.8); }
.email-pill.is-copied .email-pill__copied { opacity: 1; transform: none; }

/* Hamburger + menu sheet + CV inside Contacts: mobile/tablet only
   (see Responsive) */
.menu-only,
.menu-only-item,
.menu-sheet { display: none; }

.menu-toggle {
  flex-direction: column;
  justify-content: center;
  gap: var(--burger-gap, 8px);
  width: var(--burger-w, 32px);
  height: 40px;
}
.menu-toggle span {
  display: block;
  width: 100%;          /* Safari ≤ 18 doesn't stretch children inside a flex <button> */
  height: 2px;
  background: var(--dark-2);
  border-radius: 1px;
  transition: transform 0.35s var(--ease-out), opacity 0.2s;
}
/* Morph into an × when open */
.menu-toggle[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(calc(var(--burger-gap, 8px) + 2px)) rotate(45deg);
}
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(calc(-1 * (var(--burger-gap, 8px) + 2px))) rotate(-45deg);
}

/* Larger click/tap targets: an invisible ::after stretches each header item
   into the space around it — sideways up to the neighbouring separator (every
   pair of items has one between them, so targets never overlap) and most of
   the header's height — without changing the visible layout. */
:root {
  --hit-x: 23px;   /* the 24px desktop gap, stopping just short of the separator */
  --hit-h: 64px;   /* of the 80px desktop header */
}
.site-header__inner > .logo,
.top-nav > .top-link,
.top-nav > .theme-toggle,
.top-nav > .menu-toggle { position: relative; }
.site-header__inner > .logo::after,
.top-nav > .top-link::after,
.top-nav > .theme-toggle::after,
.top-nav > .menu-toggle::after {
  content: "";
  position: absolute;
  top: 50%;
  left: calc(-1 * var(--hit-x));
  right: calc(-1 * var(--hit-x));
  height: var(--hit-h);
  transform: translateY(-50%);
}

/* Theme switch: moon in light (→ go dark), sun in dark (→ go light) */
.theme-toggle {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex: none;
  color: var(--dark-2);
  transition: color 0.2s;
}
/* Mouse only: on phones a tap would leave the icon stuck in its hover
   colour, out of step with the burger */
@media (hover: hover) { .theme-toggle:hover { color: var(--black); } }
.theme-toggle__icon {
  grid-area: 1 / 1;
  width: 26px;
  height: 26px;
  display: none;
}
:root:not([data-theme="dark"]) .theme-toggle__moon,
:root[data-theme="dark"] .theme-toggle__sun { display: block; }
/* Lottie draws black strokes; follow the text colour in both themes */
.theme-toggle__icon svg path { stroke: currentColor; }
.theme-toggle__static {
  width: 100%;
  height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.theme-toggle.has-lottie .theme-toggle__static { display: none; }

/* Theme switch: the whole page crossfades once (View Transitions, set up
   in main.js), much lighter than animating every element's colours */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.35s;
  animation-timing-function: ease;
}

/* Phones/tablets: "scroll" hint at the bottom right of the hero (shown in
   the Responsive section); the chevrons nudge down every 2s */
.scroll-hint { display: none; }
.scroll-hint__text {
  writing-mode: vertical-rl;
  /* reads top → bottom; the capitals centre on the pill as they are
     (measured on the rendered pixels) */
  font-size: 9px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  white-space: nowrap;
  /* the trailing letter-space after the last letter would push the word
     away from the pill, so pull it back */
  margin-bottom: -0.12em;
}
/* Chevrons sit in a vertical pill outlined at the same weight as their
   strokes; nudged up 2px so their 4px dip stays centred in it */
.scroll-hint__pill {
  display: grid;
  place-items: center;
  width: 16px;
  height: 32px;
  /* a step softer than the chevrons, so the outline doesn't compete */
  border: 1.5px solid color-mix(in srgb, currentColor 55%, transparent);
  border-radius: 999px;
}
.scroll-hint__chevrons {
  translate: 0 -1.5px;
  width: 8px;
  height: 10px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  overflow: visible;
}
/* Going down, the upper chevron follows the lower one 0.12s (6%) behind;
   the lower one waits at the bottom, then both rise back together.
   Sine-like in/out ease on every segment for soft turnarounds */
.scroll-hint__chevrons path:nth-child(2) {
  animation: scroll-nudge-lead 2s cubic-bezier(.45, 0, .55, 1) infinite;
}
.scroll-hint__chevrons path:nth-child(1) {
  animation: scroll-nudge-follow 2s cubic-bezier(.45, 0, .55, 1) infinite;
}
@keyframes scroll-nudge-lead {
  0%, 40% { transform: translateY(0); }
  62%, 68% { transform: translateY(4px); }
  100% { transform: translateY(0); }
}
@keyframes scroll-nudge-follow {
  0%, 46% { transform: translateY(0); }
  68% { transform: translateY(4px); }
  100% { transform: translateY(0); }
}


/* =========================================================
   Sidebar
   ========================================================= */
.sidebar {
  position: fixed;
  inset: 0;
  z-index: 10;
  pointer-events: none;
}
.sidebar__inner {
  position: relative;
  height: 100%;
}

.section-nav {
  position: absolute;
  top: calc(50% - 6px);
  left: 33px;
  transform: translateY(-50%);
  pointer-events: auto;
}
.section-nav ul {
  display: grid;
  gap: 15px;
}
.section-nav a {
  display: block;
  font-size: 17px;
  line-height: 1;
  color: var(--grey);
  transition: color 0.25s, font-weight 0.25s;
}
/* Hover looks exactly like the current section */
.section-nav a:hover,
.section-nav a[aria-current="true"] {
  color: var(--active, var(--dark-2));
  font-weight: 700;
}

.based {
  position: absolute;
  left: 20px;
  /* --footer-lift (main.js) raises it above the footer at the page end */
  bottom: calc(22px + var(--footer-lift, 0px));
  display: grid;
  gap: 8px;
  pointer-events: auto;
}
.based__label { font-size: 13px; line-height: 1; color: var(--grey); margin-bottom: 3px; }
.based__city { font-size: 14px; line-height: 1; font-weight: 500; color: var(--dark-2); }
.based__time { font-size: 13px; line-height: 1; color: var(--grey); font-variant-numeric: tabular-nums; }

/* =========================================================
   Hero
   Positions are expressed in container units so the composition
   scales exactly like the 1240px Framer frame.
   ========================================================= */
.hero__shell { container-type: inline-size; }

.hero {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding: var(--header-h) 0 26px;
}

.hero__stage {
  position: relative;
  height: calc(356 / 1240 * 100cqw);
  --u: calc(100cqw / 1240);   /* 1 Framer px at the current scale */
}

.hero__title {
  position: absolute;
  top: 0;
  left: calc(213 * var(--u));
  font-weight: 700;
  white-space: nowrap;
}
.hero__title > span { display: block; }
.hero__hi {
  font-size: calc(86 * var(--u));
  line-height: 1.1;
  letter-spacing: -0.009em;
  color: var(--grey);
}
.hero__name {
  font-size: calc(120 * var(--u));
  line-height: 1.1;
  letter-spacing: -0.009em;
  color: var(--black);
}

.hero__extra {
  position: absolute;
  top: calc(271 * var(--u));
  left: calc(418 * var(--u));
  /* Column ends 32px before the photo (photo starts at 924) so longer lines
     wrap instead of running underneath it */
  max-width: calc((924 - 32 - 418) * var(--u));
  display: grid;
  gap: 10px;
  font-size: clamp(16px, calc(19 * var(--u)), 19px);
  line-height: 1.2;
  color: var(--grey);
}
.hero__extra p:first-child { letter-spacing: 0.005em; }
.hero__extra p:last-child { letter-spacing: -0.005em; }
.hero__extra strong { font-weight: 500; color: var(--active, var(--dark-2)); }
.inline-link {
  display: inline-flex;
  align-items: flex-start;
  gap: 2px;
}
.inline-link strong {
  background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
  transition: background-size 0.35s var(--ease-out), color 0.2s;
}
.inline-link .arrow { width: 9px; height: 8px; margin-top: 2px; }
.inline-link:hover strong { background-size: 100% 1px; color: var(--black); }
.inline-link:hover .arrow { transform: rotate(135deg) translateX(-2px); }

.hero__photo {
  position: absolute;
  top: calc(57 * var(--u));
  left: calc(924 * var(--u));
  width: calc(230 * var(--u));
  aspect-ratio: 230 / 299;
  border-radius: 12px;
  overflow: hidden;
  background: var(--photo-bg);
  border: 1px solid var(--photo-border);
}
.hero__photo picture { display: contents; }
.hero__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.8s var(--ease-out);
}
.hero__photo:hover img { transform: scale(1.03); }

/* Figma-style multiplayer cursor */
.figma-cursor {
  position: absolute;
  top: calc(-46 * var(--u));
  left: calc(835 * var(--u));
  z-index: 2;
  pointer-events: none;
  transform: translate(var(--cx, 0px), var(--cy, 0px));
  will-change: transform;
}
.figma-cursor__icon {
  display: block;
  width: 12px;
  height: 12px;
  fill: var(--figma-blue);
  stroke: rgba(255, 255, 255, 0.35);
  stroke-width: 1;
}
.figma-cursor__label {
  position: absolute;
  top: 11px;
  left: 14px;
  padding: 5px 8px 6px;
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: var(--figma-label);
  color: #f8f8f8;   /* stays light on the blue label in both themes */
  font-size: 12px;
  line-height: 1.1;
  white-space: nowrap;
  transform-origin: 0 0;
}

/* =========================================================
   Work
   Four project cards spanning columns 2–6. Sizes are Framer px of the
   1240px frame (--u), so the cards scale exactly like the hero.
   ========================================================= */
.work__shell {
  container-type: inline-size;
  --u: calc(100cqw / 1240);
}
.work {
  --u: min(1px, (100vw - 2 * var(--gutter)) / 1240);   /* same scale as the shell */
  /* 260 Framer px below the hero in total; the part inside the section
     is what's left under the header when "Work" is clicked in the nav */
  margin-top: calc(180 * var(--u));
  padding: calc(80 * var(--u)) 0 calc(120 * var(--u));
}
/* Section label: on desktop it's for screen readers only (the sidebar
   names the sections); on phones it opens each section as a cell in the
   first grid column (see the phone styles) */
.section-label {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  margin: 0;
}

.work__list {
  display: grid;
  gap: calc(80 * var(--u));
  /* Columns 2–6, 1px clear of the grid lines on either side */
  margin-left: calc(212 * var(--u) + 1px);
  margin-right: 1px;
}

.work-card {
  display: grid;
  align-items: stretch;
  /* Hairlines above and below, in the inner grid lines' colour */
  border-block: 1px solid var(--line);
  gap: calc(30 * var(--u));
  padding: calc(30 * var(--u));
  background: var(--card-bg);
}
/* Column widths and image shapes per card, from the original */
.work-card--platform { grid-template-columns: 332fr 609fr; column-gap: calc(25 * var(--u)); }
.work-card--platform .work-card__media { aspect-ratio: 609 / 400; }
.work-card--betslip  { grid-template-columns: 455fr 481fr; }
.work-card--betslip .work-card__media { aspect-ratio: 455 / 442; }
.work-card--bonus    { grid-template-columns: 458fr 478fr; }
.work-card--bonus .work-card__media { aspect-ratio: 478 / 440; }
.work-card--archive  { grid-template-columns: 301fr 635fr; }
.work-card--archive .work-card__media { aspect-ratio: 635 / 440; }
/* The image comes first in the markup (it leads on phones); on desktop
   it sits on the right, except for the betslip card */
.work-card:not(.work-card--betslip) .work-card__media { order: 2; }

.work-card__media {
  position: relative;
  overflow: hidden;
  border-radius: 6px;
  background: var(--photo-bg);
}
.work-card__media picture { display: contents; }
.work-card__media img,
.work-card__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.8s var(--ease-out);
}
.work-card:hover .work-card__media img,
.work-card:hover .work-card__video { transform: scale(1.03); }
/* Soft inner edge on every project image */
.work-card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.25);
  pointer-events: none;
}
/* The video covers its still once it is actually playing. It starts a
   screen ahead of the card (main.js), so the swap is never seen; no fade,
   a crossfade between the two different frames reads as a blink */
.work-card__video { visibility: hidden; }
.work-card__video.is-playing { visibility: visible; }

.work-card__body {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 24px;
  min-width: 0;
}
.work-card__title {
  margin: 0;
  font-size: clamp(30px, calc(44 * var(--u)), 44px);
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--black);
}
.work-card__desc {
  margin-top: 16px;
  font-size: clamp(15px, calc(18 * var(--u)), 18px);
  line-height: 1.2;
  color: var(--grey);
  text-wrap: pretty;
}

.work-card__foot {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}
/* Betslip and bonus cards: list on the left, button bottom-right */
.work-card--betslip .work-card__foot,
.work-card--bonus .work-card__foot {
  flex-direction: row;
  flex-wrap: wrap;   /* button drops under the list on narrow screens */
  align-items: flex-end;
  justify-content: space-between;
}
.work-card--archive .work-card__foot { gap: 19px; }
.work-card__facts { display: grid; gap: 10px; }
.work-card__facts ul { display: grid; gap: 8px; }
.work-card__label {
  font-size: clamp(13px, calc(15 * var(--u)), 15px);
  line-height: 1;
  color: var(--grey);
}
.work-card__facts li {
  font-size: clamp(14px, calc(16 * var(--u)), 16px);
  line-height: 1.1;
  color: var(--dark-2);
}

/* "View Project": black pill; on hover it turns light and the arrow
   slides out to the right while a fresh one slides in from the left */
.btn-project {
  flex: none;
  display: inline-flex;
  align-items: center;
  height: 44px;
  padding: 0 26px 0 32px;
  border-radius: 6px;
  background: var(--black);
  color: var(--inverse-fg);
  font-size: 18px;
  line-height: 1;
  white-space: nowrap;
  transition: background-color 0.3s var(--ease-out), color 0.3s var(--ease-out), box-shadow 0.3s var(--ease-out);
}
.btn-project__arrows {
  position: relative;
  width: 24px;
  height: 9px;
  margin-left: 2px;
  overflow: hidden;
}
.btn-project .arrow {
  position: absolute;
  top: 0;
  left: 6px;
  color: currentColor;
  transform: rotate(180deg);   /* source points left */
  transition: translate 0.45s var(--ease-out);
}
.btn-project .arrow:last-child { translate: -30px 0; }
.btn-project:hover {
  background: var(--card-bg);
  color: var(--black);
  box-shadow: inset 0 0 0 1px var(--black);
}
.btn-project:hover .arrow { translate: 30px 0; }
.btn-project:hover .arrow:last-child { translate: 0 0; }

/* Cards slide up (fully opaque, no fade) as they scroll into view
   (class set by main.js, so without JavaScript they simply sit in place).
   A longer rise with a gentle ease so the movement is actually seen. */
.has-reveal .work-card {
  transition: transform 1.2s cubic-bezier(0.25, 0.8, 0.3, 1);
}
.has-reveal .work-card:not(.is-in) {
  transform: translateY(90px);
}

/* =========================================================
   Values
   A stage on the 1240px frame like the hero: big words on the left,
   the Values | Motivation switch and its text on the right, social
   links bottom-left. Positions are Framer px (--u).
   ========================================================= */
.values__shell {
  container-type: inline-size;
  --u: calc(100cqw / 1240);
}
.values {
  --u: min(1px, (100vw - 2 * var(--gutter)) / 1240);   /* for the margin below */
  margin-top: calc(452 * var(--u));   /* ~600 Framer px after the last card, as on the original */
}
.values__stage {
  position: relative;
  height: calc(896 * var(--u));
  /* How far each line travels when the sets swap: they move together
     but over different distances, so they read as a staggered wave */
  --shift-0: calc(550 * var(--u));
  --shift-1: calc(860 * var(--u));
  --shift-2: calc(1170 * var(--u));
  --swap: 1.3s cubic-bezier(0.32, 0.12, 0.12, 1);
}

/* A window from the 2nd grid line to just before the text column (as on
   the original): lines slide out under its left edge and in from its
   right edge, and the set that's waiting stays out of sight */
.values__words {
  position: absolute;
  top: calc(30 * var(--u));
  left: calc(212 * var(--u));
  width: calc(410 * var(--u));
  height: calc(320 * var(--u));
  overflow: hidden;
}
.values__set { margin: 0; }
.values__line {
  position: absolute;
  top: 0;
  left: calc(1 * var(--u));   /* just clear of the 2nd grid line, like the hero title */
  font-size: calc(80 * var(--u));
  line-height: 1.2;
  font-weight: 700;
  white-space: nowrap;
  color: var(--black);
  transition: transform var(--swap);
}
.values__line:nth-child(2) { top: calc(112 * var(--u)); }
.values__line:nth-child(3) { top: calc(224 * var(--u)); }
.values__line:nth-child(1) { --shift: var(--shift-0); }
.values__line:nth-child(2) { --shift: var(--shift-1); }
.values__line:nth-child(3) { --shift: var(--shift-2); }
/* First set (Motivation) shows by default; the second (Values) waits off
   to the right. Choosing the second tab slides the first out to the left
   and the second in; going back reverses it. */
.values__set--second .values__line { transform: translateX(var(--shift)); }
.values.is-second .values__set--first .values__line { transform: translateX(calc(-1 * var(--shift))); }
.values.is-second .values__set--second .values__line { transform: none; }

.values__about {
  position: absolute;
  top: calc(440 * var(--u));
  left: calc(623 * var(--u));
  width: calc(542 * var(--u));
}
.values__tabs {
  display: flex;
  gap: calc(30 * var(--u));
}
.values__tab {
  padding: 0;
  font-size: clamp(16px, calc(18 * var(--u)), 18px);
  line-height: 1.2;
  color: var(--dark-2);
  opacity: 0.5;
  transition: opacity 0.3s var(--ease-out);
}
.values__tab:hover { opacity: 0.8; }
.values__tab[aria-selected="true"] { opacity: 1; font-weight: 600; }
/* Both texts share one grid cell, so the block keeps the height of the
   longer one and the swap is a crossfade with no jump */
.values__panels {
  display: grid;
  margin-top: 20px;
}
.values__panel {
  grid-area: 1 / 1;
  font-size: clamp(16px, calc(18 * var(--u)), 18px);
  line-height: 1.8;
  color: var(--grey);
  text-wrap: pretty;
  transition: opacity 0.4s var(--ease-out), visibility 0s;
}
.values__panel.is-hidden {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s var(--ease-out), visibility 0s 0.25s;
}

.values__links {
  position: absolute;
  top: calc(722 * var(--u));
  left: calc(212 * var(--u) + 1px);
  display: grid;
  justify-items: start;   /* rows only as wide as their link, so the
                             slide-in offset never pokes past the screen */
  gap: 6px;
}
.values__link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  font-size: clamp(15px, calc(17 * var(--u)), 17px);
  line-height: 1.2;
  color: var(--dark-2);
  transition: color 0.2s;
}
.values__link .arrow { width: 10px; height: 8px; }
.values__link:hover { color: var(--black); font-weight: 600; }
.values__link:hover .arrow { color: var(--black); transform: rotate(135deg) translateX(-3px); }
/* Links slide in from the right one after another as the section
   scrolls into view (class set by main.js) */
.has-reveal .values__links li {
  transition: transform 0.7s calc(var(--i) * 70ms) var(--ease-out);
}
.has-reveal .values:not(.is-in) .values__links li {
  transform: translateX(calc(30px + var(--i) * 10px));
}

/* =========================================================
   Inspiration
   Big heading top-left, intro text on the right, a photo that changes
   with the topic hovered in the list beside it. Framer px (--u).
   ========================================================= */
.inspo__shell {
  container-type: inline-size;
  --u: calc(100cqw / 1240);
}
.inspo {
  --u: min(1px, (100vw - 2 * var(--gutter)) / 1240);
  margin-top: calc(572 * var(--u));   /* same gap as the original */
}
.inspo__stage {
  position: relative;
  height: calc(1150 * var(--u));
}

.inspo__heading {
  position: absolute;
  top: 0;
  left: calc(213 * var(--u));
  margin: 0;
  font-size: calc(80 * var(--u));
  line-height: 1.2;
  font-weight: 700;
  white-space: nowrap;
  color: var(--black);
}
.inspo__muted { color: var(--grey); }

.inspo__text {
  position: absolute;
  top: calc(303 * var(--u));
  left: calc(826 * var(--u));
  width: calc(381 * var(--u));
  font-size: clamp(16px, calc(18 * var(--u)), 18px);
  line-height: 1.8;
  color: var(--grey);
  text-wrap: pretty;
}

.inspo__photo {
  position: absolute;
  top: calc(500 * var(--u));
  left: calc(324 * var(--u));
  width: calc(406 * var(--u));
}
.inspo__frame {
  position: relative;
  aspect-ratio: 406 / 619;
  overflow: hidden;
  border-radius: 6px;
  background: var(--photo-bg);
}
/* All photos are stacked; the active one fades in over the others */
.inspo__img {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.5s var(--ease-out);
}
.inspo__img.is-active { opacity: 1; }
.inspo__img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Captions share one grid cell and crossfade like the photos. The row
   is clipped just under the photo and starts tucked up out of sight, so
   the first topic chosen slides it down as if from behind the photo; its
   height is kept from the start, so nothing below moves. */
.inspo__captions {
  display: block;
  padding-top: 10px;   /* padding, not margin: the clip edge is the photo's bottom */
  overflow: hidden;
}
.inspo__captions-track {
  display: grid;
  transform: translateY(calc(-100% - 12px));
  transition: transform 0.6s var(--ease-out);
}
.inspo__photo.is-captioned .inspo__captions-track { transform: none; }
.inspo__caption {
  grid-area: 1 / 1;
  font-size: 16px;
  line-height: 1.2;
  color: var(--grey);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.25s var(--ease-out), visibility 0s 0.25s;
}
.inspo__caption.is-active {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.4s var(--ease-out), visibility 0s;
}
.inspo__caption strong { font-weight: 600; color: var(--black); }

/* Topics: bottom-aligned with the photo */
.inspo__topics {
  justify-items: start;
  position: absolute;
  top: calc(1119 * var(--u));
  left: calc(1030 * var(--u));
  translate: 0 -100%;
  display: grid;
  gap: 2px;
}
.inspo__topic {
  display: block;
  height: 30px;
  padding: 0;
  font-size: clamp(15px, calc(17 * var(--u)), 17px);
  line-height: 1.2;
  color: var(--dark-2);
  transition: color 0.2s;
}
.inspo__topic:hover,
.inspo__topic[aria-pressed="true"] { color: var(--black); font-weight: 600; }
/* Desktop only: the topics slide in one after another, like the Values
   links (main.js sets `is-in` when scrolled down to them) */
@media (min-width: 1000px) {
  .has-reveal .inspo__topics li {
    transition: transform 0.7s calc(var(--i) * 55ms) var(--ease-out);
  }
  .has-reveal .inspo:not(.is-in) .inspo__topics li {
    transform: translateX(calc(25px + var(--i) * 5px));
  }
}

/* =========================================================
   Photos
   Heading, then a wide strip of photos laid out like a collage
   (positions from the original, in Framer px) that scrolls sideways.
   ========================================================= */
.photos__shell {
  container-type: inline-size;
  --u: calc(100cqw / 1240);
}
.photos {
  --u: min(1px, (100vw - 2 * var(--gutter)) / 1240);
  margin-top: calc(494 * var(--u));   /* same gap as the original */
}
.photos__stage {
  position: relative;
  height: calc(1238 * var(--u));
  --pu: var(--u);   /* 1 strip px: the photos scale with the page */
}
.photos__heading {
  position: absolute;
  top: calc(50 * var(--u));
  left: calc(213 * var(--u));
  margin: 0;
  font-size: calc(80 * var(--u));
  line-height: 1.2;
  font-weight: 700;
  white-space: nowrap;
  color: var(--black);
}
.photos__muted { color: var(--grey); }

/* Spans columns 2–6, clipped at the 2nd and the outer grid lines */
.photos__gallery {
  position: absolute;
  top: calc(342 * var(--u));
  left: calc(212 * var(--u) + 1px);
  right: 1px;
}
.photos__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 20px;
  padding-inline: 1px 44px;
}
.photos__label,
.photos__hint {
  font-size: 13px;
  line-height: 1.2;
}
.photos__label { font-weight: 700; color: var(--black); }
/* Mouse wording by default, touch wording on touch screens */
.photos__hint-touch { display: none; }
@media (hover: none) {
  .photos__hint-mouse { display: none; }
  .photos__hint-touch { display: inline; }
}
.photos__hint {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
  color: var(--grey);
}
/* The ↔ arrow in a horizontal pill, outlined at the arrow's weight */
.photos__hint-pill {
  display: grid;
  place-items: center;
  width: 28px;
  height: 15px;
  border: 1.3px solid color-mix(in srgb, currentColor 55%, transparent);   /* softer than the arrow */
  border-radius: 999px;
}
.photos__hint-pill svg {
  width: 13px;
  height: 6.5px;
  overflow: visible;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The window onto the strip; main.js moves the track inside it */
.photos__scroller {
  margin-top: calc(25 * var(--u));
  overflow: hidden;
  touch-action: pan-y;   /* vertical swipes still scroll the page */
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
}
.photos__scroller.is-dragging { cursor: grabbing; }
.photos__scroller:focus-visible { outline-offset: -2px; }
/* One set of photos is --loop strip px long (the last photo, then the
   usual 61px gap before the first comes round again); the copy sits
   right after it so the seam is never seen */
.photos__track {
  --loop: 8684;
  position: relative;
  height: calc(744 * var(--pu));
  will-change: transform;
}
.photos__set {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(var(--loop) * var(--pu));
  height: 100%;
}
.photos__set + .photos__set { left: calc(var(--loop) * var(--pu)); }
.photos__item {
  position: absolute;
  left: calc(var(--x) * var(--pu));
  top: calc(var(--y) * var(--pu));
  width: calc(var(--w) * var(--pu));
  height: calc(var(--h) * var(--pu));
  margin: 0;
  overflow: hidden;
  border-radius: 12px;
  background: var(--photo-bg);
}
.photos__item picture { display: contents; }
.photos__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  -webkit-user-drag: none;
}

/* =========================================================
   Experience
   Company name, then its roles: title from the 3rd grid line, dates
   from the 6th, details as a bulleted list under the title.
   Framer px (--u), flowing rather than absolutely placed.
   ========================================================= */
.exp__shell {
  container-type: inline-size;
  --u: calc(100cqw / 1240);
}
.exp {
  --u: min(1px, (100vw - 2 * var(--gutter)) / 1240);
  margin-top: calc(572 * var(--u));   /* same gap as the original */
  padding-bottom: calc(160 * var(--u));
}
.exp__company + .exp__company { margin-top: calc(121 * var(--u)); }
.exp__name {
  margin: 0 0 0 calc(213 * var(--u));
  font-size: calc(80 * var(--u));
  line-height: 1.2;
  font-weight: 700;
  color: var(--black);
}
.exp__roles {
  margin: calc(60 * var(--u)) 0 0;
  padding: 0;
  list-style: none;
}
.exp__role {
  display: grid;
  grid-template-columns: calc((1032 - 421) * var(--u)) 1fr;
  align-items: center;
  padding-left: calc(421 * var(--u));   /* just after the 3rd grid line */
}
.exp__role + .exp__role { margin-top: calc(41 * var(--u)); }
.exp__title {
  margin: 0;
  font-size: clamp(24px, calc(32 * var(--u)), 32px);
  line-height: 1.2;
  font-weight: 400;
  color: var(--black);
}
.exp__dates {
  font-size: clamp(14px, calc(16 * var(--u)), 16px);
  line-height: 1.2;
  color: var(--grey);
  white-space: nowrap;
}
.exp__details {
  grid-column: 1;
  display: grid;
  gap: calc(18 * var(--u));
  margin: calc(40 * var(--u)) 0 0;
  padding: 0 calc(16 * var(--u)) 0 16px;
  list-style: none;
}
.exp__details li {
  position: relative;
  font-size: 14px;
  line-height: 1.2;
  color: var(--dark-2);
  text-wrap: pretty;
}
.exp__details li::before {
  content: "";
  position: absolute;
  top: 0.5em;
  left: -11px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--grey);
}

/* =========================================================
   Footer
   A mirror of the header: a 60px bar closed off by the separator line
   on top, credits left, a little joke centred, the version right.
   ========================================================= */
.site-footer { margin-top: calc(180 * min(1px, (100vw - 2 * var(--gutter)) / 1240)); }
.site-footer__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: 60px;
  padding: 0 28px 0 30px;
  background: var(--bg);
  border-top: 1px solid var(--separator);
  border-inline: 1px solid var(--separator);
  font-size: 14px;
  line-height: 1.2;
}
.site-footer__by,
.site-footer__version { font-weight: 500; color: var(--black); }
.site-footer__version { justify-self: end; }
.site-footer__dim { font-weight: 400; color: var(--grey); }
.site-footer__smile { color: var(--grey); }
.site-footer__br { display: none; }   /* phones only */
.site-footer__smile a {
  font-weight: 500;
  color: var(--black);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: text-underline-offset 0.2s var(--ease-out);
}
.site-footer__smile a:hover { text-underline-offset: 4px; }

/* =========================================================
   Photo viewer (lightbox)
   A native <dialog>: the photo as large as fits, arrows either side, a
   close button top-right and a counter underneath. Dark in both themes.
   ========================================================= */
.photos__item { cursor: zoom-in; }
.photos__scroller.is-dragging .photos__item { cursor: grabbing; }

.photos__item:focus-visible { outline: 2px solid var(--figma-blue); outline-offset: 2px; }

.lightbox {
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  /* 70% black over the page, which is blurred while the viewer is open
     (.viewer-open below; blurring the page itself works in every
     browser, unlike a backdrop-filter on the dialog) */
  background: rgba(0, 0, 0, 0.7);
  color: #f5f5f5;
  overflow: hidden;
}
.lightbox::backdrop { background: transparent; }
/* (not the footer: blurring it paints a black square in Safari's
   top-left corner; it is far off screen while the viewer is open anyway) */
.grid-bg, .site-header, .sidebar, main { transition: filter 0.3s var(--ease-out); }
.viewer-open :is(.grid-bg, .site-header, .sidebar, main) { filter: blur(14px); }
.lightbox[open] { animation: lightbox-in 0.3s var(--ease-out); }
@keyframes lightbox-in { from { opacity: 0; } }

.lightbox__figure {
  position: absolute;
  inset: 0;
  margin: 0;
  touch-action: pan-y;   /* sideways swipes change photo */
}
/* The photo is centred in the area left free by the buttons, the counter
   and the thumbnail row */
.lightbox__frame {
  position: absolute;
  inset: 72px 96px 144px;
  display: grid;
  place-items: center;
}
.lightbox__frame picture { display: contents; }
.lightbox__frame source { display: none; }   /* Safari would lay them out as rows */
.lightbox__frame img {
  max-width: 100%;
  max-height: calc(100vh - 216px);
  max-height: calc(100dvh - 216px);
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 8px;
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.45);
  user-select: none;
  -webkit-user-drag: none;
  animation: lightbox-photo 0.35s var(--ease-out);
}
@keyframes lightbox-photo { from { opacity: 0; transform: scale(0.98); } }

/* Thumbnail row along the bottom: every photo, the current one bright
   and kept in the middle (main.js), the rest dimmed; edges fade out */
.lightbox__thumbs {
  position: absolute;
  left: 50%;
  bottom: 24px;
  translate: -50% 0;
  display: flex;
  gap: 8px;
  width: min(760px, 100vw - 240px);
  padding: 4px 0;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.lightbox__thumbs::-webkit-scrollbar { display: none; }
/* Room either side so the first and last thumbnails can sit in the middle */
.lightbox__thumbs::before,
.lightbox__thumbs::after { content: ""; flex: 0 0 calc(50% - 30px); }
.lightbox__thumb {
  flex: none;
  width: 52px;
  height: 52px;
  padding: 0;
  overflow: hidden;
  border-radius: 6px;
  opacity: 0.4;
  transition: opacity 0.25s var(--ease-out), box-shadow 0.25s var(--ease-out);
}
.lightbox__thumb:hover { opacity: 0.75; }
.lightbox__thumb[aria-current="true"] {
  opacity: 1;
  box-shadow: 0 0 0 2px rgba(245, 245, 245, 0.9);
}
.lightbox__thumb picture { display: contents; }
.lightbox__thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  -webkit-user-drag: none;
}
.lightbox__count {
  position: absolute;
  left: 50%;
  bottom: 96px;
  translate: -50% 0;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  color: rgba(245, 245, 245, 0.6);
}

.lightbox__btn {
  position: absolute;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
  color: #f5f5f5;
  transition: background-color 0.2s;
}
.lightbox__btn:hover { background: rgba(255, 255, 255, 0.18); }
.lightbox__btn:focus-visible { outline-color: #f5f5f5; }
.lightbox__close { top: 16px; right: 16px; }
.lightbox__close svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
}
.lightbox__nav { top: 50%; translate: 0 -50%; }
.lightbox__nav--prev { left: 24px; }
.lightbox__nav--next { right: 24px; }
.lightbox__nav .arrow { width: 14px; height: 11px; color: currentColor; }
.lightbox__nav--next .arrow { transform: rotate(180deg); }   /* source points left */

/* =========================================================
   Case study pages (case-*.html)
   Same header, grid, sidebar and footer as the home page. Section titles
   sit in the 2nd column; text and visuals run across columns 3–6.
   Framer px (--u) like the rest of the site.
   ========================================================= */
.cs__shell {
  container-type: inline-size;
  --u: calc(100cqw / 1240);
}
/* Placeholders to replace: tinted so they're easy to spot */
.ph {
  background: color-mix(in srgb, var(--figma-blue) 14%, transparent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--figma-blue) 14%, transparent);
  border-radius: 2px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* Back link above the section list in the sidebar */
.cs-back {
  position: absolute;
  top: calc(var(--header-h) + 28px);
  left: 33px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 15px;
  color: var(--grey);
  pointer-events: auto;
  transition: color 0.2s;
}
.cs-back:hover { color: var(--black); }
.cs-back .arrow { color: currentColor; transition: transform 0.3s var(--ease-out); }
.cs-back:hover .arrow { transform: translateX(-3px); }

/* --- Hero: eyebrow, title, lead, facts, "In short", image --- */
.cs-hero { padding: calc(var(--header-h) + 120 * min(1px, (100vw - 2 * var(--gutter)) / 1240)) 0 0; }
.cs-hero .cs__shell > * { margin-left: calc(213 * var(--u)); }
.cs-eyebrow {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--grey);
}
.cs-title {
  max-width: calc(860 * var(--u));
  margin: 20px 0 0;
  font-size: clamp(36px, calc(64 * var(--u)), 64px);
  line-height: 1.12;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--black);
  text-wrap: balance;
}
.cs-lead {
  max-width: calc(620 * var(--u));
  margin-top: 24px;
  font-size: clamp(17px, calc(20 * var(--u)), 20px);
  line-height: 1.5;
  color: var(--grey);
}
/* One fact per grid column (cols 2–6), each under a hairline */
.cs-glance {
  display: grid;
  grid-template-columns: 204fr 204fr 204fr 204fr 212fr;   /* the grid's own columns */
  margin: calc(72 * var(--u)) 0 0;
  margin-left: calc(212 * var(--u)) !important;
}
.cs-glance > div {
  padding: 14px calc(16 * var(--u)) 0 1px;
  border-top: 1px solid var(--separator);
}
.cs-glance dt { font-size: 13px; color: var(--grey); }
.cs-glance dd { margin: 6px 0 0; font-size: 16px; line-height: 1.35; color: var(--dark-2); }

.cs-tldr {
  max-width: calc(620 * var(--u));
  margin-top: calc(56 * var(--u));
  padding: 24px 28px;
  border-radius: 8px;
  background: var(--card-bg);
}
.cs-tldr__title {
  margin-bottom: 12px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--grey);
}
.cs-tldr strong { font-weight: 600; color: var(--black); }
.cs-hero .cs-figure { margin-top: calc(72 * var(--u)); margin-left: calc(212 * var(--u) + 1px) !important; margin-right: 1px; }

/* --- Sections: title in column 2 (sticks while reading), body in 3–6 --- */
.cs-section { padding-top: calc(160 * min(1px, (100vw - 2 * var(--gutter)) / 1240)); }
.cs-section__grid {
  display: grid;
  grid-template-columns: calc(204 * var(--u)) 1fr;
  padding-left: calc(213 * var(--u));
}
.cs-section__head {
  position: sticky;
  top: calc(var(--header-h) + 32px);
  align-self: start;
  padding-right: 24px;
}
.cs-section__num { font-size: 13px; font-variant-numeric: tabular-nums; color: var(--grey); }
.cs-section__title {
  margin: 8px 0 0;
  font-size: clamp(22px, calc(28 * var(--u)), 28px);
  line-height: 1.2;
  font-weight: 700;
  color: var(--black);
}
.cs-section__body {
  display: grid;
  gap: 24px;
  min-width: 0;
  padding-right: calc(80 * var(--u));
}
.cs-section__body > .cs-text,
.cs-section__body > .cs-list,
.cs-section__body > .cs-sub { max-width: calc(640 * var(--u)); }
.cs-text {
  font-size: clamp(16px, calc(18 * var(--u)), 18px);
  line-height: 1.7;
  color: var(--dark-2);
  text-wrap: pretty;
}
.cs-sub {
  margin: 24px 0 -8px;
  font-size: 20px;
  font-weight: 600;
  color: var(--black);
}
.cs-list {
  display: grid;
  gap: 10px;
  margin: 0;
  padding: 0 0 0 18px;
  list-style: none;
}
.cs-list li {
  position: relative;
  font-size: 16px;
  line-height: 1.55;
  color: var(--dark-2);
}
.cs-list li::before {
  content: "";
  position: absolute;
  top: 0.65em;
  left: -14px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--grey);
}

/* Callout box */
.cs-note {
  display: grid;
  gap: 12px;
  max-width: calc(640 * var(--u));
  padding: 22px 26px;
  border-left: 2px solid var(--black);
  background: var(--card-bg);
}
.cs-note__title { font-size: 14px; font-weight: 600; color: var(--black); }

/* Findings: three cards side by side */
.cs-findings {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
.cs-card {
  display: grid;
  align-content: start;
  gap: 8px;
  padding: 22px;
  border-radius: 8px;
  background: var(--card-bg);
  font-size: 15px;
  line-height: 1.5;
  color: var(--dark-2);
}
.cs-card__num { font-size: 12px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--grey); }
.cs-card__title { margin: 0; font-size: 17px; font-weight: 600; color: var(--black); }

/* Options table */
.cs-table-wrap { overflow-x: auto; }
.cs-table {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
  font-size: 15px;
  line-height: 1.45;
  color: var(--dark-2);
}
.cs-table th,
.cs-table td {
  padding: 14px 16px 14px 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}
.cs-table thead th {
  padding-top: 0;
  border-bottom-color: var(--separator);
  font-size: 13px;
  font-weight: 500;
  color: var(--grey);
}
.cs-table tbody th { font-weight: 600; color: var(--black); }

/* Image / diagram slots */
.cs-figure { margin: 8px 0 0; }
.cs-figure__ph {
  display: grid;
  place-items: center;
  padding: 24px;
  border: 1px dashed var(--separator);
  border-radius: 8px;
  background: var(--photo-bg);
  font-size: 14px;
  text-align: center;
  color: var(--grey);
}
.cs-figure img { width: 100%; height: auto; border-radius: 8px; }
.cs-figure figcaption { margin-top: 10px; font-size: 13px; line-height: 1.4; color: var(--grey); }

/* Results: four big numbers under hairlines, then quotes */
.cs-metrics {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0 calc(24 * var(--u));
  margin: 8px 0;
}
.cs-metrics > div { padding-top: 14px; border-top: 1px solid var(--separator); }
.cs-metrics dt { font-size: 13px; line-height: 1.35; color: var(--grey); }
.cs-metrics dd {
  margin: 10px 0 0;
  font-size: clamp(32px, calc(44 * var(--u)), 44px);
  line-height: 1.1;
  font-weight: 700;
  color: var(--black);
}
.cs-quote {
  max-width: calc(640 * var(--u));
  margin: 8px 0 0;
  padding-left: 24px;
  border-left: 2px solid var(--separator);
}
.cs-quote p { font-size: clamp(18px, calc(22 * var(--u)), 22px); line-height: 1.45; color: var(--black); }
.cs-quote footer { margin-top: 12px; font-size: 14px; color: var(--dark-2); }
.cs-quote footer span { color: var(--grey); }

/* End of page: back / next */
.cs-end { padding: calc(160 * min(1px, (100vw - 2 * var(--gutter)) / 1240)) 0 calc(120 * min(1px, (100vw - 2 * var(--gutter)) / 1240)); }
/* Hairline from the 2nd grid line, back link left, next case right */
.cs-end__inner {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  margin-left: calc(212 * var(--u));
  padding: 28px calc(80 * var(--u)) 0 1px;
  border-top: 1px solid var(--separator);
}
.cs-end__link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: clamp(18px, calc(22 * var(--u)), 22px);
  font-weight: 600;
  color: var(--black);
}
.cs-end__link .arrow { color: currentColor; transition: transform 0.3s var(--ease-out); }
.cs-end__link:hover .arrow { transform: translateX(-4px); }
.cs-end__link--next .arrow { transform: rotate(180deg); }
.cs-end__link--next:hover .arrow { transform: rotate(180deg) translateX(-4px); }

/* =========================================================
   Entrance animations
   ========================================================= */
/* Only plays when <html> has `.intro` (set in <head>: first arrival on the
   site or a reload of this page — never on back/forward or internal links).
   Without `.intro` every element simply renders in its final state.

   Sequence (--at-* start times are computed in main.js):
   empty screen → 0.5s → title → secondary text
   → hold, during which the grid lines draw down one after another
   → photo, header, sidebar nav + "Based in" staggered and overlapping
   (cursor pops in as the photo lands) */
.word { display: inline-block; white-space: nowrap; }
.char { display: inline-block; }

/* Elements clip at the container's outer grid lines so they appear to
   emerge from underneath them */
.sidebar__inner { overflow: clip; }
.hero__shell { overflow-x: clip; }

/* No scrolling while the intro plays (class set in <head>, removed by
   main.js once the last element has landed). The scrollbar is hidden
   (see Base), so nothing shifts when it comes back. */
.scroll-lock,
.scroll-lock body { overflow: hidden; }

/* --- Hidden starting states --- */
.intro .grid-bg__cols span::before,
.intro .grid-bg__cols::after { transform: translateY(-100%); }
.intro .char {
  opacity: 0;
  filter: blur(12px);
  transform: translateY(0.18em);
}
.intro .hero__extra {
  opacity: 0;
  filter: blur(10px);
  transform: translateY(12px);
}
/* photo left 924 + width 230 + gap 86 ≈ 330 Framer px past the right edge */
.intro .hero__photo { translate: calc(330 * var(--u)) 0; }
.intro .figma-cursor__icon,
.intro .figma-cursor__label { opacity: 0; transform: scale(0.4); }
.intro .site-header__inner { transform: translateY(-100%); }
/* `translate` so it doesn't fight the nav's centering transform */
.intro .section-nav,
.intro .based { translate: calc(-100% - 40px) 0; }

/* --- Timeline --- */
/* Lines slide down from above the viewport, left → right; each starts --line-lag after the
   previous one so its tip trails ~250px behind (lag computed in main.js) */
.intro.is-ready .grid-bg__cols span::before,
.intro.is-ready .grid-bg__cols::after {
  animation: line-draw var(--line-dur) cubic-bezier(0.45, 0, 0.55, 1) forwards;
  animation-delay: calc(var(--at-grid) + var(--l, 0) * var(--line-lag));
}
.intro.is-ready .char {
  animation: char-in 0.9s var(--ease-out) forwards;
  animation-delay: calc(var(--at-title) + var(--i) * 35ms);
}
.intro.is-ready .hero__extra {
  animation: fade-up-in 0.9s var(--at-extra) var(--ease-out) forwards;
}
.intro.is-ready .hero__photo {
  animation: slide-in-x 0.8s var(--at-photo) var(--ease-out) forwards;
}
.intro.is-ready .figma-cursor__icon {
  animation: pop-in 0.55s var(--at-cursor) var(--ease-spring) forwards;
}
.intro.is-ready .figma-cursor__label {
  animation: pop-in 0.55s calc(var(--at-cursor) + 100ms) var(--ease-spring) forwards;
}
.intro.is-ready .site-header__inner {
  animation: header-drop 0.8s var(--at-header) var(--ease-out) forwards;
}
.intro.is-ready .section-nav,
.intro.is-ready .based {
  animation: slide-in-x 0.8s var(--at-sidebar) var(--ease-out) forwards;
}
/* Mobile scroll hint fades in with the sidebar step */
.intro .scroll-hint { opacity: 0; }
.intro.is-ready .scroll-hint {
  animation: fade-up-in 0.8s var(--at-sidebar) var(--ease-out) forwards;
}

@keyframes char-in    { to { opacity: 1; filter: blur(0); transform: none; } }
@keyframes fade-up-in { to { opacity: 1; filter: blur(0); transform: none; } }
@keyframes slide-in-x { to { translate: 0 0; } }
@keyframes pop-in     { to { opacity: 1; transform: none; } }
@keyframes line-draw  { to { transform: none; } }
@keyframes header-drop { to { transform: none; } }

/* =========================================================
   Responsive
   ========================================================= */
/* Mobile + tablet (< 1000px). Built from a 580px-wide design frame:
   positions are in that frame's px and scale with the viewport, the same
   way desktop scales from its 1240px frame. Text has readable minimums. */
@media (max-width: 999px) {
  :root {
    /* 1 frame px for header sizes: the smaller of the width and height
       scales, so the header stays compact on short, wide screens */
    --f: min(calc(100vw / 580), calc(100svh / 1046));
    --gutter: calc(16 * 100vw / 580);     /* grid edges follow the width */
    --header-h: clamp(56px, calc(70 * var(--f)), 105px);
    --cols: 127fr 145fr 136fr 135fr;     /* lines at 16 · 143 · 288 · 424 · 559 */
    --burger-w: clamp(18px, calc(18 * var(--f)), 26px);
    --burger-gap: clamp(4px, calc(5 * var(--f)), 7px);
    --nav-gap: 12px;   /* fixed at every phone/tablet size */
    /* Burger gets the same space on both sides as the Contacts link */
    --header-pad-r: var(--nav-gap);
    --hit-x: 11px;   /* the 12px phone gap, stopping just short of the separator */
    --hit-h: 52px;   /* of the 56px phone header */
  }

  /* Four columns: 5 lines (edges + 3 inner) */
  .grid-bg__cols span:nth-child(n + 5) { display: none; }
  .grid-bg__cols::after { --l: 4; }

  /* --- Header: full width, YP · CV | Contacts | ☰ --- */
  .site-header__inner {
    width: 100%;
    border-inline: none;
    padding: 0 var(--header-pad-r) 0 max(16px, calc(19 * var(--f)));
  }
  .logo { font-size: clamp(28px, calc(34 * var(--f)), 60px); }
  .top-nav { gap: var(--nav-gap); }
  .top-link { font-size: clamp(15px, calc(17 * var(--f)), 24px); }
  .divider { height: clamp(22px, calc(34 * var(--f)), 52px); }
  .menu-only.divider { display: block; }
  .menu-toggle { display: inline-flex; }
  .top-nav > .menu-toggle::after { right: calc(-1 * var(--header-pad-r)); }   /* reach the screen edge */  .theme-toggle { width: 28px; height: 28px; }
  .theme-toggle__icon { width: 24px; height: 24px; }

  /* CV moves from the header bar into the Contacts dropdown */
  .desktop-only { display: none; }
  .menu-only-item { display: list-item; }

  /* --- Dropdowns (Contacts, menu): the header itself grows downward ---
     The panel sits right on the header's bottom line and its height animates
     from 0 to its content (grid rows 0fr → 1fr, toggled by .is-open in
     main.js). While a panel is open the header's own line is hidden and the
     panel's bottom border takes over, so the line travels down with it. */
  .contacts,
  .menu-sheet:not([hidden]) {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    display: grid;
    grid-template-rows: 0fr;
    /* stretch (not desktop's `center`) so the content is clipped by the
       shrinking row instead of overflowing up over the header */
    align-items: stretch;
    padding: 0 max(16px, calc(19 * var(--f)));
    background: var(--bg);
    border-bottom: 1px solid var(--separator);
    transition:
      grid-template-rows 0.5s var(--ease-out),
      padding 0.5s var(--ease-out);
  }
  .contacts.is-open { grid-template-rows: 1fr; padding-block: 12px 20px; }
  .menu-sheet.is-open { grid-template-rows: 1fr; padding-block: 20px 24px; }
  .contacts__inner,
  .menu-sheet__inner {
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  .contacts__inner { gap: 4px; justify-content: flex-start; align-items: stretch; }
  /* Links on the left, "Based in" on the right; the clock's baseline lines
     up with the last link (Experience) along the bottom of the dropdown */
  .menu-sheet__inner {
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-end;              /* fallback */
    align-items: last baseline;
    gap: 16px;
  }
  .site-header__inner.has-open { border-bottom-color: transparent; }

  .contacts__inner > .divider,
  .contacts > .divider { display: none; }
  .contacts__inner > :last-child { margin-right: 0; }
  .contacts__socials { flex-direction: column; gap: 0; }
  /* Bigger text and taller full-width rows: easier to read and to tap */
  .contacts__socials .top-link { width: 100%; height: 52px; font-size: 17px; gap: 7px; }
  .contacts__socials .arrow { opacity: 1; transform: rotate(135deg); width: 12px; height: 10px; }
  .email-pill { height: 50px; margin-top: 8px; font-size: 16.5px; }
  .contacts-toggle { margin-left: 0; }   /* mobile keeps its 12px gaps */
  .contacts-toggle .arrow--toggle,
  .contacts-toggle:hover .arrow--toggle { opacity: 1; transform: rotate(-90deg); }
  .contacts-toggle[aria-expanded="true"] .arrow--toggle { transform: rotate(90deg); }

  /* Menu: section links + location (replaces the desktop sidebar) */
  .menu-sheet__links { display: grid; gap: 4px; }
  .menu-sheet__links a {
    display: block;
    padding: 6px 0;
    font-size: clamp(24px, calc(26 * var(--f)), 40px);
    line-height: 1.15;
    color: var(--grey);
    transition: color 0.2s;
  }
  .menu-sheet__links a:hover,
  .menu-sheet__links a[aria-current="true"] { color: var(--active, var(--dark-2)); font-weight: 700; }
  /* "Based in" sits bottom-right of the menu, right-aligned */
  .menu-sheet__based {
    display: grid;
    gap: 8px;
    justify-items: end;
    text-align: right;
  }

  .sidebar { display: none; }

  /* --- Hero: exactly one screen tall, laid out on the 580 × 1046 design
     frame (header included). Positions are measured from the screen's
     top-left corner:
       --ux  1 frame px horizontally (follows screen width → stays on the grid)
       --uy  1 frame px vertically   (follows screen height → fills 100vh)
       --us  the smaller of the two, for font and photo sizes so nothing
             overflows on unusually short or wide screens --- */
  .hero {
    height: 100vh;
    height: 100svh;
    min-height: 0;
    padding: 0;
    align-items: stretch;
  }
  .hero__shell { width: 100%; }
  .hero__stage {
    --ux: calc(100cqw / 580);
    --uy: calc(100svh / 1046);
    --us: min(var(--ux), var(--uy));
    --u: var(--us);
    height: 100%;
  }

  /* Mobile layout v2 (the previous "primary" version is git tag
     mobile-primary): headline at the 1st grid line, subtext at the 2nd,
     cursor above-left of the photo, bigger photo on the right,
     scroll hint bottom-left */
  .hero__title {
    top: calc(197 * var(--uy));
    /* Flush after the 1st (left edge) grid line, which is 1px wide; the
       letters' own side spacing keeps them just clear of it */
    left: calc(var(--gutter) + 1px);
  }
  .hero__hi { font-size: calc(65 * var(--us)); }
  .hero__name { font-size: calc(76 * var(--us)); }

  .hero__extra {
    top: var(--extra-top);
    /* 2px clear of the 2nd grid line (line = gutter + 127/543 of the
       inner width; the line itself is 1px wide) */
    left: calc(var(--gutter) + (100cqw - 2 * var(--gutter)) * 127 / 543 + 1px + 2px);
    right: calc(var(--gutter) + 1px + 10px);   /* 10px clear of the 1px right grid line */
    gap: max(6px, calc(8 * var(--us)));
    /* Usual size, but never so big that "Product designer who brings
       visual polish" (~19em wide) can't fit on its first row: the cap is
       the text's own width (2nd grid line to 11px before the last) / 19.7,
       so narrow phones get slightly smaller text instead of a third row */
    font-size: min(
      max(14px, calc(12.5 * var(--us))),
      calc(((100cqw - 2 * var(--gutter)) * 416 / 543 - 14px) / 19.7)
    );
    max-width: none;   /* phones use left/right bounds instead */
  }

  /* Photo on the right, 5% under its 291 design width, centred between
     the 3rd and 4th grid lines (288 and 424: line = gutter + inner width
     × 272/543 and × 408/543, each 1px wide, so the midpoint is 340/543 + .5px) */
  .hero__stage {
    /* Secondary text always 24px under the headline, whatever the
       screen's shape: headline top + its two lines (65 + 76 at
       line-height 1.1) + 24px */
    --extra-top: calc(197 * var(--uy) + (65 + 76) * 1.1 * var(--us) + 24px);
    --photo-w: calc(291 * 0.95 * var(--us));
    --photo-left: calc(var(--gutter) + (100cqw - 2 * var(--gutter)) * 340 / 543 + 0.5px - var(--photo-w) / 2);
  }
  .hero__photo {
    /* Its usual spot, but never closer than ~16px under the secondary
       text (up to 4 lines, ~94px) on short screens */
    top: max(calc(523 * var(--uy)), calc(var(--extra-top) + 110px));
    left: var(--photo-left);
    width: var(--photo-w);
  }
  /* Enters from the right, emerging from under the right grid line: it
     starts just past that line, and the stage is clipped at the line on
     the right (nothing else extends that far, so the clip is invisible
     once the photo has landed) */
  .hero__stage { clip-path: inset(-100vh calc(var(--gutter) + 1px) -100vh -100vw); }
  .intro .hero__photo { translate: calc(100cqw - var(--gutter) - var(--photo-left)) 0; }

  /* "scroll" hint: bottom left, just inside the left grid line */
  .hero { position: relative; }
  .scroll-hint {
    position: absolute;
    left: calc(var(--gutter) + 8px);
    bottom: calc(100svh * 68 / 1046);   /* 60 px of the 1046px-tall design frame */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    color: var(--grey);
    pointer-events: none;
  }

  /* Arrow + one-row label (1px smaller than desktop), centred as one group
     between the 1st grid line and the photo's left edge. The label is in
     the flow here so the group's width is known; the drift in main.js is
     clamped so it never crosses onto the photo. */
  .figma-cursor {
    top: calc(515 * var(--uy) + 62px);   /* beside the photo's top-left */
    left: calc((var(--gutter) + 1px + var(--photo-left)) / 2);
    translate: -50% 0;
    width: max-content;
  }
  .figma-cursor__label {
    position: static;
    display: block;
    margin: -1px 0 0 14px;   /* same spot as before: under-right of the arrow */
    font-size: 11px;
  }

  /* --- Work: cards span the full grid, image on top, then the text --- */
  .work {
    margin-top: 0;
    padding: 40px 0 64px;
  }
  /* Section label: a cell in the first column, boxed by a grid-coloured
     line above and below, opening every section */
  .section-label {
    position: static;
    width: calc(100% * 127 / 543 - 1px);
    height: auto;
    overflow: visible;
    clip: auto;
    margin: 0 0 24px 1px;
    padding: 7px 0 8px;
    border-block: 1px solid var(--line);
    font-size: 16px;
    font-weight: 600;
    line-height: 1;
    text-align: center;
    text-transform: lowercase;
    color: var(--label);
  }

  .work__list {
    gap: 24px;
    margin-left: 1px;
  }
  .work-card,
  .work-card--platform,
  .work-card--betslip,
  .work-card--bonus,
  .work-card--archive {
    grid-template-columns: 1fr;
    gap: 20px;
    padding: 16px;
  }
  .work-card:not(.work-card--betslip) .work-card__media { order: 0; }
  .work-card__body { gap: 24px; }
  .work-card__title { font-size: clamp(28px, calc(36 * 100vw / 580), 40px); }
  .work-card__title br { display: none; }   /* wrap to the screen instead */
  .work-card__desc { margin-top: 10px; font-size: 16px; }
  .work-card__label { font-size: 12px; }
  .work-card__facts li { font-size: 13px; }
  .work-card__facts li br { display: none; }
  /* List on the left, the "View Project" button bottom-right, its bottom
     level with the list's last row */
  .work-card__foot,
  .work-card--betslip .work-card__foot,
  .work-card--bonus .work-card__foot,
  .work-card--archive .work-card__foot {
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
  }
  .work-card__facts { flex: 1; min-width: 0; }
  .btn-project { height: 40px; padding: 0 14px 0 18px; font-size: 14px; }   /* ≤140px wide */

  /* Labels can open a section in another column: --col2 sits between
     the 2nd and 3rd grid lines */
  .section-label--col2 {
    margin-left: calc(100% * 127 / 543 + 1px);
    width: calc(100% * 145 / 543 - 1px);
  }
  /* --col3: between the 3rd and 4th grid lines */
  .section-label--col3 {
    margin-left: calc(100% * 272 / 543 + 1px);
    width: calc(100% * 136 / 543 - 1px);
  }

  /* --- Values: words full width, then the switch + text and the links
     in the second column (like the hero's secondary text) --- */
  .values {
    margin-top: 0;
    padding: 96px 0 64px;   /* + Work's 64px bottom = 160px between the sections */
  }
  .values__stage {
    position: static;
    height: auto;
    display: grid;
    --wf: clamp(36px, calc(68 * 100vw / 580), 72px);   /* big-word size */
    --shift-0: 100cqw;
    --shift-1: 140cqw;
    --shift-2: 180cqw;
  }
  .values__words {
    position: relative;
    top: auto;
    left: auto;
    width: auto;
    margin: 0 1px;
    height: calc(var(--wf) * (1.2 + 2 * 1.16));
  }
  .values__line { left: 0; font-size: var(--wf); }
  .values__line:nth-child(2) { top: calc(var(--wf) * 1.16); }
  .values__line:nth-child(3) { top: calc(var(--wf) * 2.32); }

  .values__about,
  .values__links {
    position: static;
    width: auto;
    margin-left: calc(100% * 127 / 543 + 3px);   /* 2px clear of the 2nd line */
    margin-right: 11px;
  }
  .values__about { margin-top: 32px; }
  .values__tabs { gap: 24px; }
  .values__tab { font-size: 16px; }
  .values__panels { margin-top: 14px; }
  .values__panel { font-size: 15px; line-height: 1.7; }
  .values__links { margin-top: 28px; margin-left: 3px; gap: 2px; }   /* back at the 1st line */
  .values__link { font-size: 15px; }

  /* --- Inspiration: heading full width from the 1st line; text, topics
     and photo in the second column --- */
  .inspo {
    margin-top: 0;
    padding: 96px 0 64px;   /* + Values' 64px bottom = 160px between the sections */
  }
  .inspo__stage {
    position: static;
    height: auto;
    display: grid;
  }
  .inspo__heading,
  .inspo__text,
  .inspo__photo,
  .inspo__topics {
    position: static;
    width: auto;
    translate: none;
  }
  .inspo__heading {
    margin: 0 1px;
    font-size: clamp(36px, calc(68 * 100vw / 580), 72px);
    line-height: 1.15;
    white-space: normal;
  }
  .inspo__heading br { display: none; }   /* wrap to the screen instead */
  .inspo__text,
  .inspo__topics {
    margin-left: calc(100% * 127 / 543 + 3px);   /* 2px clear of the 2nd line */
    margin-right: 11px;
  }
  .inspo__text { margin-top: 28px; font-size: 15px; line-height: 1.7; }
  .inspo__topics {
    display: flex;
    flex-wrap: wrap;
    gap: 0 18px;
    margin-top: 20px;
  }
  .inspo__topic { font-size: 15px; }
  .inspo__photo {
    order: 1;   /* after the topics, so a tap changes the photo just below */
    margin: 16px 1px 0 calc(100% * 127 / 543 + 1px);   /* 2nd line to the outer line */
  }
  .inspo__frame { border-radius: 0; }   /* square corners on phones */
  .inspo__caption { font-size: 15px; }

  /* Label in the 4th column (from the 4th grid line to the outer one) */
  .section-label--col4 {
    margin-left: calc(100% * 408 / 543 + 1px);
    width: calc(100% * 135 / 543 - 2px);
  }

  /* --- Photos: heading full width, then the strip across the whole grid,
     photos at about half their desktop size --- */
  .photos {
    margin-top: 0;
    padding: 96px 0 64px;   /* + Inspiration's 64px bottom = 160px */
  }
  .photos__stage {
    position: static;
    height: auto;
    --pu: calc(100vw / 780);
  }
  .photos__heading,
  .photos__gallery {
    position: static;
  }
  /* Same size as the other section headings; "What I see," keeps its own
     line and the rest wraps to the screen */
  .photos__heading {
    margin: 0 1px;
    font-size: clamp(36px, calc(68 * 100vw / 580), 72px);
    line-height: 1.15;
    white-space: normal;
  }
  .photos__gallery { margin: 32px 1px 0; }
  .photos__bar { padding-inline: 2px 10px; }
  .photos__scroller { margin-top: 14px; }
  .photos__item { border-radius: 8px; }

  /* --- Experience: company names full width from the 1st line; roles
     in the second column, dates under each title --- */
  .exp {
    margin-top: 0;
    padding: 96px 0 96px;   /* + Photos' 64px bottom = 160px */
  }
  .exp__company + .exp__company { margin-top: 56px; }
  .exp__name {
    margin: 0 1px;
    font-size: clamp(36px, calc(68 * 100vw / 580), 72px);
    line-height: 1.15;
  }
  .exp__roles { margin-top: 24px; }
  .exp__role {
    grid-template-columns: 1fr;
    align-items: start;
    padding: 0 11px 0 calc(100% * 127 / 543 + 3px);   /* 2px clear of the 2nd line */
  }
  .exp__role + .exp__role { margin-top: 20px; }
  .exp__title { font-size: 20px; }
  .exp__dates { margin-top: 4px; font-size: 14px; }
  .exp__details { gap: 10px; margin-top: 14px; padding-right: 0; }
  .exp__details li { font-size: 14px; line-height: 1.35; }

  /* --- Footer: one bar as tall as the header, full width like it; the
     credits and version stacked on the left, the smile on two lines on
     the right. Every line has the same 19px line box, so the right
     column's two lines sit level with the two rows on the left. --- */
  .exp { padding-bottom: 64px; }
  .site-footer { margin-top: 0; }
  .site-footer__inner {
    width: 100%;
    height: var(--header-h);   /* exactly the header's height */
    grid-template-columns: 1fr auto;
    grid-template-rows: auto auto;
    align-content: center;
    align-items: start;
    column-gap: 16px;
    padding: 0 var(--gutter);
    border-inline: none;
    font-size: 12px;
    line-height: 19px;
  }
  .site-footer__by { grid-area: 1 / 1; }
  .site-footer__version { grid-area: 2 / 1; justify-self: start; }
  .site-footer__smile { grid-area: 1 / 2 / 3 / 3; text-align: right; }
  .site-footer__br { display: inline; }

  /* --- Photo viewer: full width photo; thumbnails, then the arrows and
     counter along the bottom --- */
  .lightbox__frame { inset: 68px 12px 152px; }
  .lightbox__frame img {
    max-height: calc(100vh - 220px);
    max-height: calc(100dvh - 220px);
  }
  .lightbox__nav { top: auto; bottom: 20px; translate: none; width: 44px; height: 44px; }
  .lightbox__nav--prev { left: 16px; }
  .lightbox__nav--next { right: 16px; }
  .lightbox__count { bottom: 34px; }
  .lightbox__thumbs { bottom: 80px; width: calc(100vw - 24px); gap: 6px; }
  .lightbox__thumbs::before,
  .lightbox__thumbs::after { flex-basis: calc(50% - 25px); }
  .lightbox__thumb { width: 44px; height: 44px; }
  .lightbox__close { top: 12px; right: 12px; width: 44px; height: 44px; }

  /* --- Case study pages: one column, text from the 1st grid line --- */
  .cs-hero { padding-top: calc(var(--header-h) + 56px); }
  .cs-hero .cs__shell > *,
  .cs-glance,
  .cs-hero .cs-figure { margin-left: 3px !important; margin-right: 11px; }
  .cs-title, .cs-lead, .cs-tldr { max-width: none; }
  .cs-glance { grid-template-columns: 1fr 1fr; gap: 20px 16px; margin-top: 40px; }
  .cs-glance > div { padding-right: 0; }
  .cs-tldr { margin-top: 32px; padding: 20px; }
  .cs-hero .cs-figure { margin-top: 32px; }
  .cs-section { padding-top: 88px; }
  .cs-section__grid {
    grid-template-columns: 1fr;
    gap: 20px;
    padding: 0 11px 0 3px;
  }
  .cs-section__head { position: static; padding-right: 0; }
  .cs-section__body { padding-right: 0; }
  .cs-section__body > .cs-text,
  .cs-section__body > .cs-list,
  .cs-section__body > .cs-sub,
  .cs-note, .cs-quote { max-width: none; }
  .cs-findings { grid-template-columns: 1fr; }
  .cs-metrics { grid-template-columns: 1fr 1fr; gap: 24px 16px; }
  .cs-end { padding: 88px 0 64px; }
  .cs-end__inner { margin: 0 11px 0 3px; padding: 24px 0 0; }
  .cs-back { display: none; }   /* the menu sheet has "← All work" */

  /* Jumping to a section from the menu lands with its label right under
     the header: the space above the label scrolls away behind it */
  .work { scroll-margin-top: -40px; }
  .values, .inspo, .photos, .exp { scroll-margin-top: -96px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    transition-duration: 0.01ms !important;
  }
  .scroll-hint__chevrons path { animation: none !important; }
}
