/* ==========================================================================
   main.css — the only stylesheet (one request, no build step).
   Sections: fonts → tokens → reset → base → layout → components → pages
   Colours use light-dark(); the theme is driven by `color-scheme`, which
   follows the OS by default and is forced via [data-theme] on <html>.
   ========================================================================== */

@layer reset, base, layout, components, pages, utilities;

/* Fonts ------------------------------------------------------------------ */

/* Onest (SIL OFL 1.1) — variable, 100–900. Subsets split like Google Fonts. */
@font-face {
  font-family: Onest;
  src: url("../fonts/onest-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: Onest;
  src: url("../fonts/onest-cyrillic.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

/* Metric-matched fallbacks so the swap to Onest causes no layout shift.
   Bold gets its own face: Arial Bold is wider relative to Onest 800 than
   Arial Regular is to Onest 400, so one size-adjust can't fit both. */
@font-face {
  font-family: "Onest Fallback";
  src: local("Arial"), local("ArialMT"), local("Helvetica"), local("Liberation Sans");
  font-weight: 100 500;
  size-adjust: 105.5%;
  ascent-override: 91.94%;
  descent-override: 28.91%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "Onest Fallback";
  src: local("Arial Bold"), local("Arial-BoldMT"), local("Helvetica Bold"),
    local("Helvetica-Bold"), local("Liberation Sans Bold"), local("LiberationSans-Bold");
  font-weight: 600 900;
  size-adjust: 100%;
  ascent-override: 97%;
  descent-override: 30.5%;
  line-gap-override: 0%;
}

/* Tokens ----------------------------------------------------------------- */

:root {
  color-scheme: light dark;

  --color-brand: #ff5412;
  --color-bg: light-dark(#f3f2ee, #0f0f0e);
  --color-text: light-dark(#0e0e0d, #edece8);
  --color-text-muted: light-dark(#52514c, #a8a7a0);
  --color-text-faint: light-dark(#6b6a64, #8d8c85);
  --color-line: light-dark(#c9c7bf, #34332f);
  --color-accent: light-dark(#d63d00, #ff5412);
  --color-on-brand: #0e0e0d;
  --grain-opacity: 0.05;
  --font-sans: "Onest", "Onest Fallback", system-ui, -apple-system, "Segoe UI",
    roboto, sans-serif;
  --text-xs: 0.875rem;
  --text-sm: clamp(0.9375rem, 0.9rem + 0.15vw, 1rem);
  --text-md: clamp(1.0625rem, 0.95rem + 0.4vw, 1.25rem);
  --text-lg: clamp(1.25rem, 1rem + 0.85vw, 1.875rem);
  --text-xl: clamp(1.75rem, 1.2rem + 2.2vw, 3.25rem);
  --text-logo: clamp(1.25rem, 1.1rem + 0.45vw, 1.625rem);
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-display: 800;
  --leading-display: 0.88;
  --leading-tight: 1.2;
  --leading-normal: 1.6;
  --tracking-display: -0.025em;
  --tracking-tight: -0.01em;
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --gutter: clamp(1.25rem, 4.2vw, 4rem);
  --gap-fluid: clamp(0.625rem, 2.6vw, 2.5rem);
  --max-w: 120rem;
  --tap: 2.75rem;
  --radius-sm: 4px;
  --radius-full: 9999px;

  /* Share of the hero width the display title may take; --title-fit is the
     title's longest line width in em, so font-size = width / fit. */
  --title-share: 56cqi;
  --title-fit: 5.95;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --duration-fast: 150ms;
  --duration-base: 300ms;
  --duration-slow: 900ms;
  --duration-intro: 1200ms;
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
}

:root[data-theme="light"] {
  color-scheme: light;
}

:root[data-theme="dark"] {
  color-scheme: dark;
}

:root:lang(ru) {
  --title-fit: 7.3;
}

/* Reset ------------------------------------------------------------------ */

@layer reset {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
  }

  html {
    -webkit-text-size-adjust: 100%; /* stylelint-disable-line property-no-vendor-prefix -- iOS Safari */
    text-size-adjust: 100%;
    tab-size: 4;
  }

  img,
  picture,
  svg,
  video {
    display: block;
    max-inline-size: 100%;
  }

  input,
  button,
  textarea,
  select {
    font: inherit;
    color: inherit;
  }

  button {
    background: none;
    border: 0;
    cursor: pointer;
  }

  ul,
  ol {
    list-style: none;
  }

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

  h1,
  h2,
  h3,
  p {
    overflow-wrap: break-word;
  }

  [hidden] {
    display: none !important;
  }
}

/* Base ------------------------------------------------------------------- */

@layer base {
  html {
    background-color: var(--color-bg);
    color: var(--color-text);
    font-family: var(--font-sans);
    font-size: 100%;
    font-synthesis: none;
    line-height: var(--leading-normal);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizelegibility;
  }

  body {
    display: grid;
    grid-template-rows: auto 1fr auto;
    grid-template-columns: minmax(0, 1fr);
    min-block-size: 100vh;
    min-block-size: 100svh;
    font-size: var(--text-sm);
    font-weight: var(--weight-regular);
  }

  /* Paper grain, as in the reference design. Decorative only. */
  body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    opacity: var(--grain-opacity);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5 0 0 0 0 .5 0 0 0 0 .5 0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  }

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

  ::selection {
    background-color: var(--color-brand);
    color: var(--color-on-brand);
  }

  @media (prefers-reduced-motion: no-preference) {
    html:focus-within {
      scroll-behavior: smooth;
    }
  }
}

/* Layout ----------------------------------------------------------------- */

@layer layout {
  .site-header,
  .site-footer,
  .site-main {
    inline-size: 100%;
    max-inline-size: var(--max-w);
    margin-inline: auto;
    padding-inline: var(--gutter);
  }

  .site-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding-block: clamp(1rem, 4.5vh, 2.75rem);
  }

  .site-main {
    display: grid;
    padding-block: clamp(2rem, 6vh, 5rem);
  }

  .site-main:focus {
    outline: none;
  }

  .site-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4) var(--space-8);
    padding-block: var(--space-8) clamp(1.5rem, 9vh, 6.5rem);
  }
}

/* Components ------------------------------------------------------------- */

@layer components {
  /* Skip link */
  .skip-link {
    position: absolute;
    inset-block-start: var(--space-2);
    inset-inline-start: var(--space-2);
    z-index: 10;
    padding: var(--space-2) var(--space-4);
    background-color: var(--color-text);
    color: var(--color-bg);
    font-weight: var(--weight-semibold);
    border-radius: var(--radius-sm);
    translate: 0 -200%;
    transition: translate var(--duration-fast) ease;
  }

  .skip-link:focus-visible {
    translate: 0 0;
  }

  /* Logo */
  .logo {
    display: inline-flex;
    align-items: center;
    min-block-size: var(--tap);
    font-size: var(--text-logo);
    font-weight: var(--weight-semibold);
    letter-spacing: 0.02em;
    line-height: 1;
    transition: opacity var(--duration-fast) ease;
  }

  .logo:hover {
    opacity: 0.65;
  }

  /* Header toolbar: nav | languages | theme */
  .toolbar {
    display: flex;
    align-items: center;
    gap: var(--gap-fluid);
  }

  .nav__list {
    display: flex;
    gap: clamp(0.625rem, 2.8vw, 3.5rem);
  }

  .nav__link,
  .lang__link,
  .lang__current {
    display: inline-flex;
    align-items: center;
    min-block-size: var(--tap);
  }

  .nav__link {
    position: relative;
    font-size: var(--text-sm);
  }

  .nav__link::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0.6rem;
    block-size: 1px;
    background-color: currentcolor;
    scale: 0 1;
    transform-origin: right;
    transition: scale var(--duration-base) var(--ease-out);
  }

  .nav__link:hover::after,
  .nav__link[aria-current="page"]::after {
    scale: 1 1;
    transform-origin: left;
  }

  .lang {
    display: flex;
    align-items: center;
    gap: clamp(0.375rem, 1.6vw, 1.5rem);
    font-size: var(--text-xs);
    line-height: 1;
  }

  .lang::before {
    content: "";
    inline-size: 1px;
    block-size: 1.5rem;
    margin-inline-end: calc(var(--gap-fluid) - clamp(0.375rem, 1.6vw, 1.5rem));
    background-color: var(--color-line);
  }

  .lang__link,
  .lang__current {
    min-inline-size: 1.5rem;
    justify-content: center;
  }

  .lang__link {
    color: var(--color-text-faint);
    transition: color var(--duration-fast) ease;
  }

  .lang__link:hover {
    color: var(--color-text);
  }

  .lang__current {
    font-weight: var(--weight-semibold);
  }

  /* Theme toggle: shown only when JS is available (it needs JS to work). */
  .theme-toggle {
    display: none;
    place-items: center;
    inline-size: var(--tap);
    block-size: var(--tap);
    margin-inline-end: calc(var(--space-3) * -1);
    border-radius: var(--radius-full);
  }

  .js .theme-toggle {
    display: grid;
  }

  .theme-toggle svg {
    grid-area: 1 / 1;
    inline-size: 1.5rem;
    block-size: 1.5rem;
    transition:
      opacity var(--duration-base) ease,
      rotate var(--duration-base) var(--ease-out);
  }

  .theme-toggle__moon {
    opacity: 0;
    rotate: -45deg;
  }

  [data-theme="dark"] .theme-toggle__sun {
    opacity: 0;
    rotate: 90deg;
  }

  [data-theme="dark"] .theme-toggle__moon {
    opacity: 1;
    rotate: 0deg;
  }

  .theme-toggle:hover .theme-toggle__sun {
    rotate: 45deg;
  }

  /* Footer socials */
  .social {
    font-style: normal;
    display: flex;
    flex-wrap: wrap;
    column-gap: clamp(1.5rem, 4.5vw, 4.5rem);
  }

  .social__link {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    min-block-size: var(--tap);
  }

  .social__link svg {
    inline-size: 0.75rem;
    block-size: 0.75rem;
    transition: translate var(--duration-base) var(--ease-out);
  }

  .social__link:hover svg {
    translate: 2px -2px;
    color: var(--color-accent);
  }

  .copyright {
    color: var(--color-text-faint);
    font-size: var(--text-sm);
  }

  /* Inline text link (body copy) */
  .text-link {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.2em;
    text-decoration-color: var(--color-line);
    transition: text-decoration-color var(--duration-fast) ease;
  }

  .text-link:hover {
    text-decoration-color: currentcolor;
  }

  /* Tech stack list with dot separators */
  .stack {
    color: var(--color-text-muted);
    font-size: var(--text-md);
    line-height: 2.1;
  }

  .stack li {
    display: inline;
  }

  .stack li:not(:nth-child(3n))::after {
    content: "";
    display: inline-block;
    inline-size: 3px;
    block-size: 3px;
    margin-inline: 1.3em;
    vertical-align: middle;
    border-radius: var(--radius-full);
    background-color: currentcolor;
  }

  .stack li:nth-child(3n)::after {
    content: "\A";
    white-space: pre;
  }

  /* Display title: fills a fixed share of the hero width */
  .display {
    overflow-wrap: normal;
    hyphens: manual;
    font-size: calc(var(--title-share) / var(--title-fit));
    font-weight: var(--weight-display);
    line-height: var(--leading-display);
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    margin-inline-start: -0.05em;
  }

  .display__line,
  .display__text {
    display: block;
  }

  .display__text {
    transform-origin: 0 100%;
  }
}

/* Pages ------------------------------------------------------------------ */

@layer pages {
  /* Home hero */
  .hero {
    container-type: inline-size;
    display: grid;
    align-content: center;
  }

  .hero__inner {
    display: grid;
    grid-template-columns: max-content 1px minmax(15rem, 22rem);
    align-items: center;
    column-gap: clamp(2rem, 4vw, 4rem);
  }

  .hero__rule {
    align-self: stretch;
    background-color: var(--color-line);
    transform-origin: top;
  }

  .hero__aside {
    display: grid;
    gap: var(--space-6);
    padding-block-start: 0.35em;
  }

  .hero__name {
    font-size: var(--text-lg);
    font-weight: var(--weight-regular);
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-tight);
  }

  .hero__desc {
    max-inline-size: 15em;
    color: var(--color-text-muted);
    font-size: var(--text-md);
    line-height: var(--leading-normal);
  }

  .hero .stack {
    margin-block-start: var(--space-4);
  }

  @media (width <= 56rem) {
    .hero {
      --title-share: 100cqi;

      align-content: start;
    }

    .hero__inner {
      grid-template-columns: minmax(0, 1fr);
      row-gap: var(--space-8);
    }

    .hero__rule {
      --rule-from: 0 1;

      inline-size: var(--space-16);
      block-size: 1px;
      transform-origin: left;
    }

    .hero__aside {
      padding-block-start: 0;
    }
  }

  /* Inner pages (about, work, 404) */
  .page {
    container-type: inline-size;
    display: grid;
    align-content: start;
    gap: clamp(2.5rem, 6vh, 4.5rem);
  }

  .page__title {
    font-size: clamp(3.5rem, 15cqi, 11rem);
  }

  .page__lead {
    max-inline-size: 26em;
    font-size: var(--text-xl);
    font-weight: var(--weight-regular);
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-tight);
    text-wrap: balance;
  }

  .page__section {
    display: grid;
    grid-template-columns: minmax(8rem, 1fr) minmax(0, 2fr);
    gap: var(--space-4) var(--gutter);
    padding-block-start: var(--space-6);
    border-block-start: 1px solid var(--color-line);
  }

  .page__heading {
    color: var(--color-text-faint);
    font-size: var(--text-sm);
    font-weight: var(--weight-regular);
    line-height: var(--leading-normal);
  }

  .page__body {
    display: grid;
    gap: var(--space-4);
    max-inline-size: 38rem;
    color: var(--color-text-muted);
    font-size: var(--text-md);
    text-wrap: pretty;
  }

  .page__body strong {
    color: var(--color-text);
    font-weight: var(--weight-medium);
  }

  .facts {
    display: grid;
    gap: var(--space-3);
  }

  .facts > div {
    display: grid;
    grid-template-columns: minmax(7rem, 1fr) 2fr;
    gap: var(--space-4);
  }

  .facts dt {
    color: var(--color-text);
  }

  @media (width <= 40rem) {
    .page__section,
    .facts > div {
      grid-template-columns: minmax(0, 1fr);
      gap: var(--space-2);
    }
  }

  /* Short screens / landscape phones: let the hero breathe */
  @media (height <= 34rem) and (width >= 56.01rem) {
    .hero {
      --title-share: 48cqi;
    }
  }
}

/* Utilities -------------------------------------------------------------- */

@layer utilities {
  .sr-only {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  /* Screen-reader-only text in another script (e.g. "Русский" on EN pages)
     uses a system font so it doesn't trigger a download of that subset. */
  .sr-only[lang],
  [lang] > .sr-only {
    font-family: system-ui, sans-serif;
  }

  /* Intro. js/intro.js adds .intro (hold everything) and then .intro-play
     once the display font has loaded, so the title never visibly swaps
     from the fallback font. Without that script nothing is held back. */
  @media (prefers-reduced-motion: no-preference) {
    .intro .display__line {
      clip-path: inset(-0.1em -0.3em -0.22em);
    }

    .intro-play .reveal,
    html:not(.intro) .reveal {
      animation: reveal var(--duration-slow) var(--ease-out) both;
      animation-delay: calc(var(--i, 0) * 120ms + 450ms);
    }

    .intro-play .display__text {
      animation: title-rise var(--duration-intro) var(--ease-out-expo) both;
      animation-delay: calc(var(--line, 0) * 120ms);
    }

    .intro-play .hero__rule {
      animation: rule-grow var(--duration-intro) var(--ease-out-expo) 350ms both;
    }

    .intro:not(.intro-play) .display__text {
      translate: 0 120%;
    }

    .intro:not(.intro-play) :is(.hero__rule, .reveal) {
      opacity: 0;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .intro:not(.intro-play) :is(.display, .hero__rule, .reveal) {
      opacity: 0;
    }
  }

  .display__line + .display__line {
    --line: 1;
  }

  .site-footer.reveal {
    --i: 2;
  }

  @keyframes title-rise {
    from {
      translate: 0 120%;
      rotate: 4deg;
    }
  }

  @keyframes rule-grow {
    from {
      scale: var(--rule-from, 1 0);
    }
  }

  @keyframes reveal {
    from {
      opacity: 0;
      translate: 0 0.75rem;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
      transition-duration: 0.01ms !important;
      animation-duration: 0.01ms !important;
    }
  }

  @media (forced-colors: active) {
    .hero__rule {
      background-color: CanvasText;
    }

    .stack li::after {
      background-color: CanvasText;
    }
  }

  @media print {
    body::before,
    .theme-toggle,
    .skip-link {
      display: none !important;
    }
  }
}
