:root {
  /* Color */
  --color-ink: #000000;
  --color-ink-soft: #656565;
  --color-heading: #2c2c2c;
  --color-surface: #ffffff;
  --color-surface-sunken: #f7f7f7;
  --color-border: #e8e8e8;
  --color-overlay: rgba(0, 0, 0, 0.4);

  /* Radius */
  --radius-lg: 48px;
  --radius-md: 40px;
  --radius-pill: 100px;
  --radius-chip: 28px;
  --radius-soon: 56px;

  /* Spacing */
  --space-xs: 8px;
  --space-sm: 12px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 32px;
  --space-2xl: 40px;
  --space-3xl: 48px;

  /* Typography: families */
  --ff-display: "Roboto Flex", sans-serif;
  --ff-body: "Inter", sans-serif;
  --ff-mono: "Roboto Mono", monospace;

  /* Typography: sizes. Display + large body scale fluidly between the
     mobile floor and the desktop value, so type breathes across widths
     instead of snapping at breakpoints. */
  --fs-display: clamp(24px, 1.1rem + 1.5vw, 32px);
  --fs-body-lg: clamp(16px, 0.85rem + 0.6vw, 20px);
  --fs-body-md: 16px;
  --fs-body-sm: 14px;
  --fs-mono-lg: 20px;
  --fs-mono-md: 16px;

  /* Typography: weights & line-heights */
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --lh-tight: 1.1;
  --lh-normal: 1.4;

  /* Case stage */
  --stage-ratio: 1220 / 712;

  /* Corner smoothing: a continuous curve instead of a plain circular arc.
     Note the counterintuitive direction: superellipse(n) looks MORE
     square/sharp as n rises above 2 (a true circle), so staying just
     below 2 keeps the silhouette close to the design's plain round
     corners while still picking up the smoother, non-circular curve. */
  --corner-smoothing: 1.6;

  /* Motion: one shared easing + duration so every interaction feels
     like it belongs to the same system. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 0.22s;

  /* Elevation: layered shadows (a tight contact shadow + a soft ambient
     one) read as real depth, unlike a single flat blur. */
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.04), 0 -4px 27px rgba(0, 0, 0, 0.05);
  --shadow-hover: 0 2px 6px rgba(0, 0, 0, 0.08), 0 16px 40px -12px rgba(0, 0, 0, 0.18);
  --hairline: rgba(0, 0, 0, 0.05);
}

* {
  box-sizing: border-box;
}

@supports (corner-shape: superellipse(2)) {
  * {
    corner-shape: superellipse(var(--corner-smoothing));
  }
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--color-surface);
  color: var(--color-ink);
  font-family: var(--ff-body);
  /* Let Roboto Flex pick the optical-size cut that suits each glyph size. */
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overscroll-behavior-y: none;
}

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

a {
  color: inherit;
  text-decoration: none;
}

/* Keyboard focus only — never shows for mouse users, always for tab nav. */
:focus-visible {
  outline: 2px solid var(--color-ink);
  outline-offset: 3px;
  border-radius: 6px;
}

:focus:not(:focus-visible) {
  outline: none;
}

::selection {
  background: var(--color-ink);
  color: var(--color-surface);
}

/* Respect users who ask for less motion: kill the smooth scroll and any
   transitions/animations so nothing slides or eases for them. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.page {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  /* 24px frame on all sides. Both columns are inset 24px top and bottom,
     so they line up at the top and — because the right column's scroll
     ends with its last card at the column's bottom edge — also line up
     at the bottom (24px above the viewport edge, level with the left
     floating panel). */
  padding: var(--space-lg);
  max-width: 1920px;
  margin: 0 auto;
}

/* ---------- Typography roles ---------- */

.text-display {
  font-family: var(--ff-display);
  font-variation-settings: "opsz" 96, "wdth" 132;
  font-weight: var(--fw-semibold);
  font-size: var(--fs-display);
  line-height: var(--lh-tight);
  /* Tighten large type slightly, and balance line lengths so headings
     never leave a lonely word on the last line. */
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.text-body {
  font-family: var(--ff-body);
  font-weight: var(--fw-regular);
  font-size: var(--fs-body-lg);
  line-height: var(--lh-normal);
  color: var(--color-ink-soft);
  /* Avoid orphans / ragged last lines in paragraphs. */
  text-wrap: pretty;
}

.text-mono {
  font-family: var(--ff-mono);
  font-weight: var(--fw-regular);
  font-size: var(--fs-mono-md);
  line-height: var(--lh-normal);
}

/* ---------- Shared components ---------- */

/* .panel: soft-bg rounded wrapper that frames a stack of white cards */
.panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  background: var(--color-surface-sunken);
  border-radius: var(--radius-lg);
  padding: var(--space-xs);
}

/* .card: white rounded surface inside a panel. A hairline gives the white
   a crisp edge against the sunken bg that a shadow alone can't. */
.card {
  width: 100%;
  background: var(--color-surface);
  border-radius: var(--radius-md);
  border: 1px solid var(--hairline);
}

.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--ff-body);
  line-height: var(--lh-normal);
  cursor: pointer;
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}

.btn:active {
  transform: scale(0.98);
}

.btn--soft {
  flex: 1;
  padding: var(--space-lg);
  border-radius: var(--radius-pill);
  background: var(--color-surface-sunken);
  font-size: var(--fs-body-md);
  color: var(--color-ink);
}

.btn--soft:hover {
  background: #ededed;
}

.btn--dark {
  width: 100%;
  padding: var(--space-lg) var(--space-sm);
  border-radius: var(--radius-pill);
  background: var(--color-ink);
  color: var(--color-surface);
  font-size: var(--fs-body-md);
}

.btn--dark:hover {
  background: #1c1c1c;
  transform: translateY(-1px);
  box-shadow: 0 8px 22px -8px rgba(0, 0, 0, 0.45);
}

.btn--dark:active {
  transform: translateY(0) scale(0.99);
}

.btn--icon {
  flex-shrink: 0;
  width: 72px;
}

.btn--icon img {
  width: 100%;
  height: auto;
  aspect-ratio: 72 / 48;
}

.chip {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-sm);
  border-radius: var(--radius-chip);
  background: var(--color-surface-sunken);
  font-family: var(--ff-mono);
  font-size: var(--fs-mono-md);
  line-height: var(--lh-normal);
  color: var(--color-ink);
  white-space: nowrap;
}

.chip--soon {
  flex-shrink: 0;
  height: 48px;
  padding: var(--space-md) var(--space-lg);
  border-radius: var(--radius-soon);
  background: var(--color-overlay);
  color: var(--color-surface);
  font-family: var(--ff-body);
}

/* ---------- Left column ---------- */

.profile-col {
  width: 572px;
  flex-shrink: 0;
  overflow: hidden;
}

.profile-col-scroll {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  width: 100%;
  /* This element is the actual scroll container (overflow-y: auto on
     desktop), so it — not the outer panel — is what clips the scrolling
     content. Round it to the panel's inner corner (outer radius minus the
     8px panel padding) so content slides away behind rounded corners
     instead of showing sharp rectangular ones. */
  border-radius: calc(var(--radius-lg) - var(--space-xs));
}

.profile-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
  padding: var(--space-xl);
}

.profile-top {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  width: 100%;
}

.profile-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-sm);
}

.status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  background: var(--color-surface-sunken);
  font-size: var(--fs-body-sm);
  color: var(--color-ink);
  white-space: nowrap;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #22c55e;
  animation: status-pulse 2.4s var(--ease) infinite;
}

@keyframes status-pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.45);
  }
  70% {
    box-shadow: 0 0 0 6px rgba(34, 197, 94, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(34, 197, 94, 0);
  }
}

.avatar {
  width: 172px;
  height: 172px;
  border-radius: var(--radius-md);
  object-fit: cover;
  background: #d9d9d9;
  flex-shrink: 0;
}

.clock {
  margin: 0;
  text-align: right;
  color: var(--color-ink-soft);
  /* Fixed-width digits so the ticking clock never nudges its own width. */
  font-variant-numeric: tabular-nums;
}

.intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  width: 100%;
}

.intro-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  width: 100%;
}

.name {
  margin: 0;
  color: var(--color-ink);
}

.bio {
  margin: 0;
}

.more-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--fs-mono-lg);
  color: var(--color-ink);
  cursor: pointer;
  transition: gap var(--dur) var(--ease);
}

.more-link:hover {
  gap: 14px;
}

.more-link-arrow {
  width: 13px;
  height: auto;
  aspect-ratio: 14 / 7.36396;
}

.actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  width: 100%;
}

.actions-row {
  display: flex;
  gap: var(--space-xs);
  width: 100%;
}

.experience-card {
  padding: var(--space-md) var(--space-2xl);
}

/* Each entry stacks its title (company — role) over the dates, with a
   hairline rule between entries. */
.experience-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-xs);
  width: 100%;
  padding: 20px 0;
  border-bottom: 1px solid var(--color-border);
}

.experience-row:last-child {
  border-bottom: none;
}

.experience-title {
  margin: 0;
  width: 100%;
  font-family: var(--ff-display);
  font-size: var(--fs-body-lg);
  font-weight: var(--fw-semibold);
  font-variation-settings: "wdth" 132;
  line-height: var(--lh-tight);
  color: var(--color-heading);
}

.experience-dates {
  margin: 0;
  width: 100%;
  font-family: var(--ff-body);
  font-size: var(--fs-body-md);
  font-weight: var(--fw-regular);
  line-height: var(--lh-normal);
  color: var(--color-ink-soft);
  font-variant-numeric: tabular-nums;
}

/* ---------- Right column ---------- */

.projects-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  flex: 1;
  min-width: 0;
}

/* Thin, unobtrusive scrollbars for the independently-scrolling columns. */
.profile-col-scroll,
.projects-col {
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 0, 0, 0.18) transparent;
}

.profile-col-scroll::-webkit-scrollbar,
.projects-col::-webkit-scrollbar {
  width: 8px;
}

.profile-col-scroll::-webkit-scrollbar-thumb,
.projects-col::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.15);
  border-radius: 8px;
}

.profile-col-scroll::-webkit-scrollbar-thumb:hover,
.projects-col::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 0, 0, 0.28);
}

.case-card {
  position: relative;
  justify-content: flex-end;
  gap: 0;
  width: 100%;
  /* --card-min-h is stage + content's natural height (script.js). A
     negative margin-top on a flex child shrinks the flex column's
     auto-height in this environment, so pin the floor explicitly —
     otherwise the card collapses while its content is still compressed. */
  min-height: var(--card-min-h, auto);
}

.case-stage {
  /* aspect-ratio collapses to 0 height when an ancestor has
     overflow: hidden in this environment, so size via the classic
     padding-bottom trick instead — 712 / 1220 from --stage-ratio. */
  position: relative;
  width: 100%;
  height: 0;
  padding-bottom: 58.3607%;
  border-radius: var(--radius-md);
  overflow: hidden;
  /* Lets the badges size themselves against the stage (cqw units).
     inline-size only — `size` would make the height independent of the
     padding-bottom trick and collapse the stage. */
  container-type: inline-size;
}

/* A single Kinescope clip fills the stage; the stage's padding-bottom
   carries the clip's own aspect ratio, so nothing is letterboxed. */
.case-stage-iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Award badges sit over the clip in the stage's top-left corner */
.case-badges {
  position: absolute;
  top: var(--space-xl);
  left: var(--space-xl);
  z-index: 2;
  display: flex;
  align-items: flex-start;
  /* 2.03% of the stage width — 16px at a 1440px viewport — so the spacing
     shrinks with the card just like the badges do. */
  gap: 2.03cqw;
  pointer-events: none;
  /* Height in % of the stage (its padding-bottom makes that definite), so
     the badges shrink and grow with the card instead of staying fixed. */
  height: 8.15%;
}

.case-badge {
  display: block;
  height: 100%;
  width: auto;
}

/* Video cards keep the clip and the info panel visually separate */
.case-card--spaced {
  gap: var(--space-xs);
}

/* Sequential Kinescope clips: every layer fills the stage, only the
   currently playing one is visible. */
.case-kin-seq,
.case-kin-players,
.case-kin-slot,
.case-kin-fallback {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.case-kin-slot {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease);
}

.case-kin-slot.is-active {
  opacity: 1;
  pointer-events: auto;
}

.case-kin-slot iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

.case-stage-img,
.case-stage-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform-origin: center;
  transition: transform 0.5s var(--ease);
}

/* Only cards that actually link somewhere (they carry a .btn--icon arrow,
   unlike the "Скоро" card) react to hover: a restrained image push-in and
   an arrow nudge signal "this opens the case". */
.case-card:has(.btn--icon):hover .case-stage-img,
.case-card:has(.btn--icon):hover .case-stage-video {
  transform: scale(1.03);
}

.case-stage-kinescope {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.case-stage-kinescope iframe {
  width: 100%;
  height: 100%;
}

.case-card:has(.btn--icon):hover .btn--icon {
  transform: translateX(4px);
}

.case-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  padding: var(--space-xl);
  box-shadow: var(--shadow-card);
  /* The image stays fully in place — no covering/uncovering. Only the one
     active card (script.js) gets sticky, gluing this info panel to the
     viewport bottom as the card scrolls past. Every other card is plain
     and static, so two cards are never sticky at once. */
  position: relative;
}

.case-content.is-active {
  position: sticky;
  bottom: 0;
}


.tags {
  display: flex;
  gap: var(--space-xs);
  width: 100%;
}

.case-summary {
  display: flex;
  align-items: flex-end;
  gap: var(--space-md);
  width: 100%;
}

.case-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  flex: 1;
  min-width: 0;
}

.case-title {
  margin: 0;
  color: var(--color-heading);
}

.case-desc {
  margin: 0;
}

/* ---------- Responsive ---------- */

@media (max-width: 1100px) {
  .page {
    flex-direction: column;
    padding: var(--space-lg);
  }

  .profile-col {
    width: 100%;
  }
}

/* Desktop scroll model: the whole page scrolls (the right column is NOT a
   clipped scroll box — its cards flow freely and are never cut by a
   container). The left panel is sticky, so it stays pinned 24px from the
   top while the cases scroll past. If the left content is taller than the
   viewport it scrolls internally, staying within its own rounded frame. */
@media (min-width: 1101px) {
  .profile-col {
    position: sticky;
    top: var(--space-lg);
    height: calc(100dvh - 2 * var(--space-lg));
  }

  .profile-col-scroll {
    flex: 1;
    min-height: 0;
    height: 100%;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

@media (max-width: 560px) {
  .page {
    padding: var(--space-sm);
    gap: var(--space-sm);
  }

  .profile-card {
    padding: var(--space-lg);
    gap: var(--space-lg);
  }

  /* Display / large-body sizes now scale fluidly via clamp(), so no
     hard font-size overrides are needed here. */

  .avatar {
    width: 96px;
    height: 96px;
    border-radius: 24px;
  }

  /* Too narrow to keep the status badge beside the avatar: stack it
     underneath, aligned to the same left edge. */
  .profile-top {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-lg);
  }

  .profile-meta {
    flex: none;
    width: 100%;
    align-items: flex-start;
  }

  .experience-card {
    padding: var(--space-xs) var(--space-lg);
  }

  /* Entries already stack by default, so nothing to override here beyond
     tightening the card's own padding (above). */

  .case-content {
    padding: var(--space-lg);
    gap: var(--space-md);
  }

  .case-summary {
    flex-wrap: wrap;
  }
}
