/* =============================================================================
   Valeria Sablina — portfolio
   The palette below is taken from the real Qonversion design-system tokens, so the
   site itself behaves like the systems the cases describe: one set of semantic
   tokens, two themes, no hard-coded colours below this block.
   ========================================================================== */

:root {
  /* Surfaces and text */
  --bg: #fafafa;
  --surface: #ffffff;
  --ink: #17181c;
  --muted: #5c5f6a;
  --border: #ececef;

  /* Accents, from Valeria's palette (17.08): crimson carries every action, lime is a
     marker only — never a text colour. Her #B7FEB6 sits at 1.2:1 on white, so it can
     only ever be a plate with dark ink on top; the crimson takes the interactive role
     and clears 4.5:1 as text and as a button ground. */
  --accent: #db175c;
  --accent-hover: #b01049;
  --marker: #b7feb6;

  /* Derived */
  --on-accent: #ffffff;
  --on-marker: #17181c;
  --shadow: 0 1px 2px rgba(23, 24, 28, .04), 0 12px 32px rgba(23, 24, 28, .06);
  --radius: 14px;
  --radius-sm: 8px;

  /* Type */
  /* Manrope, chosen by Valeria (17.08). It carries Cyrillic, so EN and RU headings are
     finally set in the same face — the old Space Grotesk had none. */
  --font-display: "Manrope", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-body: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;

  /* Layout */
  --wrap: 1120px;
  --gutter: 24px;
  --section-y: 7rem;
}

[data-theme="dark"] {
  --bg: #17181c;
  --surface: #242830;
  --ink: #f4f4f6;
  --muted: #9a9daa;
  --border: #33363f;

  /* The dark theme takes a lighter tint of the same crimson — #db175c drops to 3.0:1 on
     the dark surface, #f76a97 holds 5.2:1. Same move the old violet made. */
  --accent: #f76a97;
  --accent-hover: #ffa0bf;
  --marker: #b7feb6;

  --on-accent: #17181c;

  --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 14px 36px rgba(0, 0, 0, .32);
}

/* ------------------------------------------------------------------ base */

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: 96px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1.06rem;
  line-height: 1.65;
  font-weight: 400;
  overflow-x: hidden; /* the page itself never scrolls sideways; wide bands scroll inside */
  -webkit-font-smoothing: antialiased;
  transition: background-color .25s ease, color .25s ease;
}

img { display: block; max-width: 100%; height: auto; }

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); text-decoration: underline; text-underline-offset: 3px; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -.02em;
  margin: 0;
}

/* Manrope covers Cyrillic, so the RU page no longer needs its own display face — the
   earlier Inter fallback is gone. Russian still runs longer, hence the tighter tracking. */
[lang="ru"] h1,
[lang="ru"] h2,
[lang="ru"] h3,
[lang="ru"] .hero__thesis {
  letter-spacing: -.025em;
}

/* Russian runs longer than English; at the EN measure the thesis broke inside
   "UX/UI-дизайнер". */
[lang="ru"] .hero__thesis { max-width: 30ch; }
[lang="ru"] .section__head h2 { max-width: 30ch; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--surface);
  color: var(--ink);
  padding: .75rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.skip-link:focus { left: 12px; top: 12px; }

/* --------------------------------------------------------------- top bar */

.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}

.topbar__inner {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: .8rem var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -.01em;
}
.brand:hover { color: var(--ink); text-decoration: none; }

/* Valeria's own mark, supplied 19.08 — it replaced the placeholder VS monogram. */
.brand__mark {
  width: 26px;
  height: 26px;
  flex: none;
  display: block;
}
/* Valeria's mark is a near-black silhouette: on a dark background it would disappear,
   so the dark theme shows an inverted copy of the same shape. */
html[data-theme="dark"] .brand__mark { filter: invert(1); }

.topbar__controls {
  display: flex;
  align-items: center;
  gap: 1.1rem;
}

.langs {
  display: inline-flex;
  align-items: center;
  gap: .1rem;
  font-family: var(--font-mono);
  font-size: .78rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px;
  background: var(--surface);
}
.langs__item {
  display: inline-block;
  padding: .25rem .6rem;
  border-radius: 999px;
  color: var(--muted);
}
.langs__item:hover { color: var(--ink); text-decoration: none; }
.langs__item.is-active {
  background: var(--ink);
  color: var(--bg);
}

.token-toggle {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  font-family: var(--font-mono);
  font-size: .78rem;
  color: var(--muted);
}
.token-toggle__key { letter-spacing: .02em; }
.token-toggle__values {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
}
.token-toggle__btn {
  font: inherit;
  color: var(--muted);
  background: none;
  border: 0;
  padding: .2rem .3rem;
  border-radius: 5px;
  cursor: pointer;
  transition: color .15s ease, background-color .15s ease;
}
.token-toggle__btn:hover { color: var(--ink); }
.token-toggle__btn[aria-pressed="true"] {
  color: var(--on-marker);
  background: var(--marker);
  font-weight: 500;
}
.token-toggle__sep { opacity: .5; }

/* ------------------------------------------------------------------ hero */

.hero {
  padding: clamp(3.5rem, 9vw, 7rem) 0 clamp(3rem, 7vw, 5rem);
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: .78rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 1rem;
}

.hero__name {
  font-size: clamp(2.6rem, 6vw, 4.4rem);
  margin: 0 0 .6rem;
}

.hero__thesis {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.2rem, 2.5vw, 1.75rem);
  line-height: 1.3;
  letter-spacing: -.01em;
  margin: 0 0 1.1rem;
  max-width: 22ch;
}

.hero__sub {
  color: var(--muted);
  max-width: 52ch;
  margin: 0 0 2rem;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  margin-bottom: 3rem;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: .8rem 1.5rem;
  border-radius: 999px;
  font-weight: 500;
  font-size: .98rem;
  border: 1px solid transparent;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.btn:hover { text-decoration: none; }

.btn--primary { background: var(--accent); color: var(--on-accent); }
.btn--primary:hover { background: var(--accent-hover); color: var(--on-accent); }

.btn--ghost { border-color: var(--border); color: var(--ink); background: var(--surface); }
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); }

/* The email is a button, not a mailto link: one click puts it on the clipboard. */
.btn.copy {
  cursor: copy;
  font-family: inherit;
  line-height: inherit;
}
.btn.copy.is-copied {
  background: var(--marker);
  border-color: var(--marker);
  color: var(--on-marker);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.facts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: .9rem 1.6rem;
  border-top: 1px solid var(--border);
  padding-top: 1.6rem;
}
.facts__item {
  font-family: var(--font-mono);
  font-size: .84rem;
  line-height: 1.5;
  color: var(--muted);
  padding-left: 1.1rem;
  position: relative;
}
.facts__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: .5em;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: var(--marker);
}

/* -------------------------------------------------------------- sections */

.section { padding: var(--section-y) 0; border-top: 1px solid var(--border); }
.section--about { background: var(--surface); }

.section__head { margin-bottom: 2.5rem; }
.section__head h2 {
  font-size: clamp(1.6rem, 3.6vw, 2rem);
  margin: 0 0 .9rem;
  max-width: 24ch;
}

.lede {
  color: var(--muted);
  max-width: 62ch;
  margin: 0;
  font-size: 1.06rem;
}

.prose { max-width: 66ch; margin: 2.2rem 0; }
.prose p { margin: 0 0 1.15rem; }
.prose p:last-child { margin-bottom: 0; }

/* ------------------------------------------------------- spec table */
/* The signature element: case metadata rendered like a specification sheet,
   monospaced, with dotted leaders running from the label to the value. */

.spec {
  margin: 0;
  padding: 1.4rem 1.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  font-family: var(--font-mono);
  font-size: .86rem;
  line-height: 1.6;
}

.spec__row {
  display: grid;
  grid-template-columns: minmax(9rem, 13rem) 1fr;
  gap: 0 1rem;
  padding: .5rem 0;
}
.spec__row + .spec__row { border-top: 1px solid var(--border); }

.spec dt {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  color: var(--muted);
  text-transform: lowercase;
  letter-spacing: .02em;
}
.spec dd {
  margin: 0;
  color: var(--ink);
  font-weight: 500;
}

.spec--contact dd a { font-weight: 500; }

.mark {
  background: var(--marker);
  color: var(--on-marker);
  padding: .05em .3em;
  border-radius: 4px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* --------------------------------------------------------- findings list */

.findings {
  list-style: none;
  margin: 2rem 0;
  padding: 0;
  display: grid;
  gap: .8rem;
  max-width: 72ch;
}
.findings li {
  position: relative;
  padding: .9rem 1.1rem .9rem 2.4rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 1rem;
}
.findings li::before {
  content: "";
  position: absolute;
  left: 1.1rem;
  top: 1.35em;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--marker);
}
/* Same treatment as .mark: lime stays a marker with dark ink on top, never a text colour.
   A translucent lime went muddy over the dark surface. */
.findings b {
  font-family: var(--font-mono);
  font-weight: 500;
  background: var(--marker);
  color: var(--on-marker);
  padding: .02em .28em;
  border-radius: 4px;
}

/* ---------------------------------------------------------------- figures */

.fig { margin: 2.4rem 0 0; }
.fig--narrow { max-width: 760px; }
/* Sheets that are much taller than they are wide: the frame hugs the artwork
   instead of stranding it in the middle of a full-width box. */
.fig--tall { max-width: 560px; }

.fig > img,
.shot img,
.grid-2 img {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}

figcaption {
  margin-top: .85rem;
  font-family: var(--font-mono);
  font-size: .78rem;
  line-height: 1.5;
  color: var(--muted);
}

.hint {
  display: inline-block;
  margin-left: .4rem;
  padding: .1rem .45rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: .72rem;
  white-space: nowrap;
}
.hint--block {
  display: block;
  width: fit-content;
  margin: .85rem 0 0;
  font-family: var(--font-mono);
  color: var(--muted);
}

/* pair — two shots side by side on desktop, stacked on mobile */
.pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  align-items: start;
}

/* stack — the same labelled comparison as .pair, but one above the other. Used when the
   two source exports have very different proportions and a side-by-side would leave a hole. */
.stack { display: grid; gap: 1.8rem; }

.shot { display: flex; flex-direction: column; gap: .6rem; }
.shot__label {
  font-family: var(--font-mono);
  font-size: .74rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}

.grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
}

/* scroller — wide canvases keep their scale and scroll inside their own frame */
.scroller {
  overflow-x: auto;
  overflow-y: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  padding: 1rem;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.scroller > img {
  height: var(--band-h, 320px);
  width: auto;
  max-width: none;
  border-radius: var(--radius-sm);
}

/* tall — very tall sheets are capped and scroll vertically inside the frame */
.tall {
  max-height: 560px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  padding: 1rem;
  scrollbar-width: thin;
}
.tall img { border-radius: var(--radius-sm); margin: 0 auto; }

/* phones — a row of mobile screens at a fixed 220px width */
.phones {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
}
/* Sized by height, not width: the source exports differ slightly in aspect ratio, and a
   fixed width left the row ragged along the bottom. At 480px tall they land near the
   intended ~220px width and align. */
.phones img {
  flex: none;
  height: 480px;
  width: auto;
  max-width: none;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
}

/* ------------------------------------------------------------------ grid */
/* Close-ups laid out in equal columns. Cells align to the top: the sheets
   behind them have different proportions and stretching would lie about them. */

.grid {
  display: grid;
  gap: 1.5rem;
  align-items: start;
}
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
/* A wide screen next to a phone: the pair reads as one page at two breakpoints, so the
   columns are deliberately unequal and both shots are capped in height. */
.grid--bp { grid-template-columns: minmax(0, 1.9fr) minmax(0, 1fr); }
.grid--bp .shot img {
  max-height: 520px;
  object-fit: cover;
  object-position: 50% 0;
  border-radius: var(--radius-sm);
}
.grid .shot img { width: 100%; }
/* Phone shots vary from one screen to a long scrolled page; inside a row they are capped
   and cropped from the top, and the lightbox shows the whole thing. */
.grid--phones .shot img {
  max-height: 620px;
  object-fit: cover;
  object-position: 50% 0;
  border-radius: var(--radius-sm);
}

/* Sub-heading above a group of shots inside a case body. */
.fig-title {
  font-size: 1.15rem;
  font-weight: 500;
  margin: 2.6rem 0 .9rem;
}

/* --------------------------------------------------------------- gallery */

.subcase { margin-top: 3.5rem; }
.subcase:first-of-type { margin-top: 0; }
.subcase h3 {
  font-size: 1.25rem;
  font-weight: 500;
  margin: 0 0 .6rem;
}
.subcase__note {
  color: var(--muted);
  max-width: 62ch;
  margin: 0 0 1.4rem;
}
.subcase .pair { margin-top: 1.2rem; }

/* ----------------------------------------------------------------- about */

.about {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: 3rem;
  align-items: start;
}
.about .prose { margin-top: 0; }

.about__subtitle {
  font-family: var(--font-mono);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 1rem;
}

.chips {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
}
.chips li {
  font-family: var(--font-mono);
  font-size: .8rem;
  padding: .35rem .7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--muted);
  background: var(--bg);
}

.contact { margin-top: 3.5rem; }
.contact__title {
  font-size: 1.25rem;
  font-weight: 500;
  margin: 0 0 1.2rem;
}
.spec--contact { background: var(--bg); }

/* ---------------------------------------------------------------- footer */

.footer {
  border-top: 1px solid var(--border);
  padding: 2.5rem 0 3.5rem;
}
/* One row: signature on the left, links on the right. The back-to-top button is not part
   of it — it is fixed to the viewport (see .to-top). */
.footer__inner {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 1rem 2rem;
}
.footer__name { grid-area: 1 / 1; }
.footer__links { grid-area: 1 / 2; justify-self: end; }


.footer__name {
  margin: 0;
  font-family: var(--font-mono);
  font-size: .8rem;
  color: var(--muted);
}
.footer__year {
  color: var(--muted);
  opacity: .8;
  margin-left: .35rem;
}
/* Back to top: fixed to the viewport and hidden on the first screen, per Valeria (20.08).
   It appears once the reader has scrolled roughly one screen down. Without JS the button
   stays visible rather than disappearing for good. */
.to-top {
  position: fixed;
  right: var(--gutter);
  bottom: calc(var(--gutter) + .4rem);
  z-index: 40;
  font-family: var(--font-mono);
  font-size: .78rem;
  color: var(--muted);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: .45rem 1rem;
  cursor: pointer;
  box-shadow: var(--shadow);
  transition: color .15s ease, border-color .15s ease, opacity .2s ease, transform .2s ease;
}
.to-top:hover { color: var(--ink); border-color: var(--accent); }

/* JS decides when it shows; the class is added only after the first screen. */
.js .to-top {
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
}
.js .to-top.is-visible {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* While the lightbox is open the page behind it is frozen, so a floating button that
   scrolls that page has nothing to do — and it must not catch the focus either. */
body.is-locked .to-top,
body.is-locked .to-top.is-visible {   /* must outrank .js .to-top.is-visible */
  opacity: 0;
  pointer-events: none;
}


/* ============================================================================
   v2 — multi-page structure: case pages, cards, the before/after slider and
   the lightbox. Everything below reuses the same tokens as the blocks above.
   ========================================================================= */

/* ------------------------------------------------------------ case intro */

.case-intro {
  padding: clamp(2.5rem, 6vw, 4.5rem) 0 clamp(2rem, 4vw, 3rem);
}

.crumbs {
  font-family: var(--font-mono);
  font-size: .78rem;
  letter-spacing: .04em;
  color: var(--muted);
  margin: 0 0 1.4rem;
}
.crumbs span { margin: 0 .4rem; opacity: .6; }

/* ------------------------------------------------------------- hero photo */
.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 2rem 3rem;
}
.hero__photo {
  display: block;
  width: 100%;
  max-width: 380px;   /* Valeria's cap for the new portrait (20.08) */
  height: auto;
  justify-self: end;
}
@media (max-width: 900px) {
  .hero__grid { grid-template-columns: 1fr; gap: 1.6rem; }
  .hero__photo { max-width: 300px; justify-self: start; }
}

.case-title {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.02em;
  font-size: clamp(2.1rem, 4.6vw, 3.2rem);
  margin: 0 0 1rem;
  max-width: 20ch;
}
[lang="ru"] .case-title { font-family: var(--font-body); letter-spacing: -.025em; max-width: 24ch; }

.case-lede {
  color: var(--muted);
  max-width: 62ch;
  font-size: 1.12rem;
  margin: 0 0 2.5rem;
}

/* ------------------------------------------------------------- result block */
/* The number of the case, before any visual. Market scan says most portfolios
   bury it at the end; this one opens with it. */

.result {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  padding: 1.8rem 1.8rem 1.6rem;
  margin-bottom: 1.6rem;
}

.result__headline {
  display: flex;
  align-items: baseline;
  gap: 1.1rem;
  flex-wrap: wrap;
  padding-bottom: 1.2rem;
  border-bottom: 1px solid var(--border);
}

.result__num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.8rem, 7vw, 4.2rem);
  line-height: 1;
  letter-spacing: -.03em;
  background: var(--marker);
  color: var(--on-marker);
  padding: .1em .18em;
  border-radius: 10px;
}

.result__label {
  font-size: 1.06rem;
  line-height: 1.45;
  max-width: 34ch;
  color: var(--ink);
}

.result__extras {
  list-style: none;
  margin: 1.2rem 0 0;
  padding: 0;
  display: grid;
  gap: .7rem;
}
.result__extras li {
  position: relative;
  padding-left: 1.2rem;
  font-size: .98rem;
  color: var(--muted);
}
.result__extras li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: var(--accent);
}
.result__extras b { color: var(--ink); font-weight: 600; }

.result__note {
  margin: 1.1rem 0 0;
  font-family: var(--font-mono);
  font-size: .74rem;
  line-height: 1.5;
  color: var(--muted);
}

/* -------------------------------------------------------------- case cards */

.cases {
  display: grid;
  gap: 1.5rem;
}

.case-card {
  display: grid;
  grid-template-columns: minmax(0, 400px) minmax(0, 1fr);
  gap: 2rem;
  align-items: center;
  padding: 1.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  transition: border-color .15s ease, transform .15s ease;
}
.case-card:hover { border-color: var(--accent); }

/* The title link is stretched over the whole card, so any point of the card opens
   the case (Valeria's audit, 18.08). The media link keeps its own hit area. */
.case-card { position: relative; }
.case-card__title a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}
.case-card__title a { position: static; }

.case-card__media {
  display: block;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--bg);
  border: 1px solid var(--border);
}
.case-card__media img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: 50% 0;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

.case-card__body .eyebrow { margin-bottom: .6rem; }
.case-card__title {
  font-size: clamp(1.3rem, 2.4vw, 1.6rem);
  margin: 0 0 .7rem;
}
.case-card__title a { color: var(--ink); }
.case-card__title a:hover { color: var(--accent); text-decoration: none; }
.case-card__teaser { color: var(--muted); margin: 0 0 1rem; max-width: 56ch; }
.case-card__metric { margin: 0 0 .8rem; font-family: var(--font-mono); font-size: .82rem; }
.case-card__more {
  margin: 0;
  font-family: var(--font-mono);
  font-size: .78rem;
  color: var(--accent);
}

/* ------------------------------------------------- case head with a CTA
   Valeria asked for the Figma button to sit level with the case title and to be
   repeated under the case body, so the title row becomes a two-part header. */

.case-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 1.5rem;
}
.case-head .case-title,
.case-head h3 { flex: 1 1 22ch; margin: 0; }
/* .case-title carries the 16px gap to the lede; inside .case-head its margin is
   cleared for vertical alignment, so the row itself carries the gap instead. */
.case-head { margin-bottom: 1rem; }
.case-head__cta { flex: 0 0 auto; }

.case-outro {
  margin-top: 2.5rem;
  padding-top: 1.8rem;
  border-top: 1px solid var(--border);
}
.case-outro__note {
  margin: .7rem 0 0;
  color: var(--muted);
  font-size: .92rem;
}

/* ----------------------------------------------------------- case chapters
   The builder case carries three chapters (redesign, design system, onboarding) on one
   page, so the bar below the intro works like tabs but scrolls instead of hiding
   content: everything stays in the document, in one link, for one reader. */

.chapters {
  position: sticky;
  top: 57px;              /* directly under the topbar */
  z-index: 20;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}
.chapters__inner {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: .6rem var(--gutter);
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
}
.chapters__item {
  font-family: var(--font-mono);
  font-size: .82rem;
  color: var(--muted);
  padding: .4rem .8rem;
  border: 1px solid transparent;
  border-radius: 999px;
}
.chapters__item:hover { color: var(--ink); text-decoration: none; border-color: var(--border); }
.chapters__item.is-current {
  background: var(--marker);
  color: var(--on-marker);
  border-color: var(--marker);
}

.chapter { scroll-margin-top: 112px; }
.chapter__head { margin-bottom: 2rem; }
.chapter__head h2 { margin: .3rem 0 .6rem; }

/* ----------------------------------------------------- also-shipped tags */

.tagblock {
  margin-top: 1.5rem;
  padding: 1.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
}
.tagblock h3 { font-size: 1.2rem; font-weight: 500; margin: 0 0 .5rem; }
.tagblock__note { margin: 0 0 1.1rem; color: var(--muted); max-width: 62ch; }

.tags {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
}
.tags li {
  font-family: var(--font-mono);
  font-size: .84rem;
  padding: .4rem .85rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
}

/* ------------------------------------------------------------ other works
   Two columns, as Valeria asked, so the block stays short. Every card leaves the
   site: there is no inner page behind them. */

.works {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.5rem;
}
.work-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  overflow: hidden;
  transition: border-color .15s ease;
}
.work-card:hover { border-color: var(--accent); }
.work-card__media {
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
.work-card__media img,
.work-card__media video {
  display: block;
  width: 100%;
  height: auto;      /* <video> maps its height attribute to a real CSS height */
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

/* The arrow that marks an outbound button needs air after the label. */
.btn span[aria-hidden] { margin-left: .4em; }
.work-card__body {
  padding: 1.1rem 1.2rem 1.3rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .55rem;
}
.work-card__title { font-size: 1.1rem; font-weight: 500; margin: 0; }
.work-card__note { margin: 0 0 .3rem; color: var(--muted); font-size: .95rem; }

.btn--sm { padding: .55rem 1rem; font-size: .88rem; }

/* ---------------------------------------------------------------- callout */

.callout {
  margin: 2.6rem 0 0;
  padding: 1.6rem 1.7rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--surface);
  max-width: 72ch;
}
.callout h3 {
  font-size: 1.1rem;
  font-weight: 500;
  margin: 0 0 .8rem;
}
.callout p { margin: 0 0 .9rem; }
.callout p:last-child { margin-bottom: 0; }

/* --------------------------------------------------- cross-functional block */

.crossfn {
  margin: 3rem 0 0;
  padding: 1.6rem 1.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  max-width: 72ch;
}
.crossfn__title {
  font-family: var(--font-mono);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 1rem;
}
.crossfn__list { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: .6rem; }
.crossfn__list li { position: relative; padding-left: 1.2rem; }
.crossfn__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 7px;
  height: 7px;
  border-radius: 2px;
  background: var(--marker);
}
.crossfn__note { margin: 0; color: var(--muted); font-size: .96rem; }

/* --------------------------------------------------------- contact and nav */

.contact-cta {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  padding: 2rem;
}
.contact-cta__title { font-size: 1.5rem; margin: 0 0 .6rem; }
.contact-cta__lede { color: var(--muted); margin: 0 0 1.4rem; max-width: 52ch; }
.contact-cta__actions { display: flex; flex-wrap: wrap; gap: .7rem; }

.pagenav { margin-top: 2rem; }
.pagenav__link {
  display: flex;
  flex-direction: column;
  gap: .35rem;
  padding: 1.3rem 1.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
}
.pagenav__link:hover { border-color: var(--accent); text-decoration: none; color: var(--ink); }
.pagenav__key {
  font-family: var(--font-mono);
  font-size: .74rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}
.pagenav__title { font-family: var(--font-display); font-size: 1.2rem; font-weight: 500; }
[lang="ru"] .pagenav__title { font-family: var(--font-body); }

.linklist { list-style: none; margin: 0; padding: 0; display: grid; gap: .8rem; font-family: var(--font-mono); font-size: .92rem; }
.backlink { margin: 2rem 0 0; font-family: var(--font-mono); font-size: .85rem; }
.about__subtitle--spaced { margin-top: 2rem; }
.hero__name--sm { font-size: clamp(1.5rem, 3vw, 2rem); }
.fig--phone { max-width: 220px; }
.fig--phone .tall { padding: .5rem; }

.footer__links {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  font-family: var(--font-mono);
  font-size: .8rem;
}

/* --------------------------------------------------- before / after slider */
/* The signature interaction: two identically sized exports, one wiped over the
   other. Works with a mouse, a finger and the arrow keys. */

.ba {
  position: relative;
  max-width: 880px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow);
  touch-action: pan-y;
  user-select: none;
  cursor: ew-resize;
}
.ba__base { display: block; width: 100%; height: auto; }

.ba__clip {
  position: absolute;
  inset: 0;
  width: 50%;
  overflow: hidden;
}
.ba__clip img {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: auto;
  max-width: none;
  /* Both exports share the same pixel size, so height:100% reproduces the
     full-width image exactly and the wipe stays aligned. */
}

.ba__tag {
  position: absolute;
  top: .8rem;
  font-family: var(--font-mono);
  font-size: .72rem;
  letter-spacing: .04em;
  padding: .25rem .6rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  color: var(--ink);
  border: 1px solid var(--border);
  pointer-events: none;
}
.ba__tag--before { left: .8rem; }
.ba__tag--after { right: .8rem; }

.ba__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 44px;
  margin-left: -22px;
  cursor: ew-resize;
  touch-action: none;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ba__handle::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 21px;
  width: 2px;
  background: var(--marker);
}
.ba__grip {
  position: relative;
  width: 40px;
  height: 40px;
  border-radius: 999px;
  background: var(--marker);
  border: 2px solid var(--on-marker);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .25);
}
.ba__grip::before,
.ba__grip::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 0;
  height: 0;
  margin-top: -5px;
  border: 5px solid transparent;
}
.ba__grip::before { left: 6px; border-right-color: var(--on-marker); }
.ba__grip::after { right: 6px; border-left-color: var(--on-marker); }
.ba__handle:focus-visible { outline: none; }
.ba__handle:focus-visible .ba__grip { outline: 3px solid var(--accent); outline-offset: 3px; }

.ba.is-animated .ba__clip,
.ba.is-animated .ba__handle { transition: width .18s ease, left .18s ease; }

/* ---------------------------------------------------------------- lightbox */

[data-zoom] { cursor: zoom-in; }

/* Wide and tall canvases scroll inside their frame; the caption says so, and this
   adds the second half of the sentence in the page's own language. */
html[lang="en"] .fig:has(.scroller) figcaption::after,
html[lang="en"] .fig:has(.tall) figcaption::after { content: " Click to open it full size."; }
html[lang="ru"] .fig:has(.scroller) figcaption::after,
html[lang="ru"] .fig:has(.tall) figcaption::after { content: " Кликом открывается полный размер."; }
html[lang] .fig--tall:has(.tall) figcaption::after { content: none; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: none;
  background: rgba(10, 11, 14, .96);
}
.lightbox.is-open { display: block; }

.lightbox__stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4.5rem 1.5rem 4rem;
  overflow: auto;
  overscroll-behavior: contain;
}
.lightbox__img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  border-radius: 6px;
  background: #fff;
  cursor: zoom-in;
}
.lightbox.is-zoomed .lightbox__stage { align-items: flex-start; justify-content: flex-start; cursor: grab; }
.lightbox.is-zoomed .lightbox__img { max-width: none; max-height: none; cursor: grab; }
.lightbox.is-dragging .lightbox__stage,
.lightbox.is-dragging .lightbox__img { cursor: grabbing; }

.lightbox__btn {
  position: absolute;
  z-index: 2;
  border: 1px solid rgba(255, 255, 255, .25);
  background: rgba(20, 21, 26, .8);
  color: #f4f4f6;
  border-radius: 999px;
  width: 44px;
  height: 44px;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.lightbox__btn:hover { background: rgba(60, 62, 72, .9); }
.lightbox__close { top: 1rem; right: 1rem; }
.lightbox__prev { top: 50%; left: 1rem; margin-top: -22px; }
.lightbox__next { top: 50%; right: 1rem; margin-top: -22px; }
.lightbox__btn[hidden] { display: none; }

.lightbox__bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: .9rem 1.5rem 1.2rem;
  display: flex;
  gap: 1rem;
  align-items: baseline;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: .76rem;
  color: rgba(244, 244, 246, .75);
  background: linear-gradient(to top, rgba(10, 11, 14, .9), transparent);
  pointer-events: none;
}
.lightbox__caption { max-width: 70ch; }
.lightbox__count { flex: none; opacity: .7; }

body.is-locked { overflow: hidden; }

/* --------------------------------------------------------------- motion */
/* One restrained reveal on scroll. Nothing else moves. */

.js .reveal {
  opacity: 0;
  transform: translateY(14px);
}
.js .reveal.is-visible {
  opacity: 1;
  transform: none;
  transition: opacity .5s ease, transform .5s cubic-bezier(.22, .61, .36, 1);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .reveal { opacity: 1; transform: none; }
  .js .reveal.is-visible { transition: none; }
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  /* The slider keeps working — only the eased jump on keyboard input goes away. */
  .ba.is-animated .ba__clip,
  .ba.is-animated .ba__handle { transition: none; }
}

/* -------------------------------------------------------------- adaptive */

@media (max-width: 900px) {
  :root { --section-y: 4.5rem; }
  .about { grid-template-columns: 1fr; gap: 2rem; }
  .case-card { grid-template-columns: 1fr; gap: 1.4rem; }
  .grid--3, .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid--bp { grid-template-columns: 1fr; }
}

@media (max-width: 720px) {
  :root { --gutter: 18px; }
  body { font-size: 1rem; }

  .works { grid-template-columns: 1fr; }
  .case-head__cta { width: 100%; justify-content: center; }

  /* Wrapped onto two rows the sticky chapter bar ate a third of the screen, so on a phone
     it scrolls sideways instead. */
  .chapters__inner {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .chapters__inner::-webkit-scrollbar { display: none; }
  .chapters__item { white-space: nowrap; }
  .chapter { scroll-margin-top: 104px; }

  .pair, .grid-2, .grid--2, .grid--3 { grid-template-columns: 1fr; gap: 1.6rem; }
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }

  .result { padding: 1.3rem; }
  .result__headline { gap: .8rem; }
  .contact-cta { padding: 1.4rem; }
  .callout, .crossfn { padding: 1.3rem; }
  .ba__grip { width: 34px; height: 34px; }
  .ba__handle { width: 40px; margin-left: -20px; }
  .ba__handle::before { left: 19px; }
  .lightbox__stage { padding: 4rem .8rem 3.5rem; }
  .lightbox__prev { left: .5rem; }
  .lightbox__next { right: .5rem; }

  .spec { padding: 1.1rem 1.1rem; }
  .spec__row { grid-template-columns: 1fr; gap: .1rem; padding: .6rem 0; }

  .topbar__inner { flex-wrap: wrap; row-gap: .6rem; }
  .brand__name { font-size: .95rem; }

  .hero__thesis { max-width: none; }
  .facts { grid-template-columns: 1fr; }

  .tall { max-height: 420px; }
  .phones img { height: 400px; }

  .footer__inner { grid-template-columns: 1fr; gap: 1.1rem; }
  .footer__name,
  .footer__links { grid-area: auto; justify-self: start; }
}

@media (max-width: 400px) {
  :root { --gutter: 14px; }
  .topbar__controls { gap: .7rem; }
  .token-toggle { font-size: .72rem; }
  .langs { font-size: .72rem; }
  .btn { padding: .7rem 1.15rem; font-size: .92rem; }
}
