/* =========================================================================
   ferokuk.dev — site stylesheet
   Every visual value here is copied verbatim from "Ferokuk Portfolio.dc.html".
   Do not round, re-derive or "improve" any value.

   FONTS: no @font-face here. Google Fonts is loaded from <head> in index.html:
     <link rel="preconnect" href="https://fonts.googleapis.com">
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
     <link href="https://fonts.googleapis.com/css2?family=Golos+Text:wght@400;500;600;700;800;900&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet">

   TABLE OF CONTENTS
     1. Tokens
     2. Global rules (verbatim from the design's <helmet><style>)
     3. Layout primitives & utilities
     4. Components
        4.1  Backdrop        4.2  Header / nav      4.3  Hero
        4.4  Pipeline panel  4.5  Hero stats        4.6  Marquee
        4.7  Section shell   4.8  Project cards     4.9  Stack cards
        4.10 Timeline        4.11 Education         4.12 Contact
        4.13 Footer
     5. Hover rules (the 50 style-hover attributes from the design)
     6. Responsive (replaces the JS-driven layout in componentDidMount)
   ========================================================================= */


/* =========================================================================
   1. TOKENS
   --acc / --acc2 keep their exact names: app.js reads them with
   getComputedStyle(document.documentElement).getPropertyValue('--acc').
   ========================================================================= */
:root{
  /* palette */
  --acc:#E8FF4D;
  --acc2:#52A8FF;
  --bg:#0A0B0E;
  --ink:#F1F3EC;
  --muted:#8B9188;
  --dim:#6E756D;

  /* ink alpha ladder — rgba(241,243,236,.XX) */
  --ink-02:rgba(241,243,236,.02);
  --ink-025:rgba(241,243,236,.025);
  --ink-03:rgba(241,243,236,.03);
  --ink-045:rgba(241,243,236,.045);
  --ink-05:rgba(241,243,236,.05);
  --ink-07:rgba(241,243,236,.07);
  --ink-08:rgba(241,243,236,.08);
  --ink-09:rgba(241,243,236,.09);
  --ink-10:rgba(241,243,236,.1);
  --ink-12:rgba(241,243,236,.12);
  --ink-13:rgba(241,243,236,.13);
  --ink-14:rgba(241,243,236,.14);
  --ink-22:rgba(241,243,236,.22);
  --ink-24:rgba(241,243,236,.24);
  --ink-28:rgba(241,243,236,.28);
  --ink-42:rgba(241,243,236,.42);
  --ink-45:rgba(241,243,236,.45);
  --ink-50:rgba(241,243,236,.5);

  /* bg alpha ladder — rgba(10,11,14,.XX) */
  --bg-30:rgba(10,11,14,.3);
  --bg-35:rgba(10,11,14,.35);
  --bg-40:rgba(10,11,14,.4);
  --bg-42:rgba(10,11,14,.42);
  --bg-45:rgba(10,11,14,.45);
  --bg-50:rgba(10,11,14,.5);
  --nav-bg:rgba(12,14,17,.72);

  /* type */
  --font-sans:'Golos Text',Helvetica,Arial,sans-serif;
  --font-mono:'Space Mono',monospace;

  /* motion */
  --ease-out:cubic-bezier(.2,.8,.2,1);
  --ease-pipe:cubic-bezier(.22,.61,.36,1);

  /* rhythm */
  --shell-w:1180px;
  --section-pad-y:clamp(70px,9vw,130px);
  --section-pad-x:clamp(18px,5vw,40px);
  --gap-card:clamp(16px,2vw,22px);
}


/* =========================================================================
   2. GLOBAL RULES — verbatim from the design's <helmet><style> (lines 14-42).
   app.js depends on the 'brth' / 'shk' keyframe names and on the
   [data-l] / [data-lb] selectors. Do not touch.
   ========================================================================= */
html{scroll-behavior:smooth;scroll-padding-top:98px;scrollbar-color:var(--acc) #0A0B0E;scrollbar-width:thin}
section[id]{scroll-margin-top:98px}
a:focus-visible,button:focus-visible{outline:2px solid var(--acc);outline-offset:3px}
body{margin:0;background:#0A0B0E;color:#F1F3EC;font-family:'Golos Text',Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;overflow-x:hidden}
::selection{background:var(--acc);color:#0A0B0E}
a{color:var(--acc);text-decoration:none}
a:hover{color:#F1F3EC}
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:#0A0B0E}
::-webkit-scrollbar-thumb{background:var(--acc);border-radius:99px;border:2px solid #0A0B0E}
::-webkit-scrollbar-thumb:hover{background:var(--acc)}
[data-noselect]{-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-touch-callout:none}
[data-en]{display:none}
[data-l="en"] [data-ru]{display:none}
[data-l="en"] [data-en]{display:revert}
[data-lb]{color:#8B9188;background:transparent}
[data-lb="ru"]{color:#0A0B0E;background:var(--acc)}
[data-l="en"] [data-lb="ru"]{color:#8B9188;background:transparent}
[data-l="en"] [data-lb="en"]{color:#0A0B0E;background:var(--acc)}
@keyframes mq{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
@keyframes flt{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(0,-22px,0)}}
@keyframes pls{0%,100%{opacity:.4;transform:scale(1)}50%{opacity:1;transform:scale(1.6)}}
@keyframes crt{0%,49%{opacity:1}50%,100%{opacity:0}}
@keyframes brth{0%,100%{opacity:1}50%{opacity:.6}}
@keyframes shk{0%,100%{transform:translate3d(0,0,0)}22%{transform:translate3d(-2px,0,0)}62%{transform:translate3d(2px,0,0)}}
@media (prefers-reduced-motion:reduce){*{animation:none !important;transition:none !important}}


/* =========================================================================
   3. LAYOUT PRIMITIVES & UTILITIES
   ========================================================================= */

/* page root — was ref="{{ rootRef }}" */
.app{position:relative;width:100%;min-height:100vh;overflow:clip;background:var(--bg);isolation:isolate}

/* every content section sits above the two fixed backdrop layers */
.section{position:relative;z-index:1;padding:var(--section-pad-y) var(--section-pad-x)}
.section-contact{padding:clamp(70px,9vw,130px) clamp(18px,5vw,40px) clamp(50px,6vw,80px)}

/* the 1180px measure shared by every section, the footer and the contact card */
.container{max-width:var(--shell-w);margin:0 auto}

/* utilities */
.min-w-0{min-width:0}
.flex-1{flex:1}
.mono{font-family:var(--font-mono)}
.mono-muted{font-family:var(--font-mono);color:var(--muted)}
.acc{color:var(--acc)}
.ink{color:var(--ink)}
.dim{color:var(--dim)}
.strong-ink{color:var(--ink);font-weight:600}
.is-hidden{visibility:hidden}

/* inline text link, 3px underline offset (hero lede + contact paragraph) */
.link-u{color:var(--ink);text-decoration:underline;text-decoration-color:var(--ink-28);text-underline-offset:3px;transition:color .2s,text-decoration-color .2s}
/* inline text link, 4px underline offset (job titles + education titles) */
.link-u4{color:var(--ink);text-decoration:underline;text-decoration-color:var(--ink-22);text-underline-offset:4px;transition:color .2s,text-decoration-color .2s}


/* =========================================================================
   4. COMPONENTS
   ========================================================================= */

/* ---- 4.1 Backdrop ------------------------------------------------------ */
.bg-glow{position:fixed;inset:0;z-index:0;pointer-events:none;background:radial-gradient(680px 520px at 8% -8%, color-mix(in oklab, var(--acc) 13%, transparent), transparent 68%), radial-gradient(720px 560px at 96% 8%, color-mix(in oklab, #F1F3EC 7%, transparent), transparent 68%), radial-gradient(600px 600px at 50% 108%, color-mix(in oklab, var(--acc) 7%, transparent), transparent 70%)}
.bg-grid{position:fixed;inset:0;z-index:0;pointer-events:none;opacity:.5;background-image:linear-gradient(rgba(241,243,236,.045) 1px, transparent 1px),linear-gradient(90deg, rgba(241,243,236,.045) 1px, transparent 1px);background-size:64px 64px;mask-image:radial-gradient(90% 70% at 50% 20%, #000 20%, transparent 80%)}

/* ---- 4.2 Header / nav -------------------------------------------------- */
.site-header{position:sticky;top:0;z-index:60;display:flex;justify-content:center;padding:16px 14px}
.nav{display:flex;align-items:center;gap:6px;width:100%;max-width:1000px;padding:8px 8px 8px 18px;border:1px solid var(--ink-09);border-radius:26px;background:var(--nav-bg);backdrop-filter:blur(20px) saturate(150%);box-shadow:0 22px 50px -30px rgba(0,0,0,.95)}
.brand{display:flex;align-items:center;gap:9px;color:var(--ink);font-weight:700;font-size:15px;letter-spacing:-.02em;margin-right:auto}
.brand-dot{width:9px;height:9px;border-radius:3px;background:var(--acc);box-shadow:0 0 16px var(--acc);animation:pls 2.8s ease-in-out infinite}
.brand-suffix{color:var(--muted);font-weight:500}
/* #nav-links — hidden below 900px, see §6 */
.nav-links{display:none;align-items:center;gap:2px}
.nav-link{color:var(--muted);font-size:13.5px;font-weight:500;padding:9px 13px;border-radius:14px;transition:background .2s,color .2s}
.lang-switch{display:flex;align-items:center;gap:2px;padding:3px;border:1px solid var(--ink-09);border-radius:999px;margin-left:6px}
/* colour/background of .lang-btn comes from the [data-lb] rules in §2 */
.lang-btn{border:0;cursor:pointer;font-family:var(--font-mono);font-size:11px;font-weight:700;letter-spacing:.06em;padding:7px 11px;border-radius:999px;transition:background .2s,color .2s}
.btn-cv{display:flex;align-items:center;gap:7px;background:var(--acc);color:var(--bg);font-weight:700;font-size:13.5px;padding:11px 17px;border-radius:999px;white-space:nowrap;transition:transform .3s var(--ease-out),box-shadow .3s}
.cv-arrow{font-family:var(--font-mono);font-size:12px}

/* ---- 4.3 Hero ---------------------------------------------------------- */
.hero{position:relative;z-index:1;display:flex;align-items:center;padding:clamp(40px,7vw,90px) clamp(18px,5vw,40px) clamp(70px,9vw,130px)}
/* #hero-grid — 1fr until 900px, see §6 */
.hero-grid{width:100%;max-width:var(--shell-w);margin:0 auto;display:grid;grid-template-columns:1fr;column-gap:clamp(48px,6vw,80px);row-gap:clamp(40px,4.5vw,60px);align-items:center}
.hero-badge{display:inline-flex;align-items:center;gap:10px;font-weight:600;font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);border:1px solid var(--ink-10);border-radius:999px;padding:8px 15px;background:color-mix(in oklab, var(--acc2) 7%, transparent)}
.hero-badge-dot{width:6px;height:6px;border-radius:50%;background:var(--acc);box-shadow:0 0 12px var(--acc)}
.hero-title{margin:24px 0 0;font-size:clamp(40px,7.6vw,104px);line-height:.9;letter-spacing:-.045em;font-weight:800;text-wrap:balance;overflow-wrap:anywhere;hyphens:auto}
.grad-acc{background:linear-gradient(94deg,#F1F3EC 4%,color-mix(in oklab,var(--acc) 45%,#F1F3EC) 46%,color-mix(in oklab,var(--acc) 85%,#F1F3EC) 78%,var(--acc) 100%);-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent}
/* Same ramp, reversed: for a highlighted phrase that OPENS the headline the accent has to
   land on the first word and fade out into the ink text that follows, instead of building
   towards a closing word. Stops mirror .grad-acc so both read as one gradient family. */
.grad-acc-lead{background:linear-gradient(94deg,var(--acc) 0%,color-mix(in oklab,var(--acc) 85%,#F1F3EC) 22%,color-mix(in oklab,var(--acc) 45%,#F1F3EC) 54%,#F1F3EC 96%);-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent}
/* "Высоконагруженный" is one 17-character word: measured at the 104px top clamp size it
   needs 1042px, and the hero text column is only ~633px. The h1's overflow-wrap:anywhere
   would then snap it at whatever character fills the line ("Высоконаг|руженный") with no
   hyphen. break-word demotes a mid-word break to a last resort, so the &shy; points in the
   markup win and render a real hyphen when one is genuinely needed (narrow phones). */
.grad-acc-lead{overflow-wrap:break-word;word-break:normal}

/* RU runs longer than EN here, so the shared 104px ceiling cannot hold the lead word on
   one line. Widen the RU column slightly and cap at the largest size where the lead word
   still fits whole; EN keeps the design's own clamp and narrower column. Below ~470px
   the &shy; points take over. */
[data-l="ru"] .hero-grid{grid-template-columns:1.32fr .68fr}
[data-l="ru"] .hero-title{font-size:clamp(40px,5.8vw,72px)}
.hero-lede{margin:28px 0 0;max-width:56ch;font-size:clamp(16px,1.5vw,19px);line-height:1.65;color:var(--muted);text-wrap:pretty}
.hero-actions{display:flex;flex-wrap:wrap;gap:11px;margin-top:36px}
.btn-primary{display:flex;align-items:center;gap:9px;background:var(--ink);color:var(--bg);font-weight:700;font-size:15px;padding:16px 26px;border-radius:18px;transition:transform .3s var(--ease-out),box-shadow .3s}
.btn-secondary{display:flex;align-items:center;gap:9px;border:1px solid var(--ink-12);color:var(--ink);font-weight:600;font-size:15px;padding:16px 26px;border-radius:18px;background:var(--ink-03);transition:border-color .3s,transform .3s,background .3s}

/* ---- 4.4 Pipeline panel ------------------------------------------------ */
/* The data-k / data-pod / data-conn / data-fill / data-dot / data-dot2 /
   data-track / data-src attributes are queried by app.js — keep them as
   attributes on exactly these elements. */
.panel-wrap{position:relative;justify-self:center;width:min(100%,500px);display:grid;place-items:center;padding:26px 0}
.panel-glow{position:absolute;inset:2% 3%;border-radius:44px;pointer-events:none;background:radial-gradient(120% 85% at 28% 4%, color-mix(in oklab, #F1F3EC 9%, transparent), transparent 64%), radial-gradient(115% 80% at 78% 98%, color-mix(in oklab, var(--acc) 13%, transparent), transparent 66%);filter:blur(30px)}
/* #pipeline — was ref="{{ panelRef }}" */
.panel{position:relative;width:min(100%,468px);border-radius:26px;border:1px solid var(--ink-13);background:linear-gradient(155deg, rgba(241,243,236,.1), rgba(241,243,236,.02));box-shadow:0 40px 90px -40px rgba(0,0,0,.9), inset 0 1px 0 rgba(241,243,236,.14);overflow:hidden}
.panel-head{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;border-bottom:1px solid var(--ink-09);background:var(--bg-35)}
.panel-file{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.06em;color:var(--muted)}
.panel-live{display:flex;align-items:center;gap:7px;font-family:var(--font-mono);font-size:11.5px;letter-spacing:.06em;color:var(--acc)}
.panel-live-dot{width:6px;height:6px;border-radius:50%;background:var(--acc);box-shadow:0 0 10px var(--acc);animation:pls 2.8s ease-in-out infinite}
.panel-body{padding:16px;display:flex;flex-direction:column;align-items:stretch}

/* sources row */
.pl-srcs{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.04em;line-height:1;white-space:nowrap}
.pl-src{box-sizing:border-box;text-align:center;padding:8px 4px;border:1px solid var(--ink-10);border-radius:8px;background:var(--bg-40);color:var(--muted);transition:border-color .35s var(--ease-pipe),box-shadow .35s var(--ease-pipe),color .35s var(--ease-pipe)}

/* the three-into-one bracket under the sources */
.pl-bracket{position:relative;width:66.666%;height:16px;align-self:center}
.pl-brk-l,.pl-brk-c,.pl-brk-r{position:absolute;top:0;bottom:0;width:1px;background:var(--ink-13)}
.pl-brk-l{left:0}
.pl-brk-c{left:calc(50% - .5px)}
.pl-brk-r{right:0}
.pl-brk-b{position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--ink-13)}

/* vertical connectors — [data-conn]; .pl-conn-sm is the 16px first one */
.pl-conn{position:relative;width:1px;height:20px;align-self:center;background:var(--ink-13)}
.pl-conn-sm{height:16px}
.pl-fill{position:absolute;inset:0;transform:scaleY(0);transform-origin:top;opacity:0;background:var(--ink-50)}
.pl-dot{position:absolute;left:-3.5px;top:-4px;width:8px;height:8px;border-radius:50%;background:var(--ink);opacity:0}
.pl-dot2{position:absolute;left:-2.5px;top:-3px;width:6px;height:6px;border-radius:50%;background:var(--ink-45);opacity:0}

/* node shells — shared frame + per-node body */
.pl-node{box-sizing:border-box;width:100%;border:1px solid var(--ink-14);border-radius:12px;transition:border-color .35s var(--ease-pipe),box-shadow .35s var(--ease-pipe),background .35s var(--ease-pipe)}
.pl-gw{background:var(--bg-50);padding:10px 12px;display:flex;flex-direction:column;gap:8px}
.pl-ev{height:52px;background:var(--bg-50);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-family:var(--font-mono);line-height:1.2}
.pl-af{background:var(--bg-42);padding:10px 12px 12px;display:flex;flex-direction:column;gap:8px}
.pl-out{height:40px;border-color:var(--ink-10);border-radius:10px;background:var(--bg-40);display:flex;align-items:center;justify-content:center}

/* gateway node */
.pl-gw-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px;font-family:var(--font-mono);font-size:10px;letter-spacing:.06em;line-height:1}
.pl-gw-pods{color:var(--dim);font-variant-numeric:tabular-nums}
.pl-pods{display:grid;grid-template-columns:repeat(4,24px);grid-auto-rows:8px;gap:4px}
.pl-pod{border-radius:2px;background:color-mix(in oklab, var(--acc) 44%, transparent);opacity:0;transform:scale(.9);transition:opacity .28s var(--ease-pipe),transform .28s var(--ease-pipe)}

/* event node */
.pl-ev-name{color:var(--ink);font-size:11px;letter-spacing:.08em}
.pl-ev-id{color:var(--dim);font-size:9.5px;letter-spacing:.04em}

/* antifraud node */
.pl-af-head{display:flex;align-items:baseline;justify-content:space-between;gap:8px;font-family:var(--font-mono);line-height:1}
.pl-af-title{color:var(--ink);font-size:10.5px;letter-spacing:.08em}
.pl-af-meta{color:var(--dim);font-size:8.5px;letter-spacing:.04em;white-space:nowrap}
.pl-rule{height:1px;background:var(--ink-10)}
.pl-af-grid{display:grid;grid-template-columns:auto 1fr auto;column-gap:10px;row-gap:8px;align-items:center;font-family:var(--font-mono);font-size:9.5px;line-height:1.2}
.pl-cap,.pl-step{font-size:8.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim)}
.pl-step{white-space:nowrap}
.pl-track{position:relative;height:5px;min-width:24px;align-self:center}
.pl-track-line{position:absolute;top:2px;left:0;right:0;height:1px;background:repeating-linear-gradient(90deg,rgba(241,243,236,.22) 0 3px,transparent 3px 6px)}
.pl-track-dot{position:absolute;top:0;left:0;width:5px;height:5px;border-radius:50%;background:color-mix(in oklab, var(--acc) 80%, transparent);box-shadow:0 0 8px color-mix(in oklab, var(--acc) 50%, transparent);opacity:0}
.pl-af-val{color:var(--ink);white-space:nowrap}
.pl-score-row{white-space:nowrap;font-variant-numeric:tabular-nums}
.pl-score{color:var(--ink);font-size:11px}

/* outcome node */
.pl-out-text{font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--dim);white-space:nowrap}

/* fan-out dividers */
/* One spine down the middle with the four sinks hanging off it left and right. A request
   runs straight down the spine and turns off into its node — no hopping between nodes. */
.pl-bus{position:relative;width:100%;display:flex;flex-direction:column}
.pl-bus-row{position:relative;display:grid;grid-template-columns:1fr 1fr;gap:26px}
.pl-bus-row::before{content:"";position:absolute;left:calc(50% - .5px);top:0;bottom:0;width:1px;background:var(--ink-13)}
/* The spine stops at the last row's centre. Marked with an explicit class, not
   :last-child — app.js appends spark dots to .pl-bus, which would knock a positional
   selector out of match mid-animation and leave the spine running on into a dead end. */
.pl-bus-end::before{bottom:50%}
.pl-bus-row::after{content:"";position:absolute;left:calc(50% - 13px);right:calc(50% - 13px);top:calc(50% - .5px);height:1px;background:var(--ink-13)}
.pl-bus-gap{position:relative;height:14px}
.pl-bus-gap::before{content:"";position:absolute;left:calc(50% - .5px);top:0;bottom:0;width:1px;background:var(--ink-13)}
/* transient dot that runs the bus; created and removed by app.js */
.pl-spark{position:absolute;width:8px;height:8px;border-radius:50%;pointer-events:none}

/* exit boxes */
.pl-exit{box-sizing:border-box;display:flex;flex-direction:column;gap:3px;padding:8px 10px;border:1px solid var(--ink-14);border-radius:10px;background:var(--bg-40);font-family:var(--font-mono);line-height:1.2;transition:border-color .35s var(--ease-pipe),box-shadow .35s var(--ease-pipe),background .35s var(--ease-pipe)}
.pl-exit-name{color:var(--ink);font-size:9.5px;white-space:nowrap}
.pl-exit-sub{color:var(--dim);font-size:8.5px;white-space:nowrap}

/* panel footer telemetry */
.panel-foot{display:flex;flex-direction:column;gap:8px;padding:11px 16px 12px;border-top:1px solid var(--ink-08);background:var(--bg-30);font-family:var(--font-mono)}
.pl-traffic{display:flex;align-items:center;gap:10px}
.pl-bar-track{position:relative;flex:1;height:4px;border-radius:2px;background:var(--ink-08);overflow:hidden}
.pl-bar{position:absolute;left:0;top:0;bottom:0;width:40%;border-radius:2px;background:var(--acc);transition:width .45s var(--ease-pipe),background .45s var(--ease-pipe)}
.pl-stats{display:flex;align-items:center;justify-content:space-between;gap:10px;font-size:10.5px;letter-spacing:.05em;color:var(--muted);font-variant-numeric:tabular-nums}
.pl-err{color:var(--acc);transition:color .5s var(--ease-pipe)}

/* ---- 4.5 Hero stats ---------------------------------------------------- */
.stats{grid-column:1 / -1;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,150px),1fr));gap:clamp(18px,2.4vw,34px)}
.stat{display:flex;flex-direction:column;gap:9px;padding-top:18px;border-top:1px solid var(--ink-14)}
.stat-label{font-family:var(--font-mono);font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--acc)}
.stat-value{font-size:clamp(24px,2.6vw,34px);font-weight:700;letter-spacing:-.035em;line-height:1;color:var(--ink);white-space:nowrap}
.stat-note{font-size:12.5px;line-height:1.4;color:var(--muted);text-wrap:pretty}

/* ---- 4.6 Marquee ------------------------------------------------------- */
.marquee{position:relative;z-index:1;border-block:1px solid var(--ink-08);background:var(--ink-02);padding:18px 0;overflow:hidden;mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent)}
/* No gap between the two groups: each group already ends in padding-right:52px, so the
   seam matches the inner rhythm and translate(-50%) lands exactly one group over. */
.marquee-track{display:flex;width:max-content;animation:mq 38s linear infinite}
.marquee-group{display:flex;gap:52px;padding-right:52px}
.marquee-item{font-family:var(--font-mono);font-size:13px;letter-spacing:.1em;color:var(--muted);white-space:nowrap}
.marquee-dot{font-family:var(--font-mono);font-size:13px;color:var(--acc)}

/* ---- 4.7 Section shell ------------------------------------------------- */
.section-head-row{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:20px;margin-bottom:clamp(36px,4.5vw,56px)}
.section-head{margin-bottom:clamp(36px,4.5vw,56px)}
.eyebrow{font-weight:700;font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--acc);margin-bottom:14px}
.section-title{margin:0;font-size:clamp(32px,5.2vw,64px);line-height:1;letter-spacing:-.04em;font-weight:700}
.section-title-balance{max-width:20ch;text-wrap:balance}
.section-title-sm{margin:0;font-size:clamp(26px,3.6vw,40px);line-height:1.05;letter-spacing:-.035em;font-weight:700}
.section-intro{margin:0;max-width:38ch;font-size:15px;line-height:1.6;color:var(--muted)}

/* ---- 4.8 Project cards ------------------------------------------------- */
/* #work-grid */
.work-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,410px),1fr));gap:var(--gap-card)}
.card-project{position:relative;display:flex;flex-direction:column;gap:18px;padding:clamp(22px,2.6vw,32px);border:1px solid var(--ink-09);border-radius:30px;background:var(--ink-025);transition:transform .4s var(--ease-out),border-color .4s,box-shadow .4s}
.card-top{display:flex;align-items:center;justify-content:space-between;gap:12px}
.card-code{font-family:var(--font-mono);font-size:11px;letter-spacing:.14em;color:var(--muted)}
.pill-status{font-weight:600;font-size:11.5px;letter-spacing:.03em;text-transform:uppercase;color:var(--muted);border:1px solid var(--ink-10);border-radius:999px;padding:5px 11px}
.card-body{flex:1}
.card-title{margin:0 0 9px;font-size:clamp(21px,2.2vw,27px);letter-spacing:-.03em;font-weight:700}
.card-text{margin:0;font-size:14.5px;line-height:1.62;color:var(--muted);text-wrap:pretty}
.card-metric{display:flex;align-items:baseline;gap:10px;padding:14px 16px;border-radius:16px;background:var(--bg-45);border:1px solid var(--ink-07)}
.card-metric-value{font-family:var(--font-mono);font-size:19px;font-weight:700;color:var(--acc);white-space:nowrap}
.card-metric-note{font-size:12.5px;line-height:1.4;color:var(--muted)}
.tags{display:flex;flex-wrap:wrap;gap:7px}
.tag{font-size:12.5px;font-weight:500;color:var(--muted);padding:6px 11px;border-radius:999px;background:var(--ink-05)}
/* stack-card pills are 1px narrower: padding:6px 10px */
.tag-sm{padding:6px 10px}

/* ---- 4.9 Stack cards --------------------------------------------------- */
/* #stack-grid — 1fr / 2 / 4 columns, see §6 */
.stack-grid{display:grid;grid-template-columns:1fr;gap:var(--gap-card);align-items:stretch}
.card-stack{display:flex;flex-direction:column;padding:clamp(22px,2.4vw,30px);border:1px solid var(--ink-09);border-radius:28px;background:var(--ink-025);transition:border-color .4s,background .4s}
.stack-icon{width:42px;height:42px;border-radius:14px;background:color-mix(in oklab, var(--acc) 12%, transparent);display:grid;place-items:center;color:var(--acc);margin-bottom:18px}
.stack-icon svg{width:21px;height:21px;display:block}
/* the "Production & observability" card uses the neutral chip + neutral hover */
.stack-icon-plain{background:var(--ink-08);color:var(--ink)}
.stack-title{margin:0 0 12px;font-size:18px;font-weight:700;letter-spacing:-.02em}
.stack-text{margin:0 0 16px;font-size:14px;line-height:1.6;color:var(--muted);flex:1}

/* ---- 4.10 Timeline ----------------------------------------------------- */
.timeline{display:flex;flex-direction:column;border-top:1px solid var(--ink-09)}
.timeline-row{display:grid;grid-template-columns:minmax(90px,150px) 1fr;gap:clamp(16px,3vw,40px);padding:clamp(28px,3.2vw,38px) 0;border-bottom:1px solid var(--ink-09);align-items:center;transition:background .3s}
/* Indent the date off the container edge. Padding sits inside the grid cell, so the
   column track and the content column beside it do not move. */
.timeline-date{font-family:var(--font-mono);font-size:12.5px;letter-spacing:.06em;color:var(--muted);padding-left:clamp(10px,1.6vw,24px)}
/* the current role's date is accent */
.timeline-date-current{color:var(--acc)}
.timeline-body{display:flex;gap:16px;align-items:flex-start;min-width:0}
/* 44px company / school logo chip — 6 of these across timeline + education */
.logo-chip{flex:none;width:44px;height:44px;border-radius:12px;background:var(--chip-bg,var(--ink-045));display:grid;place-items:center;overflow:hidden;border:1px solid var(--ink-14);box-shadow:0 6px 16px -8px rgba(0,0,0,.7);transition:transform .3s,border-color .3s,color .3s;color:var(--ink);font-family:var(--font-mono);font-weight:700;letter-spacing:.02em}
/* Official org marks. The initials stay in the markup and take over automatically if an
   image fails to load — app.js drops the <img>, which un-hides the sibling text. */
.logo-chip-img{grid-area:1/1;width:100%;height:100%;object-fit:cover;display:block}
.logo-chip-img--contain{width:74%;height:74%;object-fit:contain}
.logo-chip-img ~ .logo-chip-text{display:none}
/* default 14.5px; override per chip with style="--chip-fs:12.5px" */
.logo-chip-text{font-size:var(--chip-fs,14.5px)}
.timeline-title{margin:0 0 8px;font-size:clamp(19px,2vw,24px);font-weight:700;letter-spacing:-.025em}
.timeline-text{margin:0;max-width:64ch;font-size:14.5px;line-height:1.62;color:var(--muted);text-wrap:pretty}

/* ---- 4.11 Education ---------------------------------------------------- */
.edu-head{margin-top:clamp(48px,6vw,72px);margin-bottom:clamp(24px,3vw,34px)}
/* #edu-grid — 1fr / 2 columns, see §6 */
.edu-grid{display:grid;grid-template-columns:1fr;gap:var(--gap-card)}
.card-edu{padding:clamp(20px,2.2vw,28px);border:1px solid var(--ink-09);border-radius:26px;background:var(--ink-025)}
.edu-years{font-weight:600;font-size:11.5px;letter-spacing:.03em;color:var(--muted);margin-bottom:14px}
.edu-row{display:flex;gap:14px;align-items:flex-start;margin-bottom:10px}
.edu-title{margin:0;font-size:clamp(17px,1.8vw,20px);font-weight:700;letter-spacing:-.02em;line-height:1.25}
.edu-text{margin:0;font-size:14px;line-height:1.55;color:var(--muted)}
.cv-link{display:inline-flex;align-items:center;gap:10px;margin-top:34px;font-size:15px;font-weight:600;color:var(--acc)}

/* ---- 4.12 Contact ------------------------------------------------------ */
.contact-card{max-width:var(--shell-w);margin:0 auto;position:relative;padding:clamp(32px,5vw,72px);border:1px solid var(--ink-10);border-radius:clamp(28px,3.4vw,44px);background:linear-gradient(150deg, color-mix(in oklab, var(--acc) 9%, transparent), rgba(241,243,236,.05) 55%, rgba(241,243,236,.02));overflow:hidden;box-shadow:0 60px 120px -60px color-mix(in oklab, var(--acc) 20%, transparent)}
.contact-orb{position:absolute;top:-120px;right:-80px;width:340px;height:340px;border-radius:50%;background:radial-gradient(circle, color-mix(in oklab, var(--acc) 22%, transparent), transparent 66%);filter:blur(30px);pointer-events:none}
.contact-inner{position:relative;display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:36px}
.contact-title{margin:0 0 18px;font-size:clamp(30px,5vw,60px);line-height:1;letter-spacing:-.04em;font-weight:700;max-width:22ch;text-wrap:balance}
.contact-text{margin:0;max-width:48ch;font-size:16px;line-height:1.6;color:var(--muted)}
.contact-links{display:flex;flex-direction:column;gap:11px;min-width:min(100%,290px)}
.contact-btn{display:flex;align-items:center;justify-content:space-between;gap:16px;background:var(--acc);color:var(--bg);font-weight:700;font-size:15px;padding:17px 24px;border-radius:18px;transition:transform .3s var(--ease-out),box-shadow .3s}
.contact-ghost{display:flex;align-items:center;justify-content:space-between;gap:16px;border:1px solid var(--ink-14);color:var(--ink);font-weight:600;font-size:15px;padding:17px 24px;border-radius:18px;background:var(--bg-40);transition:border-color .3s,transform .3s}

/* ---- 4.13 Footer ------------------------------------------------------- */
.site-footer{position:relative;z-index:1;padding:28px clamp(18px,5vw,40px) 44px;border-top:1px solid var(--ink-08)}
.footer-inner{max-width:var(--shell-w);margin:0 auto;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:16px;font-family:var(--font-mono);font-size:11.5px;letter-spacing:.08em;color:var(--muted)}
.footer-link{color:var(--muted);letter-spacing:.08em}


/* =========================================================================
   5. HOVER RULES
   These are the 50 style-hover attributes from the design, deduplicated.
   Class specificity (0,2,0) beats the global a:hover (0,1,1), which is why
   the redundant-looking colour declarations must stay.
   ========================================================================= */

/* nav links  ×4 — "color:#F1F3EC;background:rgba(241,243,236,.07)" */
.nav-link:hover{color:var(--ink);background:var(--ink-07)}

/* nav CV button ×1 */
.btn-cv:hover{transform:translateY(-2px);box-shadow:0 14px 30px -12px color-mix(in oklab, var(--acc) 70%, transparent);color:var(--bg)}

/* hero primary button ×1 */
.btn-primary:hover{transform:translateY(-3px);box-shadow:0 20px 40px -18px rgba(241,243,236,.45);color:var(--bg)}

/* hero secondary button ×1 */
.btn-secondary:hover{border-color:var(--acc);background:color-mix(in oklab, var(--acc) 7%, transparent);transform:translateY(-3px);color:var(--ink)}

/* inline underlined links ×20 (8 × .link-u + 12 × .link-u4) */
.link-u:hover,.link-u4:hover{color:var(--acc);text-decoration-color:var(--acc)}

/* project cards ×4 */
.card-project:hover{transform:translateY(-6px);border-color:var(--ink-24);box-shadow:0 40px 80px -40px rgba(0,0,0,.9)}

/* stack cards ×3 accent + ×1 neutral */
.card-stack:hover{border-color:color-mix(in oklab, var(--acc) 35%, transparent);background:color-mix(in oklab, var(--acc) 4%, transparent)}
.card-stack-plain:hover{border-color:var(--ink-24);background:var(--ink-025)}

/* timeline rows ×4 */
.timeline-row:hover{background:var(--ink-02)}

/* 44px logo chips ×6 */
.logo-chip:hover{transform:translateY(-2px);border-color:color-mix(in oklab,var(--acc) 45%,transparent);color:var(--acc)}

/* contact primary button ×1 */
.contact-btn:hover{transform:translateY(-3px);box-shadow:0 20px 40px -16px color-mix(in oklab, var(--acc) 70%, transparent);color:var(--bg)}

/* contact ghost buttons ×2 (Telegram, GitHub — the hidden LinkedIn never hovers) */
.contact-ghost:hover{border-color:var(--acc);transform:translateY(-3px);color:var(--ink)}

/* footer links ×2 */
.footer-link:hover{color:var(--acc)}


/* =========================================================================
   6. RESPONSIVE
   Ported verbatim from componentDidMount's applyLayout(). Doing it in CSS
   removes a FOUC and a JS dependency while producing identical layout.
   Every other grid keeps the design's own auto-fit template.
   ========================================================================= */
@media (min-width:700px){
  .edu-grid{grid-template-columns:repeat(2,1fr)}
  .stack-grid{grid-template-columns:repeat(2,1fr)}
}

@media (min-width:900px){
  .nav-links{display:flex}
  .hero-grid{grid-template-columns:1.15fr .85fr}
  /* Widen the date track so the longest period — RU "Сентябрь 2026 — настоящее время",
     measured at 267px incl. padding — stays on one line in both languages. This pushes
     the content column right by the same amount. Below 900px the date wraps as before. */
  .timeline-row{grid-template-columns:276px 1fr}
  .timeline-date{white-space:nowrap}
}

@media (min-width:1320px){
  .stack-grid{grid-template-columns:repeat(4,1fr)}
}

/* contact eyebrow — the only eyebrow with a 16px bottom margin (design line 544) */
.eyebrow-contact{margin-bottom:16px}
