/* =========================================================================
   Stepicon 2026 — landing styles
   Step 1: project skeleton + hero section (static, no animations yet).
   ========================================================================= */

/* -------------------------------------------------------------------------
   0. FONTS — Inter Display (local files in assets/fonts)
   ------------------------------------------------------------------------- */
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-Thin.ttf") format("truetype");
  font-weight: 100;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-ThinItalic.ttf") format("truetype");
  font-weight: 100;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-ExtraLight.ttf") format("truetype");
  font-weight: 200;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-ExtraLightItalic.ttf") format("truetype");
  font-weight: 200;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-Light.ttf") format("truetype");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-LightItalic.ttf") format("truetype");
  font-weight: 300;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-Italic.ttf") format("truetype");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-Medium.ttf") format("truetype");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-MediumItalic.ttf") format("truetype");
  font-weight: 500;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-SemiBold.ttf") format("truetype");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-SemiBoldItalic.ttf") format("truetype");
  font-weight: 600;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-Bold.ttf") format("truetype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-BoldItalic.ttf") format("truetype");
  font-weight: 700;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-ExtraBold.ttf") format("truetype");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-ExtraBoldItalic.ttf") format("truetype");
  font-weight: 800;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-Black.ttf") format("truetype");
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter Display";
  src: url("assets/fonts/InterDisplay-BlackItalic.ttf") format("truetype");
  font-weight: 900;
  font-style: italic;
  font-display: swap;
}

/* -------------------------------------------------------------------------
   1. DESIGN TOKENS (pulled from Figma variables & text styles)
   Use these everywhere — do not hard-code colours or font sizes in markup.
   ------------------------------------------------------------------------- */
:root {
  /* --- Colours --- */
  --background-black: #000000;
  --background-white: #ffffff;
  --background-purple: #9674ff;
  --background-green: #a2ff8a;
  --background-transparent: rgba(255, 255, 255, 0.12); /* #ffffff1f */
  --background-transparent-1: rgba(255, 255, 255, 0.08); /* #ffffff14 */

  --border-purple: #9673ff;
  --border-green: #a2ff8a;
  --border-white: #ffffff;

  --text-primary: #ffffff;
  --text-secondary: rgba(255, 255, 255, 0.5); /* #ffffff80 */
  --text-tertiary: rgba(255, 255, 255, 0.24); /* #ffffff3d */
  --text-primary-inverse: #000000;
  --text-secondary-inverse: rgba(0, 0, 0, 0.5); /* #00000080 */

  /* --- Typography --- */
  --font-display: "Inter Display", "Inter", system-ui, -apple-system,
    "Segoe UI", Roboto, sans-serif;

  /* Heading / Page (Stepicon 2026) — SemiBold 156 / 1 / -2% */
  --t-page-size: 156px;
  --t-page-weight: 600;
  --t-page-lh: 1;
  --t-page-ls: -0.02em;

  /* Heading / Section — SemiBold 64 / 1 / 0 */
  --t-section-size: 64px;
  --t-section-weight: 600;
  --t-section-lh: 1;
  --t-section-ls: 0;

  /* Heading / Tabs (section title) — Bold 80 / 1.12 / 0 */
  --t-tabs-size: 80px;
  --t-tabs-weight: 700;
  --t-tabs-lh: 1.12;
  --t-tabs-ls: 0;

  /* Heading / Accent (big numbers) — SemiBold 124 / 1 / -2% */
  --t-bignum-size: 124px;
  --t-bignum-weight: 600;
  --t-bignum-lh: 1;
  --t-bignum-ls: -0.02em;

  /* Body / Accent (hero subtitle) — Medium 40 / 1.14 / 0 */
  --t-accent-size: 40px;
  --t-accent-weight: 500;
  --t-accent-lh: 1.14;
  --t-accent-ls: 0;

  /* Body / Accent-1 (plate value) — Medium 30 / 1.12 / 0 */
  --t-accent1-size: 30px;
  --t-accent1-weight: 500;
  --t-accent1-lh: 1.12;
  --t-accent1-ls: 0;

  /* Body / Accent-2 (talk titles, time) — SemiBold 32 / 1.12 / 1% */
  --t-accent2-size: 32px;
  --t-accent2-weight: 600;
  --t-accent2-lh: 1.12;
  --t-accent2-ls: 0.01em;

  /* Body / Primary-accent (speaker name/role) — Medium 24 / 1 / 0 */
  --t-primaccent-size: 24px;
  --t-primaccent-weight: 500;
  --t-primaccent-lh: 1;
  --t-primaccent-ls: 0;

  /* Body / Primary (nav links) — Medium 18 / 1.32 / 2% */
  --t-primary-size: 18px;
  --t-primary-weight: 500;
  --t-primary-lh: 1.32;
  --t-primary-ls: 0.02em;

  /* Body / Caption (plate label) — Medium 18 / 1.2 / 2% */
  --t-caption-size: 18px;
  --t-caption-weight: 500;
  --t-caption-lh: 1.2;
  --t-caption-ls: 0.02em;

  /* Tag (vertical "10 лет конференции") — SemiBold 16 / 1.32 / 2% */
  --t-tag-size: 16px;
  --t-tag-weight: 600;
  --t-tag-lh: 1.32;
  --t-tag-ls: 0.02em;

  /* --- Layout --- */
  --layout-max: 1440px;   /* design canvas width */
  --layout-pad: 16px;     /* inner padding of hero blocks */
}

/* -------------------------------------------------------------------------
   2. RESET / BASE
   ------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

body {
  min-height: 100vh;
  background-color: var(--background-black);
  color: var(--text-primary);
  font-family: var(--font-display);
  -webkit-font-smoothing: antialiased;
  font-synthesis: none; /* never fake-bold a weight that's a real Inter Display face */
  overflow-x: hidden;
}

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

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

img {
  display: block;
}

/* -------------------------------------------------------------------------
   3. BACKGROUND (generated in code — black base + stripes)
   Fixed full-viewport layer that sits behind all content.
   ------------------------------------------------------------------------- */
.backdrop {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background-color: var(--background-black);
  pointer-events: none;
}

/* -------------------------------------------------------------------------
   6. ABOUT — scattered photos + a centred spine line drawn by scroll.
   Each block keeps the 1408x900 mockup via aspect-ratio + % positions so it
   scales. Layering is by DOM order (line first, photos, then text); the
   section is isolated so the text difference-blend stays within it.
   ------------------------------------------------------------------------- */
.about {
  position: relative;
  z-index: 1;            /* above the fixed backdrop */
  isolation: isolate;    /* contain the text difference-blend to this section */
  width: 100%;
  padding: 0 var(--layout-pad) 6vw; /* bottom room for the lowered photo */
}

.about__block {
  position: relative;
  width: 100%;
  aspect-ratio: 1408 / 900;  /* preserve the mockup layout while scaling */
}

/* Centre spine line — spans the whole section; GSAP draws it with scaleY on
   scroll (visible by default so it still shows without JS / reduced motion). */
.about__line {
  position: absolute;
  left: 50%;
  /* start at the bottom of the hero's white plate (close the gutter gap):
     the section sits 16px below the plate, so reach up by the gutter + a
     couple px into the (white) plate so there's no black seam. */
  top: calc(-1 * var(--layout-pad) - 2px);
  height: calc(100% + var(--layout-pad) + 2px);
  /* match the hero SVG line thickness: stroke-width 32 in a 1440 viewBox
     rendered full-width => 32 * 100vw / 1440 (scales with the viewport too) */
  width: calc(100vw * 32 / 1440);
  margin-left: calc(100vw * -16 / 1440);
  background-color: var(--border-white);
  transform-origin: top center;
}

.about__photo {
  position: absolute;
  border-radius: 32px;
  overflow: hidden;
}
.about__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Block 1 */
.about__photo--1 { left: 0;      top: 8.11%;  width: 21.38%; height: 40.56%; }
.about__photo--2 { left: 84.30%; top: 12.11%; width: 15.70%; height: 29.78%; }
.about__photo--3 { left: 18.10%; top: 66.00%; width: 14.49%; height: 27.56%; }
.about__photo--4 { left: 69.00%; top: 65.00%; width: 19.67%; height: 31.00%; }
/* Block 2 */
.about__photo--5 { left: 0;      top: 1.78%;  width: 21.38%; height: 40.56%; }
.about__photo--6 { left: 71.66%; top: 8.89%;  width: 28.34%; height: 29.56%; }
.about__photo--7 { left: 60.16%; top: 71.00%; width: 17.12%; height: 32.44%; }
/* Block 3 — two photos: large one top-left, one lower-right */
.about__photo--8 { left: 0;      top: -6.00%; width: 40.00%; height: 54.00%; }
.about__photo--9 { left: 62.00%; top: 60.00%; width: 36.00%; height: 33.00%; }

.about__text {
  /* full-width, transform-free wrapper: a transform (or isolation) here would
     create a stacking context that traps .about__text-inner's blend inside
     it, hiding it from the photos it's supposed to invert against */
  position: absolute;
  left: 0;
  right: 0;
  bottom: 35.44%; /* equivalent to the old top:64.56% + translateY(-100%) */
  margin: 0;
  display: flex;
  justify-content: center;
}
/* Only the visible words blend (same invert effect as the hero title where a
   photo crosses it) — the tunnel mask is a separate sibling so it keeps
   painting as a normal opaque box and still hides the spine line behind it. */
.about__text-inner {
  /* "positioned" (no offset) so it stacks with the tunnel by DOM order alone
     — no z-index/isolation needed, which would otherwise block the blend */
  position: relative;
  width: min(743px, 86%);
  text-align: center;
  font-size: clamp(28px, 4.44vw, var(--t-section-size));
  font-weight: var(--t-section-weight);
  line-height: var(--t-section-lh);
  letter-spacing: var(--t-section-ls);
  color: var(--text-primary);
  mix-blend-mode: difference;
}

/* "Tunnel": a black strip masks the spine line behind the text (so the line
   no longer dirties the words), with a coloured block at the entry and exit
   so the line reads as going into a tunnel and coming back out. */
.about__tunnel {
  position: absolute;
  left: 50%;
  /* extend 80px past the text each side: a 40px mouth + a 40px gap to the text */
  top: -80px;
  bottom: -80px;
  transform: translateX(-50%);
  width: calc(100vw * 36 / 1440); /* a touch wider than the 32 spine */
  background-color: var(--background-black);
  /* no z-index needed: both this and .about__text-inner are position:relative/
     absolute with z-index:auto, so plain DOM order puts the tunnel (earlier)
     below the glyphs (later) and above the line (earlier still) */
}
.about__tunnel::before,
.about__tunnel::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  width: calc(100vw * 48 / 1440);
  height: 40px; /* mouth block height */
}
.about__tunnel::before {
  top: 0; /* entry mouth — 40px tall, 40px above the text */
}
.about__tunnel::after {
  bottom: 0; /* exit mouth — 40px tall, 40px below the text */
}
.about__text--1 .about__tunnel::before { background-color: var(--background-green); }
.about__text--1 .about__tunnel::after  { background-color: var(--background-purple); }
.about__text--2 .about__tunnel::before { background-color: var(--background-purple); }
.about__text--2 .about__tunnel::after  { background-color: var(--background-green); }
.about__text--3 .about__tunnel::before { background-color: var(--background-purple); }
.about__text--3 .about__tunnel::after  { background-color: var(--background-green); }

/* Desktop/tablet: give the spine a long, calm journey — open road from the
   hero into the first block, between the two blocks, and on to Points. */
@media (min-width: 769px) {
  .about {
    padding-top: 20vh;    /* longer road from the hero down to the 1st block */
    padding-bottom: 18vh; /* road from the 2nd block down to Points */
  }
  .about__block:not(:last-child) {
    margin-bottom: 20vh;  /* road between the statements */
  }
}

/* narrower than the other two so it clears photo--1/--2 on both sides
   (its copy is longer, so it wraps to more lines at the same font size
   as --2/--3 — kept equal per client request, not shrunk) */
.about__text--1 .about__text-inner {
  width: min(800px, 88%);
}

.about__text--2 {
  bottom: 34%; /* equivalent to the old top: 66% */
}
.about__text--2 .about__text-inner {
  width: min(933px, 90%);
}

.about__text--3 {
  bottom: 42%; /* equivalent to the old top: 58% */
}
.about__text--3 .about__text-inner {
  width: min(930px, 90%);
}

/* -------------------------------------------------------------------------
   7. POINTS (stats) — three outlined cards; lines branch from the white
   spine to the cards and draw on scroll. Full-bleed; the 1440x871 mockup is
   kept via aspect-ratio + % positions. Card borders/line strokes scale with
   the viewport (32 in a 1440 canvas => 32 * 100vw / 1440), matching the SVG.
   ------------------------------------------------------------------------- */
.points {
  position: relative;
  z-index: 1;
  width: 100%;
  padding-bottom: clamp(80px, 12vh, 200px); /* breathing room before "О чём будет" */
}

.points__inner {
  position: relative;
  width: 100%;
  aspect-ratio: 1440 / 871;
}

.points__lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.points__line {
  fill: none;
}
.points__line--white {
  stroke: var(--border-white);
}
.points__line--purple {
  stroke: var(--border-purple);
}
.points__line--green {
  stroke: var(--border-green);
}

.points__card {
  position: absolute;
  /* a touch wider than the 459/1440 base so "С 2016 года" sits comfortably —
     kept small since the white card's right edge sits close to the green
     card's left edge (only ~14px of clearance at the 1440 baseline) */
  width: 32.5%;
  aspect-ratio: 459 / 360;
  box-sizing: border-box;
  background-color: var(--background-black);
  border: calc(100vw * 32 / 1440) solid;
  padding: calc(100vw * 32 / 1440);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  color: var(--text-primary);
}
.points__card--purple {
  left: 3.33%;
  top: 19.29%;
  border-color: var(--border-purple);
}
.points__card--green {
  /* holds "С 2016 года" (the longest stat) so it gets the extra width; left
     nudged in from 64.79% so 61.3% + 36% keeps the old right edge (~97.3%)
     and never overflows the section. */
  left: 61.3%;
  top: 35.25%;
  width: 36%;
  border-color: var(--border-green);
}
.points__card--white {
  left: 31.94%;
  top: 54.99%;
  border-color: var(--border-white);
}

.points__num {
  /* Pure vw scaling (no low-end override needed) — the card also scales with
     vw, so the ratio between text and card stays constant at every width from
     769px up. Verified against the true glyph width (not the stretched flex
     box) so "С 2016 года" never overflows into the next card. */
  font-size: clamp(36px, 5vw, 112px);
  font-weight: var(--t-bignum-weight);
  line-height: var(--t-bignum-lh);
  letter-spacing: var(--t-bignum-ls);
  white-space: nowrap; /* keep "С 2016 года" on one line */
}
.points__label {
  font-size: clamp(18px, 2.08vw, var(--t-accent1-size));
  font-weight: var(--t-accent1-weight);
  line-height: var(--t-accent1-lh);
  letter-spacing: var(--t-accent1-ls);
}

/* hide the point lines before they draw (avoid a flash); reduced motion keeps them */
@media (prefers-reduced-motion: no-preference) {
  .points__line {
    stroke-dasharray: 3000;
    stroke-dashoffset: 3000;
  }
}

/* -------------------------------------------------------------------------
   7b. THEMES ("О чём будет Stepicon 2026")
   ------------------------------------------------------------------------- */
.themes {
  position: relative;
  z-index: 1;            /* above the fixed backdrop; the star layer floats over it */
  width: 100%;
  box-sizing: border-box;
  padding: clamp(64px, 9vw, 128px) var(--layout-pad);
}

.themes__title {
  margin: 0 0 clamp(32px, 4.4vw, 64px);
  text-align: center;
  font-size: clamp(34px, 5.6vw, var(--t-tabs-size));
  font-weight: var(--t-tabs-weight);
  line-height: var(--t-tabs-lh);
  letter-spacing: var(--t-tabs-ls);
  color: var(--text-primary);
}

.themes__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(20px, 3vw, 32px);
}

.theme-card {
  box-sizing: border-box;
  min-width: 0; /* grid items default to min-width:auto — an nbsp-locked run in
    the copy (e.g. "2027 год") would otherwise force the column wider than its
    1fr share and blow out the page's horizontal scroll */
  /* min-height (not a fixed aspect-ratio) — a card with longer copy (more
     wrapped lines) needs to grow, not cram its dot against the text. Grid's
     default align-items:stretch then equalizes every card in the same row
     to the tallest one, so they still all match visually. */
  min-height: clamp(240px, 21vw, 300px);
  /* transparent-1 (0.08) + ~12pt so the card plates read a touch more solid */
  background-color: rgba(255, 255, 255, 0.2);
  padding: clamp(20px, 2.2vw, 32px);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 24px; /* floor — always some air between the dot and the text, even if space-between has nothing extra to give */
}

.theme-card__dot {
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
}
.theme-card__dot--green {
  background-color: var(--background-green);
}
.theme-card__dot--purple {
  background-color: var(--background-purple);
}

.theme-card__text {
  margin: 0;
  font-size: clamp(18px, 2.08vw, var(--t-accent1-size));
  font-weight: var(--t-accent1-weight);
  line-height: var(--t-accent1-lh);
  letter-spacing: var(--t-accent1-ls);
  color: var(--text-primary);
}

/* -------------------------------------------------------------------------
   7c. PROGRAM (schedule) — title, day switcher, table of talks
   ------------------------------------------------------------------------- */
.program {
  position: relative;
  z-index: 1;
  width: 100%;
  box-sizing: border-box;
  padding: clamp(64px, 7vw, 120px) var(--layout-pad);
}

.program__title {
  margin: 0 0 clamp(32px, 4vw, 56px);
  font-size: clamp(40px, 8.6vw, 124px); /* Heading/Accent — SemiBold 124 / 1 */
  font-weight: 600;
  line-height: 1;
  color: var(--text-primary);
}

/* --- Day switcher (pill) --- */
.switcher {
  display: inline-flex;
  align-items: center;
  gap: 0;
  padding: 8px;
  border-radius: 9999px;
  background-color: var(--background-transparent);
  margin-bottom: clamp(32px, 4vw, 56px);
}
.switcher__btn {
  border: 0;
  cursor: pointer;
  padding: clamp(14px, 2.2vw, 32px) clamp(24px, 3vw, 44px);
  border-radius: 9999px;
  background-color: transparent;
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: clamp(18px, 2.08vw, var(--t-accent1-size));
  font-weight: var(--t-accent1-weight);
  line-height: var(--t-accent1-lh);
  white-space: nowrap;
  transition: background-color 0.2s ease, color 0.2s ease;
}
.switcher__btn--active {
  background-color: var(--background-white);
  color: var(--text-primary-inverse);
}

/* --- Table of talks --- */
.program__table {
  display: flex;
  flex-direction: column;
}
.program__row {
  display: flex;
  gap: clamp(24px, 5.4vw, 78px);
  align-items: flex-start;
  padding: 32px 0 40px;
  border-bottom: 2px solid var(--border-white);
}
.program__row:first-child {
  padding-top: 0;
}
/* Last row of a day sits right above the banner — its own bottom divider
   would double up with the banner's edge, so drop it. */
.program__day > .program__row:last-child {
  border-bottom: none;
}
.program__time {
  display: none; /* hidden per client request — not in the markup either; kept in case it returns */
  flex: 0 0 auto;
  width: clamp(64px, 8vw, 89px);
  font-size: clamp(24px, 2.2vw, var(--t-accent2-size));
  font-weight: var(--t-accent2-weight);
  line-height: var(--t-accent2-lh);
  letter-spacing: var(--t-accent2-ls);
  color: var(--text-primary);
}
.program__items {
  flex: 1 1 auto;
  display: flex;
  gap: clamp(24px, 5.5vw, 80px);
}
.talk {
  flex: 1 1 0;
  min-width: 0;
  max-width: calc(50% - 40px); /* a lone card stays left-aligned, not full width */
  min-height: clamp(260px, 24vw, 346px); /* push the author down — bigger gap under the title */
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 32px;
}
/* A row with a single speaker (the whole row belongs to one talk, not split
   between two) spans the full row width instead of staying half-width. */
.talk--full {
  /* full row width, but capped to a comfortable reading measure — otherwise
     a short single-speaker title stretches into one very long line */
  max-width: 820px;
}
.talk__title {
  margin: 0;
  display: flex;
  align-items: flex-start;
  gap: 16px;
  /* same size as the program-banner title ("Хотите стать спикером?") */
  font-size: clamp(24px, 3vw, var(--t-accent-size));
  font-weight: var(--t-accent-weight);
  line-height: var(--t-accent-lh);
  letter-spacing: var(--t-accent-ls);
  color: var(--text-primary);
}
/* Coloured square marking every row (matches the speaker's green/purple, so
   it stays consistent with the hidden photo tile if that ever comes back). */
.talk__title-dot {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  margin-top: 15px; /* level with the cap height of the first line, not the whole block */
  background-color: var(--background-green);
}
.talk__title-dot--purple {
  background-color: var(--background-purple);
}
.talk__title--solo {
  align-self: center; /* single-line rows centre the title against the time */
}
/* "Интерактив" (and similar standalone segments): bigger + a bigger dot so
   it doesn't read as flat as a plain talk title. */
/* Title + a "feature" tag stacked at the top of a talk card */
.talk__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
}
/* Green "Воркшоп" tag that flags workshops apart from the lectures */
.talk__feature {
  align-self: flex-start;
  /* lines up with the title's text, not the dot before it — same 32px
     offset used for .talk__author (dot 16px + its 16px gap) */
  margin-left: 32px;
  padding: 5px 14px;
  border-radius: 999px;
  background-color: var(--background-green);
  color: var(--text-primary-inverse);
  font-size: var(--t-caption-size);
  font-weight: var(--t-caption-weight);
  line-height: var(--t-caption-lh);
  letter-spacing: var(--t-caption-ls);
}
.program__row--single {
  align-items: center;
}
.talk__author {
  display: flex;
  align-items: flex-end;
  gap: 20px;
  /* lines up with the title's text, not the dot before it (dot 16px + its
     16px gap) — matters now that the photo tile is hidden and this is the
     only thing left in the row to align */
  margin-left: 32px;
}
/* Speaker placeholder: dark tile, a soft coloured glow, a person silhouette.
   Hidden per client request (they don't want the silhouette placeholder) —
   markup is kept as-is so it can be turned back on (or swapped for real
   photos) later without rebuilding the talk cards. */
.talk__photo {
  display: none; /* was: flex — restore this to bring the placeholder back */
  position: relative;
  flex: 0 0 auto;
  width: clamp(96px, 9.2vw, 132px);
  aspect-ratio: 132 / 154;
  overflow: hidden;
  background-color: var(--background-transparent-1);
  align-items: flex-end;
  justify-content: center;
}
.talk__glow {
  position: absolute;
  top: -28px;
  right: -28px; /* pushed into the top-right corner */
  width: 136px;
  height: 162px;
  border-radius: 50%; /* soft ellipse */
  opacity: 0.48;
  filter: blur(32px);
  pointer-events: none;
}
.talk__photo--green .talk__glow {
  background-color: var(--background-green);
}
.talk__photo--purple .talk__glow {
  background-color: var(--background-purple);
}
.talk__icon {
  position: relative; /* above the glow */
  width: 84%;
  height: auto;
  display: block;
}
.talk__person {
  display: flex;
  flex-direction: column;
  gap: 9px;
  min-width: 0;
}
.talk__tba {
  font-size: clamp(16px, 1.67vw, var(--t-primaccent-size));
  font-weight: var(--t-primaccent-weight);
  line-height: 1.2;
  color: var(--text-tertiary);
}
/* A confirmed speaker's real name/role — full white, not dimmed like the
   "Скоро объявим" placeholder. The role/affiliation on the second line stays
   grey so the name itself pops. */
.talk__tba--name {
  color: var(--text-primary);
}
.talk__tba-role {
  color: var(--text-tertiary);
}

/* --- "Watch online" banner --- */
.program-banner {
  display: flex;
  align-items: center;
  gap: 24px;
  margin-top: 0; /* sits flush against the bottom edge of the last event */
  padding: clamp(24px, 2.8vw, 40px);
  background-color: var(--background-transparent); /* same plate as the switcher */
}
.program-banner__text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.program-banner__title {
  margin: 0;
  font-size: clamp(24px, 3vw, var(--t-accent-size));
  font-weight: var(--t-accent-weight);
  line-height: var(--t-accent-lh);
  color: var(--text-primary);
}
.program-banner__title--live {
  display: flex;
  align-items: flex-start; /* the text can wrap to 2 lines — keep the dot on the first */
  gap: 14px;
}
.program-banner__live {
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  /* drop the dot onto the first line's optical centre (leading + cap height)
     instead of the top of the line box */
  margin-top: 0.42em;
  background-color: #ff3b30;
}
@media (prefers-reduced-motion: no-preference) {
  .program-banner__live {
    animation: liveBlink 1.8s ease-in-out infinite;
  }
}
@keyframes liveBlink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.25; }
}
/* Desktop: force "Часть докладов…" onto its own second line. On mobile the
   text already wraps in the narrow banner, so drop the hard break there. */
@media (max-width: 768px) {
  .program-banner__nl {
    display: none;
  }
}
.program-banner__sub {
  margin: 0;
  font-size: clamp(16px, 1.7vw, 24px);
  font-weight: 500;
  line-height: 1.4;
  color: var(--text-secondary);
}
.program-banner__btn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 16px;
  height: clamp(64px, 6.8vw, 98px);
  padding: 0 clamp(28px, 3vw, 44px);
  border-radius: 9999px;
  background-color: var(--background-purple);
  color: var(--text-primary);
  font-size: clamp(18px, 2.08vw, var(--t-accent1-size));
  font-weight: var(--t-accent1-weight);
  line-height: var(--t-accent1-lh);
  white-space: nowrap;
}
/* purple resting background — a purple fill-sweep would be invisible, so it
   fills green instead (text switches to dark, like the tariff buttons) */
.program-banner__btn.btn-fill::after { background-color: var(--background-green); }
.program-banner__btn.btn-fill:hover,
.program-banner__btn.btn-fill:focus-visible { color: var(--text-primary-inverse); }

/* "Подписаться" (Tariffs banner): white background, black text at rest —
   the default purple fill-sweep works fine here, so no green override needed */
.program-banner__btn--white {
  background-color: var(--background-white);
  color: var(--text-primary-inverse);
}
.program-banner__btn--white.btn-fill::after { background-color: var(--background-purple); }
.program-banner__btn--white.btn-fill:hover,
.program-banner__btn--white.btn-fill:focus-visible { color: var(--text-primary); }
.program-banner__icon {
  width: clamp(28px, 2.5vw, 36px);
  height: clamp(28px, 2.5vw, 36px);
  flex: 0 0 auto;
}

/* -------------------------------------------------------------------------
   7e. PLACE (venue) — text column + photo slider
   ------------------------------------------------------------------------- */
.place {
  position: relative;
  z-index: 1;
  width: 100%;
  box-sizing: border-box;
  padding: clamp(64px, 7vw, 120px) var(--layout-pad);
  display: flex;
  gap: 64px;
  align-items: stretch;
}
.place__text {
  /* percentage basis (not 0) so it shrinks together with the photo,
     proportionally, instead of collapsing to near-nothing whenever the
     photo's own basis alone exceeds the available width */
  flex: 1 1 30%;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.place__title {
  margin: 0;
  font-size: clamp(36px, 4.4vw, var(--t-section-size));
  font-weight: var(--t-section-weight);
  line-height: var(--t-section-lh);
  letter-spacing: var(--t-section-ls);
  color: var(--text-primary);
}
.place__body {
  margin: clamp(20px, 1.7vw, 24px) 0 0;
  max-width: 530px;
  font-size: clamp(18px, 1.7vw, 24px);
  font-weight: 500;
  line-height: 1.4;
  color: var(--text-primary);
}
.place__map {
  margin-top: auto; /* pin to the bottom of the column */
  padding-top: 40px;
  display: inline-flex;
  align-items: center;
  gap: 16px;
  align-self: flex-start;
}
.place__map-icon {
  width: 48px;
  height: 48px;
  border-radius: 8px;
  flex: 0 0 auto;
  object-fit: cover;
}
.place__map-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.place__addr {
  font-size: 18px;
  font-weight: 500;
  line-height: 1.32;
  letter-spacing: 0.02em;
  color: var(--text-primary);
}
.place__map-link {
  font-size: 18px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.02em;
  color: #8a8a8c;
}

/* --- photo slider --- */
/* Desktop: arrow slider. Mobile (≤768): plain horizontal scroll (see media query). */
.place__media {
  flex: 1 1 64%;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 16px;
}
.place__nav {
  flex: 0 0 auto;
  width: 64px;
  height: 64px;
  border: 0;
  border-radius: 50%;
  background-color: var(--background-transparent);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.2s ease;
}
.place__nav:hover { background-color: rgba(255, 255, 255, 0.22); }
.place__nav img { width: 31px; height: 31px; display: block; }
.place__slider {
  flex: 1 1 0;
  min-width: 0;
  /* fill the row's full height (matches the text column via .place's own
     align-items:stretch) instead of centering at a fixed aspect-ratio —
     top and bottom now line up with the text column exactly */
  align-self: stretch;
  border-radius: 32px;
  overflow: hidden;
  position: relative;
}
.place__track {
  display: flex;
  height: 100%;
  transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);
}
.place__slide {
  flex: 0 0 100%;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.place__dots {
  display: none; /* desktop uses the arrow slider; dots are mobile-only */
}

/* -------------------------------------------------------------------------
   7f. WHAT IS STEPIK — three big stats joined by a spine that emerges from
   green/purple tunnel mouths (line draws on scroll). Centred stack, fluid.
   ------------------------------------------------------------------------- */
.whatis {
  position: relative;
  z-index: 1;
  width: 100%;
  box-sizing: border-box;
  /* more air above (from Тарифы) than the old shared value, and even more
     below (into Finale) — the client flagged both gaps as too tight/low
     contrast against the surrounding sections (bumped a second time, +70px
     more on both sides on top of the first round) */
  padding: clamp(166px, 16vh, 290px) var(--layout-pad) calc(clamp(72px, 11vh, 180px) + 150px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.whatis__label {
  /* extra +40px per the client's annotated screenshot, on top of the earlier
     round of spacing bumps */
  margin: 0 0 clamp(256px, 16vh, 380px);
  max-width: 900px;
  /* at least 2x the old fixed 18px per client request (36px floor, scales to 64px) */
  font-size: clamp(36px, 4.4vw, var(--t-section-size));
  font-weight: var(--t-section-weight);
  line-height: 1.2;
  letter-spacing: var(--t-section-ls);
  color: var(--text-primary);
}
.whatis__stat {
  margin: 0;
  font-size: clamp(40px, 11vw, var(--t-bignum-size));
  font-weight: var(--t-bignum-weight);
  line-height: 1;
  letter-spacing: 0;
  color: var(--text-primary);
}
.whatis__seg {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 40px 0; /* 40px from the text to the coloured mouths, same as the top tunnel */
}
.whatis__mouth {
  flex: 0 0 auto;
  /* landscape (wider than tall) at every width, like the desktop tunnel mouths:
     both dimensions scale together with floors so it never goes portrait */
  width: max(36px, calc(100vw * 48 / 1440));
  height: max(30px, calc(100vw * 40 / 1440));
}
.whatis__mouth--green { background-color: var(--background-green); }
.whatis__mouth--purple { background-color: var(--background-purple); }
.whatis__line {
  /* match the upper spine thickness (About/Points: 32/1440 vw) */
  width: max(12px, calc(100vw * 32 / 1440));
  height: clamp(340px, 50vh, 720px); /* long road so the draw really reads */
  background-color: var(--border-white);
  transform-origin: top center;
}
/* hide the line before it draws (avoid a flash); reduced motion keeps it shown */
@media (prefers-reduced-motion: no-preference) {
  .whatis__line { transform: scaleY(0); }
}

/* -------------------------------------------------------------------------
   7g. TARIFFS — title + promo + three outlined price cards
   ------------------------------------------------------------------------- */
.tariffs {
  position: relative;
  z-index: 1;
  width: 100%;
  box-sizing: border-box;
  padding: clamp(64px, 7vw, 120px) var(--layout-pad);
  display: flex;
  flex-direction: column;
}
.tariffs__text {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(20px, 2.4vw, 32px);
  max-width: 1200px;
  margin: 0 auto clamp(48px, 6vw, 80px); /* gap to the cards below; the banner stays flush against the cards */
}
.tariffs__title {
  margin: 0;
  text-align: center;
  /* same size as the program title ("Программа мероприятия") */
  font-size: clamp(40px, 8.6vw, 124px);
  font-weight: 600;
  line-height: 1;
  color: var(--text-primary);
}
/* "What's included" — one descriptive sentence under the title */
.tariffs__includes {
  margin: 0;
  max-width: 720px;
  text-align: center;
  font-size: clamp(18px, 1.6vw, 22px);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
}
.tariffs__cards {
  display: flex;
  gap: clamp(16px, 2.4vw, 32px); /* 32px between cards on wide screens */
  margin-bottom: 40px; /* gap down to the broadcast banner below */
}
.tariff-card {
  flex: 1 1 0; /* equal width for all three cards, side by side */
  min-width: 0;
  box-sizing: border-box;
  background-color: var(--background-black);
  /* outline thickness: 24 in the 1440 canvas (NOT 32 like Points) */
  border: calc(100vw * 24 / 1440) solid;
  padding: clamp(20px, 2.2vw, 32px);
  min-height: clamp(260px, 27vw, 384px); /* taller cards on wide screens */
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 40px;
  color: var(--text-primary);
}
.tariff-card--white { border-color: var(--border-white); }
.tariff-card--green { border-color: var(--border-green); }
.tariff-card--purple { border-color: var(--border-purple); }
.tariff-card__info {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0; /* let the price shrink instead of blowing out the card */
}
/* White card only: old price stacked as its own line directly above the new
   price — both sit inside the flow, as the __info block's first child, so
   the OLD price lands at the same height as green/purple's single-line
   headline (they're also the first child of their own __info block). */
.tariff-card__price-group {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.tariff-card__price {
  font-size: clamp(32px, 4.4vw, var(--t-tabs-size));
  font-weight: var(--t-tabs-weight);
  line-height: var(--t-tabs-lh);
  letter-spacing: var(--t-tabs-ls);
}
.tariff-card__price-old {
  font-size: clamp(15px, 2vw, 28px);
  font-weight: 500;
  line-height: 1.2;
  opacity: 0.5;
  text-decoration: line-through;
}
.tariff-card__note {
  font-size: clamp(16px, 1.7vw, 24px);
  font-weight: 500;
  line-height: 1.4;
}
.tariff-card__btn {
  flex: 0 0 auto;
  align-self: flex-start;
  max-width: 100%; /* long labels ("Получить бесплатный билет") wrap instead of overflowing the card */
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  min-height: clamp(56px, 5.6vw, 72px);
  padding: 14px clamp(24px, 2.4vw, 36px);
  border-radius: 9999px;
  color: var(--text-primary-inverse);
  font-size: clamp(16px, 1.6vw, 20px);
  font-weight: var(--t-accent1-weight);
  line-height: var(--t-accent1-lh);
  text-align: left;
}
.tariff-card__btn--white { background-color: var(--background-white); }
.tariff-card__btn--green { background-color: var(--background-green); }
.tariff-card__btn--purple { background-color: var(--background-purple); }
/* purple button: a purple fill-sweep would be invisible on the purple resting
   background, so it fills green instead (text stays dark, like the green button) */
.tariff-card__btn--purple.btn-fill::after { background-color: var(--background-green); }
.tariff-card__btn--purple.btn-fill:hover,
.tariff-card__btn--purple.btn-fill:focus-visible { color: var(--text-primary-inverse); }

/* -------------------------------------------------------------------------
   7h. FINALE (CTA + photos) — big purple blur glow behind the content
   ------------------------------------------------------------------------- */
/* Clips the glow's excess bleed at the true bottom of the page (footer
   included) so it can't inflate document scroll height — sized by normal
   flow (finale-wrap + footer), unaffected by the glow's own overflow.
   Deliberately scoped here instead of html/body: overflow-y:clip on html
   made body compute its own overflow-y to auto (a real nested scroll
   box), which broke the native page scrollbar's rendering. */
.page-end {
  overflow: clip;
}
/* wrapper around FINALE + FAQ: the glow lives here and this box contains it
   (both for the horizontal scrollbar and the page scroll-height — without
   this clip the huge glow inflates the document by thousands of px). Safari
   treats `overflow: clip visible` as clip on BOTH axes, so the glow is cut at
   this box's bottom edge — the mobile glow below is sized to have fully faded
   out before then, so that cut only ever falls on transparent pixels. */
.finale-wrap {
  position: relative;
  z-index: 1;
  overflow: clip visible;
}
.finale {
  position: relative;
  z-index: 1; /* above the glow */
  width: 100%;
  box-sizing: border-box;
  /* now the last section before the footer — a normal closing padding */
  padding: clamp(64px, 8vw, 140px) var(--layout-pad) clamp(64px, 7vw, 120px);
  display: flex;
  flex-direction: column;
}
/* Closing photo grid — now the last thing before the footer, moved out from
   under FAQ per client request ("FAQ above the last photos") */
.finale-photos {
  position: relative;
  z-index: 1;
  width: 100%;
  box-sizing: border-box;
  padding: 0 var(--layout-pad) clamp(64px, 7vw, 120px);
}
/* the glow — scaled from the 1440 spec (1834 circle, blur 500, at left -197 / top 376) */
.finale__glow {
  position: absolute;
  left: calc(100vw * -197 / 1440);
  top: calc(100vw * 376 / 1440);
  width: calc(100vw * 1834 / 1440);
  height: calc(100vw * 1834 / 1440);
  border-radius: 50%;
  opacity: 0.48;
  background-color: var(--background-purple);
  filter: blur(calc(100vw * 500 / 1440));
  pointer-events: none;
  z-index: 0; /* behind FINALE & FAQ (both z-index 1) */
  transition: background-color 0.45s ease;
}
.finale__cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(28px, 3.4vw, 48px);
  text-align: center;
}
.finale__text {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(16px, 2vw, 32px);
}
.finale__title {
  margin: 0;
  font-size: clamp(36px, 8.6vw, var(--t-bignum-size));
  font-weight: var(--t-bignum-weight);
  line-height: 1;
  color: var(--text-primary);
}
.finale__subtitle {
  margin: 0;
  font-size: clamp(18px, 2.2vw, var(--t-accent2-size));
  font-weight: var(--t-accent2-weight);
  line-height: var(--t-accent2-lh);
  letter-spacing: var(--t-accent2-ls);
  color: var(--text-primary);
}
.finale__buttons {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 20px;
}
.finale__btn {
  height: clamp(64px, 6.8vw, 112px);
  padding: 0 clamp(28px, 3vw, 44px);
  border-radius: 9999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  font-size: clamp(20px, 2.08vw, var(--t-accent1-size));
  font-weight: var(--t-accent1-weight);
  line-height: var(--t-accent1-lh);
  white-space: nowrap;
}
.finale__speaker {
  background-color: var(--background-white);
  color: var(--text-primary-inverse);
}
.finale__route {
  background-color: var(--background-transparent);
  color: var(--text-primary);
}
.finale__btn-icon {
  width: clamp(28px, 2.8vw, 40px);
  height: clamp(28px, 2.8vw, 40px);
  flex: 0 0 auto;
}
.finale__photos {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.finale__row {
  display: grid;
  gap: 16px;
  height: clamp(180px, 32vw, 462px);
}
.finale__row--1 { grid-template-columns: 933fr 459fr; }
.finale__row--2 { grid-template-columns: 340fr 1052fr; }
.finale__photo {
  width: 100%;
  height: 100%;
  min-width: 0; /* let grid items shrink below the image's intrinsic size (no overlap) */
  min-height: 0;
  object-fit: cover;
  border-radius: clamp(16px, 2.2vw, 32px);
  display: block;
}

/* Hover: the purple fill sweeps up to fill the button; on the speaker button it
   also turns the glow green. */
.btn-fill {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: color 0.35s ease;
}
.btn-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  background-color: var(--background-purple);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: -1;
}
.btn-fill:hover::after,
.btn-fill:focus-visible::after { transform: scaleY(1); }
.btn-fill:hover,
.btn-fill:focus-visible { color: var(--text-primary); }

/* "Стать спикером": fill is GREEN (and the glow turns green too) — dark text on it */
.finale__speaker.btn-fill::after { background-color: var(--background-green); }
.finale__speaker.btn-fill:hover,
.finale__speaker.btn-fill:focus-visible { color: var(--text-primary-inverse); }
.finale-wrap:has(.finale__speaker:hover) .finale__glow,
.finale-wrap:has(.finale__speaker:focus-visible) .finale__glow {
  background-color: var(--background-green);
}

/* hero "Подать заявку": purple fill, but the label stays black (as in rest state) */
.plate--button.btn-fill:hover .plate__value,
.plate--button.btn-fill:focus-visible .plate__value {
  color: var(--text-primary-inverse);
}

/* -------------------------------------------------------------------------
   7i. FAQ — heading + accordion
   ------------------------------------------------------------------------- */
.faq {
  position: relative;
  z-index: 1;
  width: 100%;
  box-sizing: border-box;
  /* FAQ is now the first section in finale-wrap (top padding matches what the
     finale CTA used to open with, for the same gap from Whatis above);
     bottom padding: +100px per earlier client request for room before the photos */
  padding: clamp(64px, 8vw, 140px) var(--layout-pad) clamp(148px, calc(6vw + 100px), 200px);
}
.faq__title {
  max-width: 696px;
  margin: 0 auto clamp(40px, 5vw, 80px);
  font-size: clamp(56px, 8.6vw, var(--t-bignum-size));
  font-weight: var(--t-bignum-weight);
  line-height: 1;
  color: var(--text-primary);
}
.faq__list {
  max-width: 696px;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: 40px;
}
.faq__item {
  border-bottom: 2px solid var(--border-white);
  padding-bottom: 40px;
}
.faq__q {
  width: 100%;
  border: 0;
  background: none;
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  text-align: left;
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: clamp(20px, 2.6vw, var(--t-accent2-size));
  font-weight: var(--t-accent2-weight);
  line-height: var(--t-accent2-lh);
  letter-spacing: var(--t-accent2-ls);
}
.faq__chevron {
  width: 32px;
  height: 32px;
  flex: 0 0 auto;
  transition: transform 0.3s ease;
}
.faq__item--open .faq__chevron { transform: rotate(180deg); }
.faq__a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.35s ease;
}
.faq__item--open .faq__a { grid-template-rows: 1fr; }
.faq__a-inner {
  overflow: hidden;
}
.faq__a p {
  margin: 20px 0 0;
  max-width: 600px;
  font-size: 18px;
  font-weight: 500;
  line-height: 1.32;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
}
.faq__a a {
  color: var(--text-primary);
  text-decoration: underline;
}
.faq__a a:hover {
  color: var(--text-secondary);
}

/* -------------------------------------------------------------------------
   7j. FOOTER
   ------------------------------------------------------------------------- */
/* Logo on the far left; a right-anchored block (.footer__main) holds the nav
   links column + the social buttons. That block is the SAME 758px basis as
   the hero subtitle, so the links column starts on the hero's "power line"
   (lines up with the first nav item at 1440). +80px above and a hairline
   divider separate it from the CTA. */
.footer {
  position: relative;
  z-index: 1;
  width: 100%;
  box-sizing: border-box;
  margin-top: 80px;
  border-top: 2px solid rgba(255, 255, 255, 0.12);
  padding: clamp(48px, 5vw, 72px) var(--layout-pad) clamp(40px, 4vw, 56px);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 40px;
}
.footer__logo {
  flex: 0 0 auto;
  display: block;
  line-height: 0;
}
.footer__logo img {
  width: auto;
  height: 44px; /* a touch larger than the 32px top-bar mark */
}
.footer__main {
  flex: 0 1 758px; /* same right-anchored basis as .hero__subtitle */
  min-width: 0;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 40px;
}
.footer__links {
  display: flex;
  flex-direction: column;
  gap: 16px;
  font-size: var(--t-primary-size);
  font-weight: var(--t-primary-weight);
  line-height: var(--t-primary-lh);
  letter-spacing: var(--t-primary-ls);
  color: var(--text-secondary);
}
.footer__links a:hover {
  color: var(--text-primary);
}
.footer__social {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 18px;
}
/* Enlarged (~1.5×) high-contrast circles so they read clearly against the
   dark background. */
.footer__social-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.1);
  color: var(--text-primary);
  transition: background-color 0.2s ease, color 0.2s ease;
}
.footer__social-link svg {
  width: 36px;
  height: 36px;
}
.footer__social-link:hover {
  background-color: rgba(255, 255, 255, 0.22);
}

/* -------------------------------------------------------------------------
   4. HERO
   ------------------------------------------------------------------------- */
.hero {
  position: relative;
  z-index: 1;
  isolation: isolate;     /* keep the title/subtitle blend within the hero */
  width: 100%;            /* edge-to-edge — no centring container / max-width */
  /* Normally 100vh. On a wide/short (zoomed) window the full-width lines push
     their convergence lower (it scales with width ≈ 21.8vw), so grow the hero
     just enough that the bottom-aligned content still sits below it — this
     keeps the lines full-width and un-clipped instead of crashing the title.
     At 1440×900 the 100vh term wins, so the reference is unchanged. */
  min-height: max(100vh, calc(21.8vw + 565px));
  padding: var(--layout-pad) var(--layout-pad) 0; /* 16px gutter top/sides */
  border-bottom: var(--layout-pad) solid transparent; /* 16px bottom gutter, sits outside the clip */
  overflow: hidden;       /* clip the line layer to the plates (no green diagonal poking out) */
  display: flex;
  flex-direction: column;
  justify-content: flex-end; /* content sits at the bottom; the fixed header floats over the top */
}

/* Independent SVG line layer (purple/green corner).
   No z-index: it paints first (it's first in the DOM) so the title/subtitle
   above it can blend against it. The background gutter does not inset it —
   it spans the full hero width. */
.hero__lines {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%; /* fill the hero; slice keeps the aspect and lets the lines run
                   all the way down behind the plates at any window shape, so
                   they never float short of the plates */
  pointer-events: none;
  overflow: hidden;    /* clip the long vertical line to the hero region */
}

/* Line strokes (colours from the Figma variables) */
.hero__line {
  fill: none;
}
.hero__line--purple {
  stroke: var(--border-purple);
}
.hero__line--green {
  stroke: var(--border-green);
}
.hero__line--white {
  stroke: var(--border-white);
}

/* Hide the hero lines before the draw animation runs, so they don't flash
   in fully while GSAP is still loading. Each path is shorter than 2000, so a
   2000 dash + offset fully hides it; GSAP then sets the exact length and
   draws to 0. Reduced-motion users skip the animation, so keep them visible. */
@media (prefers-reduced-motion: no-preference) {
  .hero__line {
    stroke-dasharray: 2000;
    stroke-dashoffset: 2000;
  }
}

/* --- Top bar (logo + menu): fixed site header that hides on scroll-down and
       reveals on scroll-up (toggled from script.js). --- */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 150; /* above content, below the mobile menu overlay (200) */
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--layout-pad); /* matches the hero's 16px gutter */
  transition: transform 0.35s ease, background-color 0.3s ease,
    backdrop-filter 0.3s ease;
}
.topbar--hidden {
  transform: translateY(-100%); /* slid up out of view on scroll-down */
}
.topbar--solid {
  /* readable backing once it floats over page content (not over the hero top) */
  background-color: rgba(0, 0, 0, 0.72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.topbar__menu {
  display: flex;
  align-items: center;
  gap: 32px;
  font-size: var(--t-primary-size);
  font-weight: var(--t-primary-weight);
  line-height: var(--t-primary-lh);
  letter-spacing: var(--t-primary-ls);
  color: var(--text-secondary);
  white-space: nowrap;
}

.topbar__menu a:hover {
  color: var(--text-primary);
}

/* --- Hero content (title + subtitle + CTA) --- */
.hero__content {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 20px; /* title/subtitle sit ~20px lower, closer to the plates */
}

.hero__title-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between; /* title hugs left, subtitle hugs right */
  gap: 32px;
}

.hero__title {
  margin: 0;
  max-width: 100%;
  flex: 0 0 auto;
  font-size: clamp(52px, 10.8vw, var(--t-page-size)); /* fluid, caps at the token */
  font-weight: var(--t-page-weight);
  line-height: var(--t-page-lh);
  letter-spacing: var(--t-page-ls);
  color: var(--text-primary);
  mix-blend-mode: difference; /* inverts where it overlaps the line layer */
}

.hero__subtitle {
  margin: 0 0 6px;
  /* Right-anchored. The subtitle no longer blends, so it must never overlap
     the white hero line (vertical stroke at ~50% of the viewport → right edge
     ≈ 51.1vw). Two behaviours, blended with min():
       • 758px basis = left edge lines up with the first nav item (the "power
         line"). Used on wide screens, where that still clears the line.
       • calc(48.9vw - 48px) = pin the left edge ~32px to the right of the
         line. Takes over once the nav-aligned position would come closer
         than 32px (around 1650px and below).
     Whichever is NARROWER wins, so the text stays ≥32px off the line while
     preferring nav alignment when there's room. Shrinking only helps. */
  flex: 0 1 min(758px, calc(48.9vw - 48px));
  min-width: 0;
  max-width: 100%;
  font-size: clamp(22px, 2.78vw, var(--t-accent-size)); /* fluid, caps at the token */
  font-weight: var(--t-accent-weight);
  line-height: var(--t-accent-lh);
  letter-spacing: var(--t-accent-ls);
  color: var(--text-primary);
  overflow-wrap: break-word; /* never spill past the container edge */
  /* no blend mode — the subtitle just sits on top, the line passes under it */
}

/* --- CTA plates (place / date / button) --- */
.hero__cta {
  display: flex;
  gap: 8px;
  /* spans the full content width; the 16px gutter comes from the hero padding */
}

.plate {
  flex: 1 1 0;
  min-width: 0;
  min-height: 148px; /* grows if text wraps at narrow widths instead of clipping */
  padding: 20px 24px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.plate--place {
  position: relative; /* anchor for the school logo */
  background-color: var(--background-purple);
}
.plate__logo {
  position: absolute;
  top: 20px;
  right: 24px;
  width: clamp(40px, 3.2vw, 46px);
  height: auto;
}

.plate--date {
  background-color: var(--background-white);
}

.plate--button {
  background-color: var(--background-green);
  justify-content: flex-end;
}

.plate__label {
  font-size: var(--t-caption-size);
  font-weight: var(--t-caption-weight);
  line-height: var(--t-caption-lh);
  letter-spacing: var(--t-caption-ls);
  color: var(--text-secondary-inverse);
  white-space: nowrap;
}

.plate__value {
  font-size: var(--t-accent1-size);
  font-weight: var(--t-accent1-weight);
  line-height: var(--t-accent1-lh);
  letter-spacing: var(--t-accent1-ls);
  color: var(--text-primary-inverse);
}

/* Desktop: 64x64 school logo on the "Место" plate. The address is forced to
   two lines (.plate__nl in the markup); the first, shorter line clears the
   logo on its own and the second sits below it, so no big right gutter is
   needed. Mobile keeps its own smaller logo + 52px gutter (max-width:768). */
@media (min-width: 769px) {
  .plate--place .plate__logo {
    width: 64px;
    height: 64px;
  }
  .plate--place .plate__value {
    padding-right: 8px;
    /* fluid so the forced first line ("«Школа 21». Москва, ул.") fits the
       narrowing plate down to ~1280; caps at the token so 1440 is unchanged */
    font-size: clamp(26px, 2.083vw, var(--t-accent1-size));
    overflow-wrap: break-word;
  }
}

/* Below ~1280 the forced two-line address can no longer dodge the 64px logo as
   the plate narrows. Drop the manual break and reserve the logo's width so the
   address wraps naturally and always clears it (1440 keeps its look above). */
@media (min-width: 769px) and (max-width: 1280px) {
  .plate__nl {
    display: none;
  }
  .plate--place .plate__value {
    padding-right: clamp(72px, 5.6vw, 80px);
    font-size: clamp(20px, 2vw, 26px);
  }
}

/* --- Vertical tag ("10 лет конференции") pinned to the right edge --- */
.hero__tag {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(calc(-50% - 50px)); /* centred, then lifted 50px */
  z-index: 2;
  background-color: var(--background-white);
  padding: 16px 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hero__tag-text {
  margin: 0;
  writing-mode: vertical-rl;
  transform: rotate(180deg);  /* read bottom-to-top */
  text-transform: uppercase;
  white-space: nowrap;
  font-size: var(--t-tag-size);
  font-weight: var(--t-tag-weight);
  line-height: var(--t-tag-lh);
  letter-spacing: var(--t-tag-ls);
  color: var(--text-primary-inverse);
}

.hero__tag-accent {
  color: var(--border-purple);
}

/* -------------------------------------------------------------------------
   8. BURGER + MOBILE MENU (shown only on mobile)
   ------------------------------------------------------------------------- */
.topbar__burger {
  display: none; /* desktop uses the inline nav */
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  line-height: 0;
}

.menu {
  display: none; /* only mounted on mobile (see media query) */
}

/* lock background scroll while the menu is open */
html.menu-open,
html.menu-open body {
  overflow: hidden;
}

/* -------------------------------------------------------------------------
   5. RESPONSIVE
   Breakpoints: wide (>1440, handled by the clamp pulls above) · desktop ·
   small desktop (<=1280) · tablet (<=1024) · mobile (<=768) · small (<=480).
   Title/subtitle sizes are already fluid (clamp); the queries handle layout.
   ------------------------------------------------------------------------- */

/* Small desktop */
@media (max-width: 1280px) {
  .hero__content {
    gap: 32px;
  }
  .topbar__menu {
    gap: 28px;
  }
}

/* Tablet — stack the title and subtitle, drop the side tag */
@media (max-width: 1024px) {
  /* Footer: below this width the 758px right-anchored block crowds the links
     against the logo. Let .footer__main dissolve so logo / links / social
     become three even-spaced flex items (equal gaps via space-between). */
  .footer__main {
    display: contents;
  }
  .hero__title-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
  }
  .hero__subtitle {
    /* stacked layout: reset the desktop flex-basis (675px) — in this column it
       would otherwise force a 675px-tall subtitle and a huge empty gap */
    flex: 0 0 auto;
    width: auto;
    max-width: 620px;
  }
  .topbar__menu {
    /* tighter gap + smaller type so the 7 links (incl. the longer
       "Принять участие") still fit beside the logo down to 769px */
    gap: 14px;
    font-size: 16px;
  }
  .plate__value {
    font-size: 24px; /* narrower 3-col plates: keep the address readable */
  }
  .hero__tag {
    display: none;
  }

  /* Place: stack the text above the horizontal photo scroll — the side-by-side
     layout doesn't have room to breathe once the photo column gets this narrow */
  .place {
    flex-direction: column;
    gap: 28px;
  }
  .place__media {
    flex: 1 1 auto;
    width: 100%;
  }
  .place__map {
    padding-top: 28px;
  }
  /* Turn the slider into a plain horizontal scroll (no arrows) */
  .place__nav {
    display: none;
  }
  .place__slider {
    /* stacked layout: no text column to stretch-match anymore, so size by
       aspect-ratio again like before */
    align-self: auto;
    aspect-ratio: 3 / 2;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .place__slider::-webkit-scrollbar {
    display: none;
  }
  .place__track {
    transform: none !important; /* let native scroll drive position, not the JS slider */
  }
  .place__slide {
    flex: 0 0 85%; /* peek the next photo to signal scrollability */
    scroll-snap-align: start;
  }
  /* Scroll indicator dots under the photos */
  .place__dots {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-top: 18px;
  }
  .place__dot {
    width: 8px;
    height: 8px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background-color: rgba(255, 255, 255, 0.3); /* dimmed */
    cursor: pointer;
    transition: background-color 0.25s ease, transform 0.25s ease;
  }
  .place__dot--active {
    background-color: var(--text-primary, #fff); /* active */
    transform: scale(1.15);
  }
}

/* Mobile — single column throughout */
@media (max-width: 768px) {
  /* topbar: logo + burger (nav moves into the fullscreen menu) */
  .topbar__menu {
    display: none;
  }
  .topbar__burger {
    display: block;
  }
  /* The header is fixed, so reserve space at the top of the hero — otherwise
     the tall stacked content overflows up under the logo/burger (most visible
     in in-app browsers like Telegram, where the title nearly touches it). */
  .hero {
    padding-top: calc(var(--layout-pad) + 64px);
  }
  /* hero lines clutter the small screen — hide them */
  .hero__lines {
    display: none;
  }
  .hero__content {
    gap: 28px;
  }
  /* big, edge-to-edge display title like the mockup */
  .hero__title {
    font-size: clamp(64px, 19vw, 104px);
  }
  .hero__title-row {
    gap: 16px;
  }
  .hero__cta {
    flex-direction: column;
  }
  .plate {
    flex: 0 0 auto; /* size to content (stacked) so the long address never clips */
    min-height: 116px;
  }
  .plate__value {
    font-size: clamp(20px, 5.8vw, 26px); /* long address fits without clipping */
  }
  .plate__nl {
    display: none; /* let the address wrap naturally on narrow screens */
  }

  /* About: drop the scattered absolute layout for a stacked one */
  .about {
    padding-bottom: 48px;
  }
  .about__block {
    aspect-ratio: auto;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    padding: 36px 0;
  }
  .about__line {
    display: none; /* spine doesn't fit the stacked layout */
  }
  .about__tunnel {
    display: none; /* no spine on mobile, so no tunnel masking needed */
  }
  .about__text {
    position: static;
    bottom: auto;
    width: 100%;
    grid-column: 1 / -1;
    order: -2;          /* text first, above the photos */
    margin: 0 0 28px;   /* breathing room between the heading and its photos */
  }
  .about__text-inner {
    width: 100%;
    font-size: clamp(24px, 6.4vw, 34px); /* readable for the long statement */
  }
  .about__text--2 {
    width: 100%;
  }
  .about__photo {
    position: static;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 5; /* uniform portrait crop on mobile */
  }
  .about__photo--6 {
    grid-column: 1 / -1; /* the wide landscape photo spans both columns */
    order: -1;           /* and sits above the two square photos */
    aspect-ratio: 3 / 2;
  }

  /* Points: stack the cards, drop the connector lines */
  .points__inner {
    aspect-ratio: auto;
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 24px 16px;
  }
  .points__lines {
    display: none;
  }
  .points__card {
    position: static;
    width: 100%;
    aspect-ratio: auto;   /* size to content instead of a tall empty box */
    gap: 32px;
    /* border thickness matches the tariff cards on mobile */
    border-width: clamp(10px, 3.4vw, 18px);
    padding: 24px;
  }
  /* desktop swaps the green/white card CONTENTS for the right L→R reading
     order; the stacked column follows DOM order, so re-order it here to keep
     the intended sequence: 2 дня → 150+ → С 2016 года */
  .points__card--white { order: 1; }
  .points__card--green { order: 2; }
  .points__num {
    font-size: clamp(48px, 13vw, 72px); /* full-width cards: bigger, readable */
  }

  /* Themes: single column, size to content */
  .themes__grid {
    grid-template-columns: 1fr;
    gap: 12px;
  }
  .theme-card {
    aspect-ratio: auto;
    min-height: 180px;
    gap: 40px;
  }
  .theme-card__text {
    font-size: clamp(20px, 5.6vw, 26px);
  }

  /* Program: stack the time over the talks, and talks one under another */
  .program__row {
    flex-direction: column;
    gap: 16px;
    padding: 20px 0 28px;
  }
  .program__row--single {
    align-items: flex-start;
  }
  .program__time {
    width: auto;
  }
  .program__items {
    flex-direction: column;
    gap: 28px;
    width: 100%;
  }
  .talk {
    flex: 0 0 auto; /* size to content in the stacked column (don't collapse to 0) */
    gap: 20px;
    max-width: none; /* full width when stacked */
    min-height: 0; /* keep the avatar tight under its own title (clear grouping) */
  }
  .talk__title--solo {
    align-self: flex-start;
  }
  /* Drop the coloured square marker per row — not needed on mobile. The
     title text now starts flush left (no dot + gap before it), so the
     author/badge indents that matched that offset need to reset too. */
  .talk__title-dot {
    display: none;
  }
  .talk__author,
  .talk__feature {
    margin-left: 0;
  }
  /* Banner: stack text above a full-width button */
  .program-banner {
    flex-direction: column;
    align-items: stretch;
    gap: 20px;
  }
  .program-banner__btn {
    justify-content: center;
  }

  /* Tariffs: stack the cards; full-width buttons are easier to tap */
  .tariffs__cards {
    flex-direction: column;
  }
  .tariff-card {
    /* stacked in a column now, so flex-basis:0 would disable the automatic
       content-based minimum height and let the button spill past the border */
    flex: 1 1 auto;
    min-height: 200px;
    border-width: clamp(10px, 3.4vw, 18px); /* keep the outline clearly visible */
  }
  .tariff-card__btn {
    align-self: stretch;
    justify-content: center;
    text-align: center;
  }

  /* hero "Место" plate: keep the long address clear of the school logo */
  .plate--place .plate__value {
    padding-right: 52px;
  }

  /* Footer: stack logo → links → social into a left-aligned column.
     (.footer__main is display:contents from the 1024 breakpoint, so logo,
     links and social are all direct flex children here.) */
  .footer {
    flex-direction: column;
    align-items: flex-start;
    gap: 32px;
  }
  /* Finale: full-width buttons */
  .finale__buttons {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }
  .finale__btn {
    width: 100%;
  }
  /* Closing photos → a swipeable horizontal slider (the 2×2 grid is cramped
     on a phone). Flatten the rows so all four photos become equal slides. */
  .finale__photos {
    flex-direction: row;
    gap: 12px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* let the slides bleed to the screen edges, then pad so the first/last
       still align to the layout gutter */
    margin: 0 calc(-1 * var(--layout-pad));
    padding: 0 var(--layout-pad);
  }
  .finale__photos::-webkit-scrollbar {
    display: none;
  }
  .finale__row {
    display: contents; /* the 4 photos become direct slides */
  }
  .finale__photo {
    flex: 0 0 78%;
    scroll-snap-align: center;
    height: auto;
    aspect-ratio: 3 / 2;
  }

  /* Purple glow stays a blurred ellipse, but sized to fully fade out before
     the .finale-wrap bottom edge — so the (Safari) clip at that edge only
     ever falls on transparent pixels and never leaves a hard cut. */
  .finale__glow {
    left: 50%;
    top: auto;
    bottom: calc(100vw * 300 / 1440);
    transform: translateX(-50%);
    width: calc(100vw * 1300 / 1440);
    height: calc(100vw * 1000 / 1440);
    filter: blur(calc(100vw * 210 / 1440));
  }

  /* --- Fullscreen mobile menu --- */
  .menu {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 200; /* above the star layer (z 100) */
    background-color: var(--background-black);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s ease;
  }
  .menu.menu--open {
    opacity: 1;
    visibility: visible;
  }
  .menu__inner {
    height: 100%;
    display: flex;
    flex-direction: column;
    padding: 16px;
    overflow-y: auto; /* short screens: let the menu scroll instead of clipping */
  }
  .menu__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  .menu__close {
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    line-height: 0;
  }
  .menu__nav {
    display: flex;
    flex-direction: column;
    gap: clamp(14px, 3.4vw, 20px);
    margin-top: clamp(36px, 9vw, 52px); /* gap below the logo row */
  }
  .menu__nav a {
    font-size: clamp(24px, 6.4vw, 30px);
    font-weight: var(--t-accent1-weight);
    line-height: 1.1;
    color: var(--text-primary);
  }
  .menu__cta {
    margin-top: auto; /* pin the buttons to the bottom */
    padding-top: 32px; /* guaranteed gap from the nav above */
    display: flex;
    flex-direction: column;
    gap: 12px;
  }
  .menu__btn {
    height: clamp(56px, 14vw, 68px);
    border-radius: 9999px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    font-size: var(--t-primary-size);
    font-weight: var(--t-primary-weight);
    line-height: var(--t-primary-lh);
    letter-spacing: var(--t-primary-ls);
  }
  .menu__btn--white {
    background-color: var(--background-white);
    color: var(--text-primary-inverse);
  }
  .menu__btn--ghost {
    background-color: var(--background-transparent);
    color: var(--text-primary);
  }
  .menu__btn-icon {
    width: 28px;
    height: 28px;
  }
}

/* Small phones */
@media (max-width: 480px) {
  .hero__content {
    gap: 22px;
  }
  .plate {
    padding: 16px 18px;
    min-height: 104px;
  }
}
