From b5ffc67a828540386cfe2fe744976dc4c00b9002 Mon Sep 17 00:00:00 2001 From: Emil Date: Sun, 20 Sep 2026 21:37:35 +0300 Subject: [PATCH] Redesign the resume site as a 3D-editor viewport New design: studio backdrop with a perspective floor and X/Z axis lines, an orientation gizmo that orbits on scroll, Bricolage Grotesque and Instrument Sans (bundled, no build-time network). Projects are laid out as plates by a row planner that keeps every row full for any count; a demo image from the repo root is shown when present, otherwise a generated voxel sculpture. Text and projects still come live from Gitea. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01XtcZtnG4GQA1d6mW5PNrS9 --- README.md | 48 +++- app/fonts/BricolageGrotesque-Variable.woff2 | Bin 0 -> 76888 bytes app/fonts/InstrumentSans-Variable.woff2 | Bin 0 -> 30092 bytes app/globals.css | 176 +++------------ app/layout.tsx | 7 +- app/page.tsx | 2 +- app/site.tsx | 212 ----------------- components/Cover.tsx | 102 +++++++++ components/Gizmo.tsx | 59 +++++ components/Hero.tsx | 41 ++++ components/Projects.tsx | 108 +++++++++ components/Sections.tsx | 103 +++++++++ components/Site.tsx | 58 +++++ components/TopBar.tsx | 24 ++ components/gizmo.module.css | 38 ++++ components/hero.module.css | 191 ++++++++++++++++ components/projects.module.css | 237 ++++++++++++++++++++ components/sections.module.css | 226 +++++++++++++++++++ components/topbar.module.css | 69 ++++++ data/resume.json | 26 +-- lib/plan.ts | 39 ++++ lib/types.ts | 5 + lib/useScroll.ts | 43 ++++ 23 files changed, 1440 insertions(+), 374 deletions(-) create mode 100644 app/fonts/BricolageGrotesque-Variable.woff2 create mode 100644 app/fonts/InstrumentSans-Variable.woff2 delete mode 100644 app/site.tsx create mode 100644 components/Cover.tsx create mode 100644 components/Gizmo.tsx create mode 100644 components/Hero.tsx create mode 100644 components/Projects.tsx create mode 100644 components/Sections.tsx create mode 100644 components/Site.tsx create mode 100644 components/TopBar.tsx create mode 100644 components/gizmo.module.css create mode 100644 components/hero.module.css create mode 100644 components/projects.module.css create mode 100644 components/sections.module.css create mode 100644 components/topbar.module.css create mode 100644 lib/plan.ts create mode 100644 lib/useScroll.ts diff --git a/README.md b/README.md index a5b47ca..46e378c 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,44 @@ # Emil Shanayev — resume site -Live at **https://shanaty.ru/resume/**. A static Next.js site whose content is loaded live from Gitea: +Live at **https://shanaty.ru/resume/**. A static Next.js site whose content is read live from Gitea, so it is updated by editing repositories, not by redeploying. -- **Text** (name, bio, skills, experience, education, contacts, …) comes from [`data/resume.json`](data/resume.json) in this repo. -- **Projects** are the public repos on Gitea (`git.shanaty.ru/Emil_Shanaty`) that carry the topic **`resume`**. Tag a repo and it appears within about a minute; remove the topic and it disappears. -- Optional `projectNotes` in `data/resume.json` (keyed by repo name) enrich a project with a title, kind, longer description, highlights, tech tags, extra links and a `rank` (lower ranks first; the rest are newest first). Without a note a project shows its Gitea description, language and topics. +## What comes from where -## How it works +| On the page | Source | +|---|---| +| Name, role, bio, skills, experience, education, languages, contacts | [`data/resume.json`](data/resume.json) in this repo (`main` branch) | +| Projects | Public repos of `Emil_Shanaty` on Gitea that carry the topic **`resume`** | +| Project picture | Optional `demo.png`, `demo.jpg`, `demo.gif` or `demo.webp` in the root of that repo | +| Project title, kind, description, highlights, tech tags, links, order | Optional `resume-card.json` in the root of that repo | -A systemd timer on the server (`resume_sync.py`, in the `auto` repo) rebuilds `https://shanaty.ru/data/resume.json` every minute from the `main` branch of this repo plus the topic search. The page fetches that file on load and falls back to the copy bundled at build time if it is unreachable. A broken `data/resume.json` (invalid JSON, missing fields, non-http links) is rejected and the previous published data stays. +A timer on the server (`resume_sync.py` in the `auto` repo) rebuilds `https://shanaty.ru/data/resume.json` every minute from these sources, so a change shows up within about a minute. If a source is broken (invalid JSON, missing fields, unsafe links) the previous published data stays and the problem is logged (`journalctl -u gitea-resume`). -To update content: edit `data/resume.json`, commit, and **push to Gitea** (`git push gitea main`). No rebuild or deploy is needed. +## Adding a project + +1. On Gitea, add the topic `resume` to the repository (it must be public). +2. Optional: put a `demo.png` (or `.jpg`, `.gif`, `.webp`) in the repo root. Up to 6 MB, any proportions; animated GIFs and WebP keep animating. Without one the project gets a generated picture. +3. Optional: put a `resume-card.json` in the repo root to control how the project reads: + +```json +{ + "title": "Cortex Engine", + "kind": "AI-native 3D game engine", + "description": "One or two sentences on what it is and what makes it interesting.", + "highlights": ["Pure Vulkan 1.3 backend", "Playable FPS demo"], + "tech": ["C#", "Vulkan", "MCP"], + "links": [{ "label": "Docs", "href": "https://example.com/docs" }], + "rank": 1, + "hidden": false +} +``` + +Every field is optional. Without a card the page uses the Gitea description, the repo language and its topics (the topics `resume`, `portfolio` and `featured` are not shown as tags). `rank` puts a project first (lower first, unranked ones follow, newest first); `"hidden": true` removes it from the page. The same values can also live centrally in `projectNotes` (keyed by repo name) in `data/resume.json`; a `resume-card.json` wins over it. + +The layout adapts to any number of projects: rows of two or three plates with a wider feature plate first, no lone project left in the last row, and a single project gets the whole width. + +## Editing the text + +Edit `data/resume.json`, commit and **push to Gitea** (`git push gitea main`). No rebuild or deploy is needed. ## Development @@ -20,12 +48,16 @@ npm run dev # http://localhost:3000, data from the public https://shanaty npm run build # static export in out/ ``` -`BASE_PATH` sets the URL prefix (default `/Emil_Shanayev_Resume`, for GitHub Pages) and `NEXT_PUBLIC_DATA_URL` the data URL. +`BASE_PATH` sets the URL prefix (default `/Emil_Shanayev_Resume`, for GitHub Pages) and `NEXT_PUBLIC_DATA_URL` the data URL. Fonts (Bricolage Grotesque, Instrument Sans; SIL Open Font License) are bundled in `app/fonts`, so building needs no network. ## Deploy `./deploy-shanaty.sh` builds and publishes the site to shanaty.ru (needs the ssh key `~/.ssh/MyGitea`). Only needed after changing code or styles. +## Design + +The page is laid out like a 3D-editor viewport, a nod to the game-engine work it presents: a studio backdrop with a perspective floor whose red X and blue Z axes match the axis colours of Blender and Unity, and an orientation gizmo in the corner that orbits as the page scrolls (press it to go back to the top). Projects without a demo image get a deterministic isometric voxel sculpture generated from the repo name. + ## Not published on purpose The official resume on hh.ru holds more personal details (phone, date of birth, salary expectations). This site only carries the professional content. diff --git a/app/fonts/BricolageGrotesque-Variable.woff2 b/app/fonts/BricolageGrotesque-Variable.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..fcc4eb1eb7ccc8fcacbd60586a61be5e6d4fee13 GIT binary patch literal 76888 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 literal 0 HcmV?d00001 diff --git a/app/fonts/InstrumentSans-Variable.woff2 b/app/fonts/InstrumentSans-Variable.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..8611e41b14c75cfc8360e50d0d22a22d20a1de50 GIT binary patch literal 30092 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

;7&cRT>@vBgT`qml^v#W*W zk*y;-tGgD88nGITaTr3OgeaCB+3tmTN$nKaK;z<%^TG+2A`MTEraop@Z))#+eDDi< zx<5ZP<8_ropdbQHYj7tA)mil-BVfgyYu1<|(+teh@mS454NWkP5? zoz*44G;9zdj|OTDQPe|-5}2X+*kqUnan{3GFt<)fHtuxTYoban2g)n$9X$_XtqsC@ zY-h{rk6O>KAgRP>Ght^cMrMVuE2svb@5xI2*h?1_XW~M@0uZ#|ttmIw@pj%qSN+)E zwIEkF!Zs1O7ph8}%x0GceQTOXwd!Q^86Ddpf=y*s#5Bj9EsjVqZ|iS%6|!zidxr6n z3Vb&1`dD|Jw7uAv>m<5A=(C-oG)e2wgdiqDu_I@Fd8RZp-tRttlQkrAhZ=8?XyPUr z#Y%Np0He31n=5-0QAv}yDkL5uE(6L3hsv20?gdB%OJ9NlbF^=V^@;xjhoYn*s;grK z#2EXS)v4K^0r=};N~sRKA2O3#OHvWoR2s{P$m6VoD&W}6%$3w)6DAHilwD1tu>!Lr z)6sSzn4PROQ6nIaNp*O*sZ3`8ai(EqkhIftZBD? zeVU@LTOGU4uSn>lx&U)3)Vnm%vOpb-S0<&YH&l**gDM~SLwADZQ$qsDi zm=PZZv*_6k`_E{Sx}PFadU4yVtwNinCo!D|+%6#ziw`YUS;EZ5D19WuV6}8KF?+3gD3Uh2Lq!luXS7xND1%IRNZGX(B^$wngzZ0y$!qxHF}QAA8nu^; zg5yMI+Gp7AYn^H~peSIOWv#;<6jBa?tQc9Emh>igyof}c7KUcuq+RJrX0KLV=Ns_a zI)IG4eYo~^4jaLxgTJe@ImrSHlJB5_z|i6EPBSn;#!-kmeMktq8xlei+!^;+^FBj_ zSH2gJ`&l45|A;^N_TvFz?SoI_sLTs6>Op^UQKQog4#%NBE~5r0?TwQw`34Kut5*&|T(0VU*!%Dqfp*VPHBx zvm8v#Nxl_QYr_rz|0VJc&tDViprZ>sYk^RFvxhgKy^C4T8WB6%9YJQ{Q_L>IhdDqy zm`8+YR~O-p>q@UvwK87FmFxl=mekxouSJk;i|d*Z5RgD7uJ@=4Ac$#!Tsu+wHPkX{ zNYV(|_;ZP^yd{~@c0j?ZV5^py@c0dNBm1^=0s%MG)Q5iBG+yU>DIW2`H6`@V;cnUx z&|*@Y!#oP;L(TYH=enHpt88viq2}FFvTSyoz2xwB+9 z$8||e@*li|q2ZxP- zwy5F<#($9QpwPTG%y-T(Ii|JCM|%8y{5L)t?`UHG9)A%Se_Ry)MiFH^b4i-ZGa?Wgmi# z&PIq$#X^!U6>wS`I@2?Y4UPBL z3)n7goF!M|2YLxa#=IyEuYI&4G+xy@R(r1&q|QZ;tPPwxslhM;qd2 zxeU~XL!hVm$Ne9E-E1^pVOD&)*UGG1i6`2a(1)LSo%kxhQH88W+}fY^p&wkQ*9EbT z4~%#xKHhBVkI$dMz!tKe;sBNWX$kVStoZ$S6zq905hk9@50{&Y^EiiGq93$ZQ`<^A z;Zm`Pcvr7qX94BrnD7m7r_sT(mY~!#`n(Iq>iAYZwm*$d*vkY`Q@E72$ot_!ice}-I@J-*8W6&? z;=t9Q4)!!+>>72bcRN6*vz9dO9)2@#<_jzyMi9E<&a1qSOU-b8C11724pmbS>{FaI z;Pw}>I*;GJmZO%k`)Hl_J=N(b#w<-iMvLW1v&4g*1{X9laycEi3bBPCm^retp!AqC zZ6nb!Id$Jp<+2(^00yje4&Aoa#&7iFfoRgQLv=tQbXhV?REb6O%*jQ}+gMpvE)5Uj zCYTg@Gf(d$Wv55as`?LK(?X%MHK$lw%{E(^cx`_(;zfZ0XrC?uusUc6%E6;RJcvmW zk|_tu2fBf1L?%E3bO2@t_fiS&aNM!c=2TRDouSHQ3u)Hih0J2O6_+*5y;SQlBEnWv z$Tko5AIv7#<1(x3zB)rAZ zowL~oTaY3FZxIs0E(i%gm*xP6u(cAl0oY)syy=jVQl&6=4}y^e`BZAsl;g(GSb;Om z`K_i@_6_HCQVHma%S-(qlQ%8Ufco_%cfD_$I_vTqc(M&S#PNE&(6f;Uieg+SM*`A|HO@{IG{AI=KcT$bd(QY)(2Uff%Co&N&wHBh;c(M`7Y8Ck% zS)@A-xnWu8h%6zj&=Ji!hnqM44d6~N0t%%Kq=QF|m+`9jU@%OOFu|H*{U1SYQnBu` zJN5HfXVX1=bWcDa7~%$W**3jdq?8y`R}F=wlUWDm1Gy0JNYaOB<3k*m3<{@Pr|Mux z!kmu)4=p@Oq@}yp*SrXcBO748=Q+%#kjgpPsA@pfxbA8$vmRv1_`vDOz_4ebG%((tS%69|sA#snjt7iDV z7btFVhuX!;n#X~*HDm2*$oJ{Ju%RwaKwmH?n;Z}Uo&p&p#G_>_SI)=B7VMhs%w4wh z$EJ}FXJ}g&8gW+1cZhH{ z@`=c@xtZn2@gW?n6>Nn4vkL8H3szLFG)aO!`sPU;Hgy0UU9x(pk_vM$ys=2U{q|QH z``pn}v-$lH<49r3LxdHl(FO*f*=!`%Cd0B2qBQf+RpXn}kXmiZQxx#di(y*K-*YS5 zQ(_~;8kT1nbfuQU_;iqwq-eGjt)WxEPujzsBkN+5Cn&uA;*eK^YAgX~yM(PDJ~^3vO4z2q{ghbuuisc5Ew}_% zAQTW%NR4nfqCDM;mf~lnr?Um<+ba<1LCc$J9xWj7F);H65ndZQnG^=cxCzvOCzUJB z6y6JzmcB6^8*P9k8*4np+p{yZx`Qhhp(KvV3Ukh2`$4e&h_#`4Gjyucp7uIRj!r4> zWSw(%RV+p_!eu1+K%H6PKz@UhFj6iOLqILdnTtF}w49=&VRMPKs<>vuv(f;OjRX(E zUzoNR)2b!xpViH)~#Adw6xya2EbsCr9#PE=%hMzr05Bwy4k!fD*J#&*gH(pccf8 zcbm-_pUSMrOtPRD<(&5`wR;gZ3fnLQ2WG{uLuZrf#&471CAG$B&-(69uwwky=J8E* zF4(hT1-zFNQx}3Ckqbg%X;mM_n^2iMoHII!s8NT8EK1OF2K#`r3|ft(7D=8^Dw5ji z{Ep+3>A+x784Kl(eu9Eg9+Z0E90loB^E;Q66 zy`&n`d9K7XQZ%eM4f{3?LcQ?D34j9Uz+|vE-r+)0Ma@7S&uU#xDCxH*oi9)**XbZR zE8CgKEXjzUl8RzFg-0abw?)K(Osd^!MkOhz#j)mxxJRllE#N{4KsE7<5eAnV zqbRprv~Zge2tI`q8{&!hLtF@T1lKhiI$)hv=B_Edhh7OaGKI-zO;T>zqu_#jnDL*~ zruvlcRM&E~(`+2LBjc=~(FKXiL0i&QvCJsk{g|AEr5vnfV~0m%Cvk#ElPE--j_W&7 z4d@cujrCseG;Qg~seny-;EoQBp6VIXx&$h20F0*acw5U9$sRTnKoGlQpm!<<9x_Pc zNBJ%Jj2E&^>BppXU7wee)rpS302ZVjr#J~D_%^~>I2Fs8+5du`&5<1 zKS&@d*o8u7G(#71*@C=6w5s;u4wgg%Z!74C@%?&&Pl>7hXvmPrS{nOH^|yt1(~zpj#eI zvwNu{fD~Lx^azY{JOCxPQI{e}h{5Jz#1fi?nY6VFEaf|{5k}|TTc(!X=Bh4{tl{kY zp~h0i=};H3Mc}os9RdzTHHt1iIj`bB4$4;m1$+Kb^6L)hQmjjMSulG_kos%R$%Y=O zMyJ^WWNW8AZ22eCs3R>S$rN3RU0Ix}fMCyeej6m6krtHI^!^UBm@LIkljRa2p;6$@ z;VPLxWV#CL>}nL~MdidIfk17i*o*S-APCadlVfrJv9iM!L8sMAZ2LS0XOmL&E^Ce$ z_zgLpC|aS+)X2D5vPjF-Li-`F*DP_N2fA7~GYv2$X&))d;p-BeyU`iaAsmj0n@wJ8 z#g|V6qyu~;{Hw+GEW6{g*HK`J@Q~JYUPunio?V>D>#y6Z&+3&<_$*k@G_z-&RS&)X zwR(ukQJCvErlT_qr=+tm9--lsQd*lmp7`VHsh<-Ymvc;b6q!zc`MWe77KL$FR8oG7 zE6?qf1P%h1-wH4Vup$uJl*)YYVL0pd!AJQ>bF~ zfwhz$=;kbzTNmO<|2ZM2vpzh&%2*R#0X$EZKGt0h>qoDpi~^?xwIUwKpK0a1`)s76 zu~{>pt9&Qs+*U%wK(OuDN@wGaT5ge47eFO4rbg`LD(XjzO^r_@UXklSCVSqXcIg_Q zK|9mB>8}SLKemZ!@AFb>yO2!rLSt(xDD%YPmSiyBd7vj^-rL|iM4%zs3#@IAS&Vmj z>bTe4>nzm4%j`u&iEB-*e$hlA%3vAK@)}UB%B`}t_8+yj`IGAm=(g_t+*89&0!B(Q zA(>AqH}oc08tPZzMm%0$zy%J}IkM%S!uxOtCr4@g1C^xiSZ%GRL;2%#@M97*xMg{o zh$bFrcv#>NO)wbKdJQ})Pe#**q#7o!A9%k~kpeh{=GHXz@Csw^-}Xiyk{nLOHePC< z`3Sppxxg4Z?v0UVkUhJ5joh`j+Em-fg?nOlK&_F)Q06@xZ@w!PPzn3744BQr zdC~Qjk48q-l+)j;eb^DJC;fC(j?z7eZRjoilrWXa=^fnxD2G%;n zLa!25=iSDlCMIcN5bB(nj81}!xW68%F~^oEB~>{| z^_G_hQeA-BG3ip6-MT|XEd%VV(==(S|sVU1UVlNGFh(T)NHz}P|c3tXZDnRr&vzY#_<2Ixa>qbuS4SWO*O0zz&8#BwC&2{x5eC40 zv338Ty?p|}tCuHWletEE7y8&tEktfRQIK`_69c42p`5kzxPq$PNNS6}Vt693UN>9% zvTK>)m3aK*;yXEdx_!X=ENa|zXx=+f9#mmtJ4_P8?1aB4F`7g}+3PbVq+G~wiC=aT z(e=G~t9{d~t5cjlg7~H0PGMFypiJ3-j}AzS0zAplrJz=7 zhq(|P;sqqsEs%zo$HYryQY;91Z zq}i4Z)4o<}NcwCskY>0O!L09qKB%a`1(g4yFEqH&DwyBFu-;_yF5M{^xY{`B8ffgy z;RBhXFw7&;b9}hr%hZj&l;1UuCfY~4t1?+4-iGze{j&3sE`fzwyOMGR6nZKJs7jyO z5t?9gXk;^h%K9%B%yM@gFL2^`vZz0?h9G`G)3obMdo0WH8Y1f#@JkhbvdKwebYM;S zV;6rradl1^khs!j{5q>OzG(9Wd1L-uxkxC9_%Bw*j{V%Tx|Lfm6ukQk+8IgHU!D1W zNOiuF*nhXS{k+m%%fZ=@GOe&2FR{cDi*;5Z1zm_>h0g?6 znSf!D!_!_r6>%}Lp%x}0(CplAR1KuKSg|KFtn$_ySb~6im~IGBN9weM^<96~vAQ>) zK|t8l&x1PX8A_V0M`pS0RQ@Fn`14Y=y9-gN?nQhiSkO9{+L3BW9xuMl>0xb`$2~KJcLvKC0be(tVu(_7ebf1h*o=r;&lh$io~g z!wslK3fCbEo?^m%-^U_?LX0L^&{={YEDPwSa25#2&V(y(9B3`$NzRQ#e8##Yd;rWW zLnk(NZ9aEE5H8v>%h50v4|1(-kg(GL?S?(-e>C@dyDMZG}44p zP8Ktk=oR=l%OIPg`SUfpIhcVaVwSYC2LV4!)H;qQ72&BwX`)?8;wgY#4ZQSXX|dr< zl@XI18G-FAnz7Hv@-)EX64^~byp7;aluB_|pvLndBOm>Po~9kX%P7oE3WSRX{c+!V&-h5*V;0LA*78;C4KT z=qd!#nwEZSoo}6N?P*PKjcCni>2FbJNw-w{{%)RYHflQ6glmdws`j~5LP|BIykbr< ztMF#QzrYb4%&*Bk&Y5$Wx#*mGF7~+julbc@wz##g?{WkB3lkTZ~X=68P{u+4(=hA#IWm7QG@W&N8ad-Q0Cp2aM_}+Nx7hHdpSnc&u zRhP8H`9Y56K)#WiGdP9D{pgN=MYP+Ur~czDT6u$?v5bM_$+u=Rt$FB-_UJ>pMl&=D zzd(ZnZ(Sxq+QSqp349;$jQJ z0Dtz3c5bE)nqRF>%S(ot{0e#yzjA$k3aZZX|KeF_w+Z0M*T5!Wu#8Z!BeFQ&pEs58 z*^nUhy=Gx(QXJwB4=8vI0wh@9TN2MgQ7{>iOdhxn7B`-!d&f^!0#NuG#F5~8rFen38YFI>QBlZ4qOf~4#0b7dv7#R=j{YoC zF-;mzp#OX&Lf)V%)LW*9zj2MQGtB^|9wYw1nh=-DMAbu_g?cQGUz_u`r?(-ow`Z8- z?c{qg*R1U74pA^2vPR-FU?9C{Mx866iE!^SaXkYTs$Pn)E8UNXUatEUTchdyjX{4O zWaM*QnxMy7v)09!u=g#C&`3q=aCjT_N}e_rzMGF?VjUM*823+HB&;41mw=sYQJC{q ztmf^I$hY@oa(#`mxc9Og?(;$k?a&Dk8Gudd>!lr>2#d2$Ly?G|YqI*6I*<54xQuuP=}2_->a8Q z@a}1RzQKJNiIsDA6b76`s~OKN>!AMpLgw967^_&eQ~3Dnw9@66dq$ttlLLm|J&9+q z%Z)T~RD0=gl%$Nb4VwhJ{KHzk%HMl0uUXy}PKzE#eg0u$y~S!&GypUzW}Z+xFuU09 zlaAIkKt&4$8!OX%q0633d%DU;s$}^DSOE6> z7wrN-fl^;)SyU%)-sO)nRNpj6>8&tT7RZMOl!$`O4#Tux%(%|cW55uK7eH`?HF_KX zvw-~HlgW)rI`L0Vjngfqi+2?}?QFkgw=K;kU2l^p7U$e(P-s8H(jdA;G>T1(kxTCC zV6>e2s3zzv^T1&mWM21KMRqD1coW$nyTg>gA_z(tknPPkh+dNMta906%|gEZDzPzm zE};`zwW@iBm>R~JtBZZd>J}Ij|8{G6I_+#wye>9IT~yn#tcbN?#FCjcYHyH?(T!<0 z0fXWe^{RE7sB!t+{0^9po_FOg4 zIC?ZX>>nA}`fEmiE??EeR#P=ILYs-1eYJ4(*IIjn_xMc^#XwQ>?mMezz!9we$g2(c zhfXtWg@XWsQ(}jIgzdWv_)3l6{BXDoHqOfjOhiFX=`^%m{q|I|N3m9&3$e$kISX)H#_!lSwv^j(s8~Rf)KHjZu4e zYr1$iCP83xTLY`Zfb|Yl(|UX6zMfly9y~7LbeIWt(r_Y)8^tWc%`&e}3NfA^epDWt zq-L^DJ!)0KQ8BHwHx9`w_b;xYfhgT-qk~no|K&pA*q2yO`U= z(3!YYRxGI8BfJEg`WBNoP&a%DDc$4mFu+57aJf`WN3fk@fUd?G6le7+zzzc<5Rd&>&8FLuerX7*51cNed(YS2x*^Jw8JJ2k) z!V-ju_rz%l_6sGEa!P$^CbG2jk zOlq-?XjH*LRbDoZnJ62ocWGVaCz(}?BRHXH$Tgj2Fcb!wbDQ}i6S$ySa+`cztJPm( zfCkzIMaADZil2Em-{~5q(gY_pnuICUqycUP8h!_tWa_oXfA!gtSQhDWh|1_#PzkKO zrEerFDeOy-IKd=C#h0$U$#De@Fw{(ge7uTD7bh952O~HGAVyfB5@u34f6PlFMXM^z zL1-q<66Ow5F{6l>gl7}#XBJuE!>0IIx9Es}>Y^6KgWlq93{fh_x&CHK{oi$9D)9QtNTI5`sE5 zjwLZ5CO(rV>bY)iMn?I0y@*qc`q_-)fi77qTAXK3!-DjFxzRx5a&o7{*>>d5q;Lv# zu&z-a$|(g{Loqa|g`Tj?9xgnIhzjJ_=T&0hU7@zfM(cyigdD@rTmk-5JA%uqok6g! zCI}YQ2KI(}VkO(}AP*9GXr^k1ayirq%5Ry~xJ}66mC{m#WGz=UGR<}T%^wC*GM>yl zrdLqsF_nRhaT3jR`A^p~@s&w~aus%mwG6WpD$yjox|QAcB={|C30h`DSq71SC#@bRk*Tus_Mzg6nlP4C@WqxxbHG2 zQXwZ^{31=FDYG`_8f9Tebo_H2n%PRHbS5$bh^iMvLHaa^%tB9m&eP^uL(&w4k{$S$ zlm=cFq3(Kwkiz|RV(7z40)RSF`s>8WE1;Z~Znb1qPjG^3-dMa16Cu3FbF%A|f;^2D z0$Ybnnwz58pOANiy0|f|8bW^Uh;X5Yfk3HlHWyZ$Val%y3;6^_O;YdnnxEe+UAG|p>86XWT`U>RxUU&7lEeAXgnM4%w5c~5LaHHZ<;tJU!vTk5ASWhm2gbBIE-iwr!WfV@jB7l~#$R+dE;tLPb3 z4s}1f%+uFu40EDd(^S1q=y9lY2ZVm>0}w<&eRCS554@-90{5Ewz&K)BzE7tz{bW|6 z6X=EJwxejCxz`TAiVS!|g-jA+n22a^;762Lv6@A)(Ito$8N`L?5le{#QAoa!@VKG% zMfzhDi}NvZkCC2}vVzo55kXe6nznuiIReDh`OH$tW>_|sL=@&TSw%-6DMpbvo*FtG zUdy?}9Mtsw^xLzUQ@=-@ZhBxgq!+rB!*>d#7i0+B)Jq?X=hA#%`l;5iVl@6GD{iEN zI%ecWIdPJ#A|tG^2q`-BVvkPep_o}DuEKImsPC++TAcI3e#elKx56rWeTK249vH6~ z{9_>{d|;Wr)>5$S|>UF3u|Jb#FmA z+q0tI>!=Oi*_K;agjqxbfI;Oz=0ZRM5ojum#q+U1jz%jG7V;S|!NU3+*vx2@4f9&? zzECUPSs1bAFr%Vz)NQfKoq$A?dMsFz!(r?)#T}yoX=x4RyR$rH+Z)jmEXT@vb~0N` zwR}8J+&XS&YmFd+2qLHl?E-H%xBuxlP|7n>5!i%@`p@)b1lNPNWEUo$km)HzI7>^g z94oi31_lL&sU;-C+vASc^DU= zFaUVUN|IU#FO~BKbnfdNm?0h#03i*<<#I9ua|IJAgKvuhG%24RCc?Tcj(`O+wt&R)W2s-@g!(|zvvK5J%k zhTiP{f$r|n>QoLt19OwU3++w$4wQh>*8mg|tily2!)=f_(5n;zdULKy-IXdD6*@DR z%Slu%5@JHgWo{9wmA0nPUMsi~!i&(>h$l@+;ziL+piv>KuH<}P-R=kt-D5C#4o~QH zDHkHdV+JZ= zwPkPb$w=$0Tw+3$*v(_`%dWFJAld?!8jSR~6+W#ciQAeuKl4`ngJ{df$QO2zPz&<<0qBdN-=b@Teky6f_)grAaZwdT4RI!a}XlyVa9W|{xoSnt?WA5QVl=!!!g!6FBv)Vl8c`ta; zOWGYb?PCvo;!~gb+!rXc2CaY(IPlzepS!Di8Z52adfjX-V*jL zaTO_r2>cC2bi|fzv26igktAXY^O~mXnl?Y%Hg#`yTj`U3tG3XJrpJTf43OT zxAL>EBs81Kbi1^-W>mBnF@btoMF7_7uTIY4Wog5EHo!IjRmA@~tOA}U-Q>}URtEaR zY&^j6Y2<&|v=r@4bI>saRy~oZ(G`6K;RAd3EA&JF@}D606R(&DVH$E0{EdsU3SeviY%93cj`fX+7X&TbELncJGSFFku!7t>ju03a*ul+n+<@}G6_yO z;|&%USzR^4GdhnzcgfFD9dlvRK8;~aE}r1Oav^PP_-BrsCiA(Pvw5xC3Bb(lOx?`U zH)}gTymo()^Z5`W4S?3$fO+2oe)Nmq03dz62Ou}H!<9MV6+=#&aNn3=XIb?4fLWhT zybqcG`iqov$)A>jJcB%U`P5{(v-n!`m}DvCn>-xecQ9F+v;oN?Zi0pCcp5{CGJ zz|6MlC7M&48Duzuem?E^*X_sB_Hmi#Wzzu~EVc_J&_KT3lZIB5f1X!60>91s( zdAc!^>hDcjXJUj%j;K%aI(hV6vln0}%S&m%u!DvKc@ z3XB8RHcn=vb%SWS3UoeVw((XhY%roW7jiQADXb~TjIZ~aXZR}Y>{trYg1{6XeV77F zm8l;LMV}L6ED>^?S)D`eyuK zQ#|PWqw07Wd& z%eqr#1w`JZO<4C5N*f|u)gBRJH9^bd9=)z=`8WnEkn%D%DDXn~%4;e=zyMv=gOb`y(i1UQB@={OC0D(_@^Gj!%w}@ixm*kfcl< zi-Pvx?Xbtab>~!mZ7wS+nUuJ%G8ut+MH!x-m@{qvA@esZuNkXjCo14UVRX%~p2;uF z70&wigZIW1?M{M@#}EfS8Ke$NV^Rg9)BD1o*PrF?I@a?=gg;{V^_h#eUFaf@+VGqe zR1fa3ifVDnR}@fCr$ienC@~se=vh)S%IaiH(f$qUU9+`Ce?N^v@vSOBr;(o#KJ(}H z=WL`h_w*h)&KUkh<<}vJ*%7;N?ia#q*jwL^?XIe#BDDwj^G_ZN%Lzt1NsRXNlBCMb zM3#Sp10HM$SW$PQBK7E-g|m<3m@nE7(!A#A9Lr;^CH?(O7Gpn?c^WPH6Hb5I@Ayms z<(q4-(*suPvs09ObK8W+Zlm|{TW1lY4`=3k0St>WJ;1TxK4*zMOWNi#Je__E#WUW9 z(EggXOn2c)=`YwE8L@w%?MSQ$lJb+<(!foS5J;5ln;|oU^4Y2%Q}bX97oM1gsW#J@ zoZ0df8;H3<^n&jA?J2l$OwP{a2bf|;Ybu*aS_fNH2;X&>@9ldmCrz$vT#S z#V6Nfes!{AtC71=h;{wK^qp!?T(PVUmvdiP7az3V{mF=%MY(o2nV76`rpLr}HgChS z6n&IiURiqKMQ$ z^X6FmL^4l&HvTx`R(G>q<`s|6q8fs%VdT^&mo#1>jPA%*F{XdMHO6R-ZnhbH_t#f%d2=1t0sZseKYyFh zShWXY0F0_H`sl(cT*-nI@MIRSutBwBYqfe|s0t zv?x9PT3?=hSJi2Mw0hr`j}Z-{@80Wd4Bz8x9%1rj`R)yVR?pQTVn+GqK&P&G+8+5H zUz4L4AxrU-8*WWmr6$Nknb2C+-#k@2qaRH@V?axaH9VeOj0*iwV~S6wv?_IGo2>tB zw`P4wr_Z@lsL4leCEtCS^-)*t%7b@4sOdn8sjb&(CwAfV38vfj4?5!Fik87xOuXUm zN4xNGGZ7PN?#JSg@SdrhKInpXZk(A4Q}5>lbhS3CO2r1>5W@g>2P{) zkv!~6KK?o`dH?o&JoYbb@J)@y!bk+%hMU{!`lFrB*-hY2bjyX)EGb!(7906$s_w6( zq6(ELe@lxpdjp7 zu|DN)k0)5szSNn+vkmc1L2hqDcsw6t#~iku;V?MPWfGHx`jB_8O|`Bu*h4)NZKUuW zp&-6>8yKV=qJMFJ<%}dIn(gtY~PQE8;*Qf6nG`^NU!Un1F#ozZt96;ReL-G zp_6weGP!`GRrVBrrjKPd_c&;FoI&=4g7A)U+T|LfZ8M=TynBoR6{tCLuGw+!bMQ_= zqo>tVjGR@3`dY%VkIQ%M7h)ZWElCIer zc0j35*zNk{fSUau^#zwlVVDQ^ys{U(bmW>w);PG_zp2@;kt&M7<0^Lb5d}ZbozTd! zRN(IN{r-wL?cPF+SyFCvkGbG|J#BBnPwe$?$qw(&0=jO?%^Meva`oPVFYa;~4a&$&RTx_viV{YHza%Hh+lQe7 zx6r}i4COXxr4uK%Nqp_TJ|?=M547$5j)JN0_JT5K=EcL;-S2(4oEb}`GNXeJdmp&= zhQlCX)#Wg`FA&`4yK+HoaoIn7`;v3!?D_LeebMax!{zMNoeR$!f&2rGv!(YR)>YSA zuXzV~a{0_-A5c#=?gLARrTelUN5VdiXlX(Kv-Q;IU(Qn>Xx}84DeO~-I~IIxBuqw3 zW@N9RM||;AEE4^uF-iXfx#J9q#^})EM*{38TdH>m_@oB)o0SWRFXK8ey8Cq_Pp?C! z$R!T?Vu>jKjgPN)MVvM`;EXJ}@BBCQaLZm3ual<~!)?gAPuFnch?U4<+9{VyKbc2R zEN#(LnEH8s`_S;saiWiq;BrCG6!Vp7>5sKcGv3buXC0Ns*B;yIoa0s>7iH}PmPK?E zZq6`OKs-1TD8{0JJi~;Fu}G)@S|Fl~S*t8-ohYNYAu2X<6OQXii$O`s`5}{uAEA^= z9c{kevD3^&#NfHT?ZPZd;CV#v)*$Y<>I)Ay_nCs{#~!-w%w|%}iX}d?QNgf0DG`aqOd>bQm(2aQ z?UDb2br4;_Y*Q|mb#er8kVT7Lh1f}SybagqVB*C{EM9ggX;B}Ie+zCP2#)ow%#7O7 zI~L0x5ZTY1#k3e`{Zp*ozYu5cVq|ug+wUE`0m@+nnuB#?tjjP_gbAt_UjlF2>ilr9 zadWxN87f3Vp{$b$=AxSi+}zgrYM1d2gNhN0Sk1!f?fnSG^+p{T!2K%Iz;%4Z*j>5& zw>msrz=|S(dzXui)`KrD_}&{3E`EAB9W zSRIMSTgzonV=QKa4w3jZ-Czn8NYW!A+FHru4RCR5#3< zHSPV&U-qWTod$7Bl_?Ws0oDJ=(N_yNfyzmhK)fbFkd(`1p&$&Je#YgcxPW4L%rND0 z872z|ZqHhDk&E4c_7>Paw2cIsd2CV2f0<bZJ zvDw4zuzphgu)M3+KC1&F`@gv}3pUj+tX~GlP;<);7FoK8aYez;P_h!Nb+f&s+N?d@ z-P$Peti+e$4vjs{_}S-yISe*XwCh@?L{mnSsj{l0CQcF<^=ZtuRSwvhZPBP z4l7~qIK=NZF(iTny@4;eZwEG4i&$2w_Z!p-)+1JD@tjH*GMdfNQ59&b3os1*zB^!n z__S)}^EX)FRbn@Ase9Tg58>5!9)8mg%7>7 z?!lM5_Fr)Mz%QPu$5&qWICA~tD<>ak5B!2$ckikj?gjmKfBeeQ#DTy4sROJz@~`NJ zD~IoYFE+CdY0~?!E|>`q8#)W0{o)<3x(&6Tsz10OCl*Lq0Us`=m&!tm zZ*nxQoNeiNwsrF(Tfv)Maze->WkfJUkbw|^2cm>VBv!};BB5TcFaZV%Y)KM#4-Vq9 zTjK%o#);X%A>yv`zo&lE5}>5JlL^U=0A{rYaLG&}Dcutw!G8~Donxp3wB-Ti*a0SfRTs;sf+YRO=| zBjlzqmb4;H4vrEbBWBl|D4W$1AZn3N$`bE{cU0!hYNWhuxu2IEX1p{yE3Gt(z$4#m4o#)o!s7 z%^QsUPN%WIUk?n>*1cyQnuhP04*TO%rG@eEH59CmL~pwtDPC*AV>~UEHR_85ZYd1v zaT4>e-v)$oVf-Jk`xo8ixHWm9RSyoq%>=V_pFLSb&KZEbAfT%MRa1w>^o?Y(3x}eBv#jP;utR*6K z>CM$*dSoD}?#}rt`*-L3lKm9WLU>VQ&DD|-h+;jcl_aeQ!I`~;TW7QDO?I1J=OV5| zA}Mn`t46Fzsn%~$i&$DL#|&PTBxE$}V>uPrdTGUhHLH*O=T&OKgntyU0VR~19$gfR zHrQQgkBM`KLhhhdg7EKkt=&36Sr)BaA6)Ge_t??~UBA<*@6YRj0h-=%_Q7fE-D43? zc(k-I9^H(=DzEQ-A8Nn@JQbWW_9U1JMLkAZ*}HQ(LZ~em<2$kLUlR21cT^u__EU4_ z!3Rey^`{UCQTJX?tC?K5E4w+L5Q*SL5l`ct4C%n0vUN-7NX0A06fo`QWWz@>un{p*R zzF}*E@l++~O2M8v4qp_pFh@lDO;_D0wjo)9zVl^aM0_JySMW;?nCpbE9#;G>Sf2C1 zavvzZ)!-g%Smt?amc?Ih_|3Z7b+2OH&u{&)oqb#P?&VHx`&yCC1XGW5SK6`kh?d6l zGDE;5|K~@6ul}u!+&q8&II>M>=Ekm>@6lf+jJ6&BkLI1HyEP#Lf@R?cxIrpBA_sr4 zcATOE&IfNizH(FEZJw4)OU)6d40WJMPbx5QD07*3Gmn$Gdwxz~spi|3IpF+~-;0P) z1g1|8IwQbVsAWlO%aWF+wJoh{f%^ldn6YC&!TK>Y#cv$U#e4rb_DuR;*-h;ECn5W% z>HUR2rL|zo7c(8tAN1HojbwGr?S}d2+<>o)_ zx_iT#^xLf;DO?>YM$-C$)!L%R%kyKH5v&9i_i#e6NAsW_#NEozd~pj*fu{XI)4Re&@@( zYo{YBM>O{FQLP}|RxC$Eo3s~sTwHMXV%Hu+K5y9Las?c53UV<#wi}<;#Nz5{95-y( zf^h67#!WH3x(|j8+aKjdsxJr;$}Dc~!F_3$+t-WfaZ5%Ck?DZHzhInx@CeFUd%~m5 zssHvZB^#P$s^*rZ7XHh^ErMyeu)CWlFYf^73o(1_j9jnOcgc&H;b?aynk(9U4J9v8 zbk}p>nNb14>qhweZW!qn2*2rq`TQ>A+Zmpg&(rV(8XjK@0^4sVZU?{o_X@K6&F#o` zX;=4iY}M)A_T97F?c2?(a&|q04)-Kiw%g+gH;K2e(qo5963TZbI2$#>Xx^dU84eqE z<{Wk;Zk!FCCA|$ccVH3v&ZG7AEvmiBkp+56Ms)UdcNP9P6k*at@=B+ppfp9I+!4Rk z?sO5R_2C!eVN%(o)mw8&{h0}MxfzyYuSHQdG zCx|CLKaCy0fQcjQ$o=v7Z(4}Ue~T&h4PU?ZeN_Mcmj3P3 zowvBapW@L?v6;^^e1YkVO|5O|yWwSB-G=}A;~Y&b?diQ=fMXxR=I@;QWBZTyLOr!y~MfZ+)H^T3|?XXnBm`DZc3dj5HBtGu;E*KV@4wAvb(E4TxX z+ZSK@>`nCDM@{W-nc7ZWeAGW(*1vU`wq15|JO9k{T5UY;&z)WGb#pc=&-)&)29ECN4zBPhL0^iwBs9YYqnA1m`V#xtk8mWGEaw5vf8XN`+i0v8%)+&8s)yjV&s##+6=8 zs5~1}e)jSQ2Ti=<@V_n5rOe}Y@5m{S{Jl z&o}@7;6Se23diFPnS!#q4_rI={rC8EE_+N^}{9}7Gvzb!OOHT5V;&QtD3UiJ7b5;%Ji?dR zSAR?DXvVTuQf+@Y6pN_VNCkhgXY zfx3H;q39tih_)zf1uV11BCY-~K6H>zU8?nFID~$x9)@~pp#Bih-2<)|sOMy&cqUWj zgj3kynvQb^JNcCQp$vJ?_?<(cZX0S@1K{S%bp#YHm3bB&dWh|HZ zBF5do!qfD(tn5kde&r}CV{0aVCa;{@U>35s=Ecd(*_@Y=?~<}_CAB7p%EtY(BcBs3 ziRCz|L^ht?}GwBAi!cv#YnaaE1>LlqwbmuhxiK- zVTD9%Qy)`aNJm~xZ{EsKCUQS>`85kCT9+&nm86MU>g13NNL(Jm14@))7fkpD53qw1 zSdhRM_#Tl~#WBs&94*umE!SN-qO9>{U`bYOFWa7-nbDk9B1f%aI9D)%8C=6W7PE}| z*uq=%u);5#p&cE##6x|(Z}3wd^KZi|BBMB73T-6fqxd-f8;|0btePuRnF*PZ8?q_2 zna%%~q;hL_y-)`gtv}wBz5i9bgYU}gv|G!2O&{tP+R@GaW8R*sd1mUTb?(f`7{)ol z`DkXA?QPq*%~ zLASm|eJj3k#Z7?T{%5ra%o`8_-0aEL1gEtvEG@Z)E=2mNBk>Xujxs#pOS1H#cs&4$ zI>oyP8kLREX`vMLj}F|Rvp7t7UQ~jebq!a0j(J(&Kw8;B!r-+=kx9bM?ws5ngZo@^61S@6mg{>^~{r)bJZlpLr zm!=Jr1Nw4un&w^p0NMNJda-sQS>)N7@0MnuO6M1+AXF`Z%WG+BxH-JtDcg+NJp#HGYi<>p^Klv8Gk_%C8@}!>ZqOBdUglorrh2wgxfy$*qXy-VIO0MU4~EZ@67#v6YgS7LyVvw1Pe@Q%R<|@y@T2K&ef_aFYZIh z=`>u4$pmyFK?p#3SYqX^Jr9a+&^bqVEeJEr8)Y%y1?YH{r(#X90}?D*)OBVcTArWr zfTeCB@jYY=KsBM-YYXX;0EI`Z%J_T}%bK{_EH8nh@$A`m*#VMVeBA^Yz86ttsSH_) z@%Qq5U^YmCC--90Jgbi6CaZFm#Zsvc%ttcv6KFhGy`~9yZq*jnW^x#9`x}PwwDGVx z%iWKcV`Z5cwcWyg*6P`t_qGE`-9nB%*EB#iq15XOOE~fyZWrX{Wd&rxTFny`OAsr3 zCHA=4q?&DQoy{389E<3h?)VZXgw~@681l|#bYRq`Bef$ApqDlv;oQ-YY^IianjJ-f z&+S&Rbw2uQx+-!Tyw3F?b%j`NfvyVdIaNUC`8=#R!ph8!DhFNJuT&wtSTD#yM(GL~ zGIGuSP2dypm;RAWWx#z=)$xgHE{Y;c!0VKyOUUTi)mLi|Wc~1VLAmOq0SJ zLCX5A1qi@yPR+voma}+0xZG;nnRI%7_j5tu=%X763=cZ_0QEH28|AaXe0nM?^6pf` z+0lJJl$Pnpz0lltaO-bi}%gRe?OwN8}iC=FL#0&jiP9uEe4aJ3k;q9jcdh~d4q;OfSpvj)f{ zD9xjgXJyI4B7?9I$x2V$7~7MO5qm`rE+2Qz92Eh6ZUsT!{Z0!lB^zn$OvWceZ7Gi= zu!uM%lE4QkMrg1tX*tY_J$8mv{lH(9qW(-O6=EZ;5a z^dufpCjj3|jgsT6oFg#+VZw+gVX(;XO_MwpVYE*{7WSF6i^@nbXc}@lYM-migvJrHxnlIpeIS{EM;+uX`5D2(O!tz9jx85lof)Rm=S_pWLbe z(Y&-b6JIY3xg4m#ZC6}x;A{$D&wfLxuEXYSyJ zi$NhHr-en@Ox70TB!=QbXqmk=Q$;)tOhMt=0?^*tARrAtFCdn;PgMA|sD2mz9=z?v zN%gi*=(!~qI;NB-{SzepAT6;mf#qKLgTr&01gMbuiYk#qvA8XI zgOPF|)A)$}AZFDfE_7!_@yvU3Fv_brai{_q#64|3;;c9IRxR66S%zsmcD+9TE#u8T z%`{U?S~46=Qom_jfI=ZwtW)w)FRMoo?%<{F(onzZ2!tFU<}*w@YLYm1-d=?zveFv6 zq7${@+0Y;=6c{Ud;*oH+I2ug-C~g!eA$FSsz!-T&w?r0G9iD1Z>}a~SZ5qb1vG(S^ zKXla-6#~iZLVKcBmE2Go1#Y)!NBl4albV#Wa#zt4!QeJSG%u2|-Ce(uCk~+s8;mRp zal%W6NtRQ-nRlg9r4M?K(@z683_bNie&Iul3WUri=jOd;kC~zwR*nh+#fSiQ_Ib05k7&$#G(KfWfYxqvElx`Ow%A-Qq z#k}KlUThBRh@lRv zaUTb1>$dR%e47VRB)GJ79A@6qQn$Q>HQJW)MpzX6!OiF@%6Zgv!i)U^+!NTYo!Y*O zML{%uAxXMp>rAZ6F653w^Y^BUT2q-OYme4UTYs*ma^K)#MtH{InNYaK3L~E=&>K^C zucA)dS3MtjXu5ubQ0(`aGvHYcFKY+P&cX^9+o}t>riJ5`Ud^u|3cY-Ym)WdYm`auF zim=b?JUhXMK;;)68|_7zjIQ3nN6hm559wvg52%^LPvL!wJakZ}4j(SiM^=}GBtdUp z8`Pu-A~B=lLh0D?6v z?29tx0JA1NVN!GrzAE-$j(M#>#|_HJI_PmdH-rtPR*?WKUGm?Z^iB9`>!mK*Qh~91 z5(RLsBlEC%uqPQ1%3`Zox8W?;F}I(tJ$m}MifNf$aFkh*tBGxFJXp|+!O|rK-juS} zIeL|5h^WsurAjBBcDg%_oouev z{@!#a3|Y}c;`b+AU+42xz=&F`cAQ2oyLCGK+U8bAJpnevql7*mfRZ#L->`xyatYyY-p1CO1CXh!I$44JTt5F7z;Hb;V3}hsrXrl&aW2xTG}@FS zl*kgte$bxIC*u$7`htmG3Ia!M%h3q{_$fQ$>ez9q?ZxBgJX8r8qT<$zaf`Ks7w<6* zft$U+cGAqZ+ z>EWzIZsM0`dgGRQ-K}yy6J(kXV>e^0nQpG4l-+|WF$}~T;o=ys<#}=HSSuMbk^k-7 zw^SeZPr9-)TpYr9maz>=Jmrrc-sNzwdo1%cxK6^775R;0hbdhV)21s4h!;655?=_1 zuJ%8Nigbz7Bs`Qg`lB<~Y+0rWvvE3MAPQwK5d_M++dHGhDYPF`r1cj9{_TgV9}Y0rr9%2;#n8XL&uW{$ z{L=fzy6S-#z#ar2x6Ke~qs-Hi#YG#osIYLT$SqXl>XY`8U$_J|32mGxQ6xUuHpqGJ zS$w7Yo_F9C{Q$?%+qZxrY6kfagZK6KItOUE3ogN@M1Kmb$97HJf4%L~BVHAKfDW#$ zapdu1xYFnUHyU(~cQ>7Hl(cSt=|!YaFRS7jZrmQWKWRT`gGkP&JxN1jD@*XXS?@bO zB~)s|4w`qX15USC%Q7F2J#*NsvV3^-3W~;|QhwLF?m2oGelxU7MAeeUB*IABUt4>% zf6^O8yb9%|Ki?k>*G38|X7`srN~yc_!!}ZV9>Au<;S`41+*-$_^TC6NZBCnP)CQNd zydy9Ny;)&LpJG2l`1+2_qdGU|o=NAlQ{fx^^?7|g+5oV0O5co@&MfOTRDPgB(7d;YNU_Wns?zAgc~@4&ZauQb=++|w$qp4sz`p0`c%(ah7o2C+?tDHt zvb{B&BziI#ZfzeK%;!)L`D4}a%~s#hg@m~EfgXoy-Q7Bx6Rym(?)FE#!7lLoS))5D zF11}o|Dx+_?c0~CMqLdVVS+tBPbz9X&V4U4F)GLU$^H1Oyt3B84Y{V;+wS(W6DI5w z|Mu28!QX5{Z{p~~*}OQ0>u>K&9&=aP-Yijy45>De-$CosNnE?pb>jt5g{x4rRixu+q>ozsgaMb9_HkeN& zX366ny2$TxN;s2vFXwCdxq0JfN-H>3B6fK-P(UfEkhdAhcDg3#1`> zid1uBs>&8$6@QFCyxt&jR|vm7VimdoF4uxA5g#}k(0elUp1xnU>EVpEGbdUB<^ z0wm-d*(b^gM;()5>Y<8{)QY{KxF-(XWbC}F4+fUERDADsA0fy6s2nwm$hi5Ce?f-t z`~4A+TY#|8&0@3Tuk06HSE%W&ZuGl1OgDH`eNasAOa@A*-*8&kPf{2Ou1mA2^2OKUt$5BxjKSn4F4v~lTh zR#7&j4o_3?B?t8fLg^0xhPjPz1GjLCaeh%KNpOaleaJdT42OZeW{jCStHKIG*B5%| zp5x1Fx*hZIo`HwPiZp*qvA))}QXgSwjC;1k1(AAI8)$mjnBb=EujH7qo$?Tq-k(I~u)qdU}yyR_1g2+i zNs_O17H@5S>z(Q9!My3ZD}SM}V(w(wtmFv}kmbdVdTb4cqF@)Spm9c+inV+&nZTzP z%}+f*-%#F$-paCMYrNDk{#cXIX@~P>bl(5}Bv%59DnM9qTKDUOO5+ zXr&rOG^AWkz|FbIgq)j5KqReD8+pUp8(!3lGTtm_$dNptH>#u43Tv>xdXWzHNY!y_ zSuf`3e?1V)qmJs-vpd4gX0Yov%-|~<_TRRKTHw7kp9kC`cu3_1bMed`tkKok)o@DD zppQw+K+W|`zR;DYSYDB6Ly!CoMX|;$%Qie_nwEq=qbPEJkE$wefUe-H4$#$+V&=IC zBVTeEN{B^6!U|BwdTmA(1=fZ!A&RHqgtV|08Z><7KqKnS*cxmLLzcUM|9fVC2G!D; zWgtZXm#9RyZ8oviH>X8<&I=ZjqdY>p8PrtrfNnGcr|n2{I)%CyepO2VKB`dV&wW2o z)$lHh<*v%A$p{4U8oJun>Pj5Lxe(+IlTr$K$*UitN}U1b8T=V>34swMA&} z(jXFaZkBEf2Zgnl7`?1^GuNxA+$fEO5?nImNFgq&<}9LNB4w6YcsJsFZVjrAb6 z7JO>Ke$#Xfk+CP2{sO&G042yF35xGN$#1greEenWGTFWrEqp6Z3+c&;ki!~ecpnmE zi?M;KKUvms;rS7zG*m!lBRQ&3voIxK^MwrowMSzsG}p5v3@hc5!25yM4v#`wgstZc z@PoP1Jore0CjdlqrMC>uK`z{aF0@q5@-OVM4Hn3DWzL&4Q*>v)%=Ng5Zr{oY5rNqw ziZB(TWh6`tQGOFsf?=^lY99#2(hdW%hh zFCEQe@8g*Pc`62_4WW%oD=W!xsTjqo%&vuHSw6YEyQBdNS)SN&$Xb^a6pha<$r=}w zWtE1FF;Y;dl`+~dhAktRT3sgd$Aym0Mf^hnHDqj+qx_u9^f;eLcZ^hCKDS^(*@A;6 zM_qBH<6mdFD9g?{vB~+dtO$0;#3*Wx4==2wvdL5Ty1_!$9qd}=aN84yGl@NzIvN2I z{f7xlrj4p<&$7~3xhbiF9CAk$25a_I(T|yTmeNf`hDc5WHUg+1|n;~oP-y%P%K$~-{lK`&Y?%oco)$Zhqq3GZ4WT!cvP zdEW;<{0AD-%av2@2n5^azT`g!tyo8+ch)F7OsY7><0X`nd?k6k{v`v-`VAR$)GCAu z(udTBjT$quqs4_Y{!DMuRA|&;!}y0Bhts3VYuZMeY;epWkI46_0s%q$Y!tS|HjR$# z+;QbTcGadZ35&1^hj8(#Zk{`Yq;}r;56zz>JmNz5L_mbZmAG-|!81A{Ub%A>AkbSF zP7BuKCKCY`52^9yL!6uQF38Y;uS74aG|#*3qPJOH(x>0B5lp=J7J{oqvu7RC#^7l? zvEx^h4np7g-epoj7Ab|Oi$93~ffkVp5-dch#lpzQEfFq4q@|*I-b&Y)_L+}8@cDfD zV)c#YCUa0pR<2~qey_83VyL80sdWqTseGzLa^?9qeSR#|Po*|P_RqA8+QdP^%^S~O zSsBVb+v8JT%(~5aDkr0M-Ja@8zBI`)FjlIn>k}of>PAD!#lTQ$NHy$JAc_^m>EYs< zO>K=-HJ52z*=IJhol~{6lPKbE`1dK0jg2XkZFzFE&#|TDTqdPjRcTzYKOIKxwm?Z~ zN`s}L*BuS}5u;D1478e2!l15(^cLCrQW3mFD*2vX*Xu2<^yoSJ-u^!GIz|-xL3+djK8I`y{c@_%YG1Oyj0GjdNeClx-;{BYtpZ{1^@s6gZpFA literal 0 HcmV?d00001 diff --git a/app/globals.css b/app/globals.css index a51f572..a8872ec 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,144 +1,42 @@ -@import url('https://fonts.googleapis.com/css2?family=DM+Mono:wght@300;400;500&family=Manrope:wght@400;500;600;700&display=swap'); +/* Design tokens: a studio-lit 3D viewport. Axis colours (X red, Y green, Z blue) are marks and lines, not text. */ +:root { + --studio: #e6e9ed; + --studio-deep: #cdd3db; + --paper: #f4f6f8; + --ink: #15181d; + --muted: #5b6571; + --line: rgba(21, 24, 29, 0.14); + --x: #e0384b; + --y: #5aa300; + --z: #2c63e0; + --z-text: #2455c9; - :root { --ink:#f3f6f0; --paper:#0b0e0d; --surface:#121715; --surface-raised:#171d1a; --acid:#c7ff46; --muted:#96a099; --line:rgba(222,237,220,.14); --dark:#070908; --glow:rgba(199,255,70,.14); } -* { box-sizing:border-box; } -html { scroll-behavior:smooth; background:var(--paper); } -body { margin:0; overflow-x:hidden; background:var(--paper); color:var(--ink); font-family:'Manrope',sans-serif; } -main { overflow:hidden; position:relative; background-image:linear-gradient(rgba(255,255,255,.025) 1px, transparent 1px),linear-gradient(90deg, rgba(255,255,255,.025) 1px, transparent 1px); background-size:48px 48px; } -a { color:inherit; text-decoration:none; } -a:focus-visible { outline:2px solid var(--acid); outline-offset:5px; } -::selection { background:var(--acid); color:#0b0e0d; } -.link-arrow { width:14px; height:14px; flex:none; fill:none; stroke:currentColor; stroke-width:1.35; stroke-linecap:round; stroke-linejoin:round; } -.shell { width:min(1180px, calc(100% - 48px)); margin-inline:auto; } -.ambient { position:absolute; width:680px; height:680px; border-radius:50%; pointer-events:none; filter:blur(4px); opacity:.55; } -.ambient-one { top:-350px; right:-220px; background:radial-gradient(circle, var(--glow), transparent 67%); } -.ambient-two { top:1200px; left:-430px; background:radial-gradient(circle, rgba(67,146,130,.13), transparent 66%); } -.nav { height:86px; display:flex; align-items:center; justify-content:space-between; border-bottom:1px solid var(--line); position:relative; z-index:1; } -.mark { font:600 17px 'DM Mono',monospace; letter-spacing:-.04em; color:var(--acid); } -.mark span { color:var(--muted); font-weight:300; } -.nav nav { display:flex; gap:34px; font:400 12px 'DM Mono',monospace; text-transform:uppercase; letter-spacing:.08em; } -.nav nav a { position:relative; transition:color .2s; }.nav nav a::after { content:''; position:absolute; left:0; right:0; bottom:-8px; height:1px; background:var(--acid); transform:scaleX(0); transform-origin:left; transition:transform .2s; }.nav nav a:hover { color:var(--acid); }.nav nav a:hover::after { transform:scaleX(1); } -.hero { min-height:760px; padding:64px 0 70px; position:relative; border-bottom:1px solid var(--line); } -.hero-kicker { max-width:290px; font:400 11px/1.5 'DM Mono',monospace; text-transform:uppercase; letter-spacing:.06em; color:var(--muted); display:flex; gap:10px; } -.pulse { width:8px; height:8px; margin-top:4px; background:var(--acid); border-radius:50%; box-shadow:0 0 0 5px var(--glow),0 0 18px var(--acid); flex:none; } -.hero-orbit { position:absolute; width:230px; height:230px; border:1px solid rgba(199,255,70,.24); right:-60px; top:90px; border-radius:50%; opacity:.55; animation:spin 20s linear infinite; z-index:0; pointer-events:none; } -.hero-orbit::before,.hero-orbit::after { content:''; position:absolute; border-radius:50%; background:var(--acid); box-shadow:0 0 18px var(--acid); }.hero-orbit::before { width:7px; height:7px; top:34px; left:34px; }.hero-orbit::after { width:4px; height:4px; bottom:29px; right:56px; } -.hero-orbit span { position:absolute; inset:32px; border:1px dashed rgba(231,250,224,.18); border-radius:50%; display:grid; place-items:center; font:500 13px 'DM Mono',monospace; color:var(--acid); animation:spin-reverse 20s linear infinite; }.hero-orbit i { position:absolute; width:100%; height:1px; top:50%; background:linear-gradient(90deg, transparent,rgba(199,255,70,.6),transparent); } -.eyebrow { font:400 11px 'DM Mono',monospace; text-transform:uppercase; letter-spacing:.15em; color:var(--muted); } -.hero h1 { font-size:clamp(70px,11.5vw,164px); line-height:.82; letter-spacing:-.085em; margin:56px 0 26px -8px; font-weight:600; position:relative; z-index:1; text-shadow:0 0 55px rgba(199,255,70,.07); } -.hero h2 { max-width:760px; font-size:clamp(28px,4.2vw,58px); line-height:1.03; letter-spacing:-.05em; margin:0 0 32px; font-weight:500; text-wrap:balance; } -.hero-copy { width:min(650px, calc(100% - 220px)); margin-left:26%; color:#bac4bb; font-size:16px; line-height:1.75; } -.hero-actions { margin:42px 0 0 26%; display:flex; gap:10px; } -.button { padding:14px 18px; border:1px solid rgba(243,246,240,.36); background:rgba(15,20,18,.55); font:500 11px 'DM Mono',monospace; text-transform:uppercase; display:flex; gap:26px; justify-content:space-between; transition:transform .2s,background .2s,border .2s; } -.button.primary { background:var(--acid); border-color:var(--acid); color:#11150f; box-shadow:0 12px 30px rgba(199,255,70,.16); }.button:hover { transform:translateY(-3px); background:var(--acid); border-color:var(--acid); color:#11150f; } -.hero-facts { display:flex; gap:38px; margin:58px 0 0 26%; font:400 10px 'DM Mono',monospace; color:var(--muted); text-transform:uppercase; letter-spacing:.05em; }.hero-facts b { color:var(--acid); font-size:17px; font-weight:400; margin-right:6px; } -.hero-index { position:absolute; right:0; bottom:70px; font:300 11px 'DM Mono',monospace; color:var(--muted); pointer-events:none; } -@media (max-width:1100px) { - .hero-orbit { display:none; } - .hero-index { display:none; } -} -.section-heading { display:flex; justify-content:space-between; align-items:flex-end; padding:23px 0; border-bottom:1px solid rgba(243,246,240,.65); } -.section-heading p { margin:0; font:500 12px 'DM Mono',monospace; text-transform:uppercase; letter-spacing:.11em; } -.section-heading span { font:300 11px 'DM Mono',monospace; color:var(--muted); } -.capabilities,.work,.tools,.about { padding-top:100px; } -.cap-grid { display:grid; grid-template-columns:repeat(3,1fr); } -.cap-card { padding:42px 30px 36px 0; min-height:320px; border-right:1px solid var(--line); transition:background .25s,padding .25s; } -.cap-card + .cap-card { padding-left:30px; } -.cap-card:last-child { border-right:0; } -.cap-number { font:300 11px 'DM Mono',monospace; color:var(--muted); } -.cap-card:hover { background:linear-gradient(135deg,rgba(199,255,70,.09),transparent 68%); }.cap-card h3 { font-size:24px; margin:54px 0 16px; letter-spacing:-.035em; }.cap-card p { color:#b0bab2; font-size:14px; line-height:1.7; min-height:74px; }.cap-card:hover .cap-number { color:var(--acid); } -.tag-list { display:flex; flex-wrap:wrap; gap:7px; margin-top:24px; } -.tag-list span { font:400 10px 'DM Mono',monospace; border:1px solid var(--line); background:rgba(255,255,255,.025); padding:6px 8px; color:#b8c2bb; } -.project { display:grid; grid-template-columns:160px minmax(0,1fr) 150px; gap:34px; padding:52px 0; border-bottom:1px solid var(--line); transition:background .25s; }.project:hover { background:linear-gradient(90deg,rgba(199,255,70,.075),transparent 72%); }.project:hover .project-meta span { color:var(--acid); } -.project-meta span { font:300 11px 'DM Mono',monospace; color:var(--muted); } -.project-meta p { font:400 10px/1.5 'DM Mono',monospace; text-transform:uppercase; color:var(--muted); margin-top:14px; max-width:150px; } -.project-body h3 { margin:0 0 18px; font-size:clamp(30px,4vw,52px); letter-spacing:-.055em; font-weight:500; } -.project-body > p { max-width:720px; color:#b0bab2; line-height:1.75; margin:0; } -.project-body ul { display:grid; grid-template-columns:1fr 1fr; padding:0; margin:26px 0 0; list-style:none; gap:9px 20px; } -.project-body li { font:400 11px 'DM Mono',monospace; } -.project-body li::before { content:'—'; color:var(--muted); margin-right:9px; } -.project-links { display:flex; align-items:flex-end; justify-content:flex-end; flex-direction:column; gap:10px; } -.project-links a { width:100%; display:flex; justify-content:space-between; align-items:center; padding:11px 0; border-bottom:1px solid rgba(243,246,240,.55); font:400 10px 'DM Mono',monospace; text-transform:uppercase; }.project-links a:hover { color:var(--acid); border-color:var(--acid); }.project-links a:hover .link-arrow,.tool-grid a:hover .link-arrow,.contact-grid a:hover .link-arrow { transform:translate(2px,-2px); }.link-arrow { transition:transform .2s; } -.tool-grid { display:grid; grid-template-columns:1fr 1fr; } -.tool-grid a { min-height:130px; border-bottom:1px solid var(--line); padding:26px 0; display:flex; justify-content:space-between; gap:30px; transition:color .2s,transform .2s; } -.tool-grid a:nth-child(odd) { padding-right:30px; border-right:1px solid var(--line); } -.tool-grid a:nth-child(even) { padding-left:30px; } -.tool-grid a:last-child:nth-child(odd) { border-right:0; padding-right:0; } -.tool-grid strong { font-size:18px; } -.tool-grid p { color:var(--muted); font-size:12px; margin:9px 0 0; } -.tool-grid a:hover { color:var(--acid); transform:translateX(8px); }.tool-grid a:hover strong { box-shadow:inset 0 -8px rgba(199,255,70,.28); } -.education { display:grid; grid-template-columns:160px 1fr; gap:34px; padding:30px 0; border-bottom:1px solid var(--line); }.education-list { padding:18px 0 70px; }.education-list .education:last-child { border-bottom:0; } -.education > span { font:300 11px 'DM Mono',monospace; color:var(--muted); } -.education h3 { margin:0 0 8px; font-size:22px; } -.education p { margin:0; color:#b0bab2; line-height:1.6; } -.education-note { font-size:13px; } -.footer { background:radial-gradient(circle at 85% 15%,rgba(199,255,70,.13),transparent 26%),var(--dark); color:#f3f6f0; width:100%; max-width:none; padding:90px max(24px,calc((100% - 1180px)/2)) 32px; margin-top:30px; border-top:1px solid var(--line); } -.footer .eyebrow { color:#a4a69c; } -.footer h2 { font-size:clamp(45px,7vw,96px); line-height:.98; letter-spacing:-.065em; font-weight:500; margin:48px 0 80px; } -.footer h2 em { color:var(--acid); font-style:normal; } -.contact-grid { border-top:1px solid #484b42; } -.contact-grid a { display:grid; grid-template-columns:120px 1fr 24px; padding:22px 0; border-bottom:1px solid #484b42; align-items:center; transition:padding .2s,color .2s; }.contact-grid a:hover { padding-inline:10px; } -.contact-grid span { font:400 10px 'DM Mono',monospace; text-transform:uppercase; color:#92958a; } -.contact-grid strong { font-weight:400; } -.contact-grid a:hover strong { color:var(--acid); } -.footer-bottom { display:flex; justify-content:space-between; padding-top:60px; color:#787b71; font:300 9px 'DM Mono',monospace; text-transform:uppercase; } -@keyframes spin { to { transform:rotate(360deg); } } @keyframes spin-reverse { to { transform:rotate(-360deg); } } -@media (prefers-reduced-motion:reduce) { *,*::before,*::after { scroll-behavior:auto!important; animation-duration:.01ms!important; animation-iteration-count:1!important; transition-duration:.01ms!important; } } -@media (max-width:980px) and (min-width:761px) { - .hero h1 { font-size:clamp(72px, 11vw, 120px); } - .hero-orbit { right:2%; width:250px; height:250px; } - .project { grid-template-columns:120px minmax(0,1fr); gap:26px; } - .project-links { grid-column:2; flex-direction:row; justify-content:flex-start; } - .project-links a { width:150px; } -} -@media (max-width:760px) { - .shell { width:min(100% - 28px,1180px); } - .nav { height:70px; }.nav nav { gap:15px; font-size:10px; }.nav nav a::after { bottom:-6px; } - .hero { min-height:auto; padding:55px 0 60px; }.hero-kicker { margin-bottom:34px; }.hero h1 { margin-top:0; font-size:19vw; }.hero h2 { font-size:36px; } - .hero-copy,.hero-actions { width:100%; margin-left:0; }.hero-copy { margin-top:30px; }.hero-actions { flex-direction:column; }.hero-facts { margin-left:0; gap:16px; flex-direction:column; }.hero-index { display:none; } - .section-heading span { display:none; }.capabilities,.work,.tools,.about { padding-top:70px; } - .cap-grid { grid-template-columns:1fr; }.cap-card,.cap-card + .cap-card { border-right:0; border-bottom:1px solid var(--line); padding:34px 0; min-height:0; }.cap-card h3 { margin-top:28px; }.cap-card p { min-height:0; } - .project { grid-template-columns:1fr; gap:20px; padding:38px 0; }.project:hover { padding-left:0; }.project-meta { display:flex; justify-content:space-between; }.project-meta p { margin:0; max-width:none; }.project-body ul { grid-template-columns:1fr; }.project-links { align-items:flex-start; }.project-links a { width:150px; } - .tool-grid { grid-template-columns:1fr; }.tool-grid a:nth-child(n) { border-right:0; padding:24px 0; } - .education { grid-template-columns:1fr; gap:20px; padding-bottom:70px; }.contact-grid a { grid-template-columns:80px 1fr 20px; }.contact-grid strong { font-size:12px; overflow-wrap:anywhere; }.footer-bottom { gap:20px; }.footer-bottom span:last-child { text-align:right; } + --radius-plate: 18px; + --radius-control: 10px; + --shell: min(1240px, calc(100% - 48px)); + --gutter: clamp(20px, 3vw, 32px); + --section: clamp(84px, 11vw, 148px); + + --font-body: var(--font-text), 'Segoe UI', system-ui, sans-serif; + --font-head: var(--font-display), 'Segoe UI', system-ui, sans-serif; } -/* Resume site: skills, experience, live project list, side info. */ -.skill-grid { display:grid; grid-template-columns:repeat(3,1fr); } -.skill-card { padding:34px 28px 34px 0; border-right:1px solid var(--line); border-bottom:1px solid var(--line); transition:background .25s; } -.skill-card:nth-child(3n+2), .skill-card:nth-child(3n) { padding-left:28px; } -.skill-card:nth-child(3n) { border-right:0; } -.skill-card:hover { background:linear-gradient(135deg,rgba(199,255,70,.09),transparent 68%); } -.skill-card h3 { font-size:22px; margin:30px 0 12px; letter-spacing:-.035em; } -.skill-card p { margin:0; color:#b0bab2; font-size:14px; line-height:1.65; } -.exp-item { display:grid; grid-template-columns:200px 1fr; gap:34px; padding:34px 0; border-bottom:1px solid var(--line); } -.exp-item > span { font:300 11px/1.6 'DM Mono',monospace; color:var(--muted); text-transform:uppercase; letter-spacing:.05em; } -.exp-item h3 { margin:0 0 16px; font-size:22px; letter-spacing:-.03em; } -.exp-item ul { margin:0; padding:0; list-style:none; display:grid; gap:9px; color:#b0bab2; line-height:1.6; } -.exp-item li::before { content:'—'; color:var(--muted); margin-right:10px; } -.status-note { margin:0; padding:44px 0; border-bottom:1px solid var(--line); color:var(--muted); font:400 12px/1.8 'DM Mono',monospace; } -.status-note a { color:var(--acid); border-bottom:1px solid rgba(199,255,70,.4); } -.status-note b { color:var(--ink); font-weight:500; } -.project-updated { margin:20px 0 0; color:var(--muted); font:300 10px 'DM Mono',monospace; text-transform:uppercase; letter-spacing:.05em; } -.about-grid { display:grid; grid-template-columns:1.25fr 1fr; gap:64px; padding-bottom:70px; } -.about-grid .education-list { padding-bottom:0; } -.side-info { padding-top:18px; } -.mini-heading { margin:0 0 14px; padding-bottom:10px; border-bottom:1px solid rgba(243,246,240,.35); font:500 11px 'DM Mono',monospace; text-transform:uppercase; letter-spacing:.11em; } -.side-info .mini-heading:not(:first-child) { margin-top:40px; } -.lang-list { list-style:none; margin:0; padding:0; } -.lang-list li { display:flex; justify-content:space-between; padding:10px 0; border-bottom:1px solid var(--line); } -.lang-list b { font:400 11px 'DM Mono',monospace; color:var(--acid); font-weight:400; } -.side-info .tag-list { margin-top:0; } -.contact-note { color:#92958a; font-style:normal; font-size:12px; } -@media (max-width:980px) { - .skill-grid { grid-template-columns:repeat(2,1fr); } - .skill-card:nth-child(n) { padding:34px 24px 34px 0; border-right:1px solid var(--line); } - .skill-card:nth-child(2n) { padding-left:24px; border-right:0; } - .about-grid { grid-template-columns:1fr; gap:40px; } +* { box-sizing: border-box; } +html { background: var(--paper); scroll-behavior: smooth; scroll-padding-top: 88px; } +body { + margin: 0; + color: var(--ink); + font: 400 17px/1.6 var(--font-body); + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; } -@media (max-width:760px) { - .skill-grid { grid-template-columns:1fr; } - .skill-card:nth-child(n) { padding:30px 0; border-right:0; } - .exp-item { grid-template-columns:1fr; gap:14px; padding:28px 0; } - .about-grid { padding-bottom:50px; } +a { color: inherit; } +h1, h2, h3, p, ul, dl, dd, figure { margin: 0; } +ul { padding: 0; list-style: none; } +::selection { background: var(--z); color: #fff; } +:focus-visible { outline: 3px solid var(--z); outline-offset: 3px; border-radius: 4px; } + +@media (prefers-reduced-motion: reduce) { + html { scroll-behavior: auto; } + *, *::before, *::after { animation-duration: 0.01ms !important; animation-delay: 0ms !important; transition-duration: 0.01ms !important; } } diff --git a/app/layout.tsx b/app/layout.tsx index c830ca8..40a057a 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,6 +1,11 @@ import type { Metadata } from 'next' +import localFont from 'next/font/local' import './globals.css' +// Both fonts are bundled (SIL Open Font License), so building never depends on the network. +const display = localFont({ src: './fonts/BricolageGrotesque-Variable.woff2', variable: '--font-display', weight: '200 800', display: 'swap' }) +const text = localFont({ src: './fonts/InstrumentSans-Variable.woff2', variable: '--font-text', weight: '400 700', display: 'swap' }) + export const metadata: Metadata = { title: 'Emil Shanayev — Resume', description: 'Resume of Emil Shanayev: backend, DevOps, AI systems, scientific software and game technology.', @@ -9,7 +14,7 @@ export const metadata: Metadata = { export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { return ( - + {children} ) diff --git a/app/page.tsx b/app/page.tsx index ab37908..4a842f5 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,6 +1,6 @@ +import Site from '@/components/Site' import resume from '@/data/resume.json' import type { Resume } from '@/lib/types' -import Site from './site' export default function Home() { return diff --git a/app/site.tsx b/app/site.tsx deleted file mode 100644 index 506e26a..0000000 --- a/app/site.tsx +++ /dev/null @@ -1,212 +0,0 @@ -'use client' - -import { useEffect, useState } from 'react' -import type { Live, Project, Resume } from '@/lib/types' - -// Deployed on shanaty.ru the build points at the same-origin file; elsewhere (dev, GitHub Pages) it uses the public URL. -const DATA_URL = process.env.NEXT_PUBLIC_DATA_URL ?? 'https://shanaty.ru/data/resume.json' -const GITEA_PROFILE = 'https://git.shanaty.ru/Emil_Shanaty' - -const pad = (n: number) => String(n).padStart(2, '0') -const monthYear = (iso?: string) => (iso ? new Date(iso).toLocaleDateString('en', { month: 'short', year: 'numeric' }) : '') - -const ArrowIcon = () => ( - -) - -type Status = 'loading' | 'live' | 'offline' - -export default function Site({ initial }: Readonly<{ initial: Resume }>) { - const [resume, setResume] = useState(initial) - const [projects, setProjects] = useState([]) - const [generatedAt, setGeneratedAt] = useState() - const [status, setStatus] = useState('loading') - - useEffect(() => { - const controller = new AbortController() - fetch(DATA_URL, { cache: 'no-store', signal: controller.signal }) - .then((response) => (response.ok ? response.json() : Promise.reject(new Error(`HTTP ${response.status}`)))) - .then((data: Live) => { - if (!data?.resume || !Array.isArray(data.projects)) throw new Error('unexpected data') - setResume(data.resume) - setProjects(data.projects) - setGeneratedAt(data.generated_at) - setStatus('live') - }) - .catch((error: Error) => { - if (error.name !== 'AbortError') setStatus('offline') - }) - return () => controller.abort() - }, []) - - // Once the list has loaded and is empty (no repo carries the `resume` topic yet), the section is hidden entirely. - const showProjects = status !== 'live' || projects.length > 0 - const primary = resume.contacts[0] - const github = resume.contacts.find((contact) => contact.label === 'GitHub') - - return ( -

- ) -} diff --git a/components/Cover.tsx b/components/Cover.tsx new file mode 100644 index 0000000..70fbcfe --- /dev/null +++ b/components/Cover.tsx @@ -0,0 +1,102 @@ +import { useMemo } from 'react' + +// Deterministic isometric "sculpture" for a project without a demo image: the repo name seeds a small voxel +// stack, so every project gets its own picture that stays the same between visits. + +function hash(text: string): number { + let h = 2166136261 + for (let i = 0; i < text.length; i++) { + h ^= text.charCodeAt(i) + h = Math.imul(h, 16777619) + } + return h >>> 0 +} + +function random(seed: number) { + let a = seed + return () => { + a = (a + 0x6d2b79f5) | 0 + let t = Math.imul(a ^ (a >>> 15), 1 | a) + t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t + return ((t ^ (t >>> 14)) >>> 0) / 4294967296 + } +} + +const GRID = 5 +const TILE = 54 +const RISE = 30 +const ACCENTS = ['#e0384b', '#5aa300', '#2c63e0'] +const NEUTRAL = { top: '#f9fafb', left: '#d6dbe2', right: '#b8c0cb' } + +function mix(hex: string, other: number, amount: number): string { + const channel = (i: number) => parseInt(hex.slice(1 + i * 2, 3 + i * 2), 16) + const to = (i: number) => Math.round(channel(i) * (1 - amount) + other * amount).toString(16).padStart(2, '0') + return `#${to(0)}${to(1)}${to(2)}` +} + +type Cube = { i: number; j: number; k: number; top: string; left: string; right: string } + +function build(name: string): Cube[] { + const next = random(hash(name)) + const cubes: Cube[] = [] + const accent = ACCENTS[Math.floor(next() * ACCENTS.length)] + const second = ACCENTS[Math.floor(next() * ACCENTS.length)] + for (let i = 0; i < GRID; i++) { + for (let j = 0; j < GRID; j++) { + const edge = Math.abs(i - 2) + Math.abs(j - 2) + const height = Math.max(0, Math.round(next() ** 1.3 * 4 - edge * 0.35)) + for (let k = 0; k < height; k++) { + const isTop = k === height - 1 + const pick = next() + const color = isTop && pick < 0.3 ? accent : isTop && pick < 0.4 ? second : null + cubes.push( + color + ? { i, j, k, top: mix(color, 255, 0.22), left: color, right: mix(color, 0, 0.24) } + : { i, j, k, ...NEUTRAL }, + ) + } + } + } + if (cubes.length < 5) cubes.push({ i: 2, j: 2, k: 0, ...NEUTRAL }, { i: 2, j: 2, k: 1, top: mix(accent, 255, 0.22), left: accent, right: mix(accent, 0, 0.24) }) + return cubes.sort((a, b) => a.i + a.j - (b.i + b.j) || a.k - b.k) +} + +const face = (points: [number, number][]) => points.map((p) => p.join(',')).join(' ') + +export default function Cover({ name }: Readonly<{ name: string }>) { + const cubes = useMemo(() => build(name), [name]) + const originX = 220 + const originY = 150 + const point = (i: number, j: number, z: number, dx: number, dy: number): [number, number] => [ + +(originX + (i - j) * (TILE / 2) + dx).toFixed(1), + +(originY + (i + j) * (TILE / 4) + dy - z).toFixed(1), + ] + + return ( + + ) +} diff --git a/components/Gizmo.tsx b/components/Gizmo.tsx new file mode 100644 index 0000000..fc379f4 --- /dev/null +++ b/components/Gizmo.tsx @@ -0,0 +1,59 @@ +'use client' + +import { useScrollProgress } from '@/lib/useScroll' +import styles from './gizmo.module.css' + +const AXES = [ + { label: 'X', vector: [1, 0, 0], color: 'var(--x)' }, + { label: 'Y', vector: [0, 1, 0], color: 'var(--y)' }, + { label: 'Z', vector: [0, 0, 1], color: 'var(--z)' }, +] as const + +const PITCH = 0.46 +const LENGTH = 29 +const CENTER = 48 + +function project([x, y, z]: readonly [number, number, number], yaw: number) { + const x1 = x * Math.cos(yaw) + z * Math.sin(yaw) + const z1 = -x * Math.sin(yaw) + z * Math.cos(yaw) + const y2 = y * Math.cos(PITCH) - z1 * Math.sin(PITCH) + const depth = y * Math.sin(PITCH) + z1 * Math.cos(PITCH) + return { x: CENTER + x1 * LENGTH, y: CENTER - y2 * LENGTH, depth } +} + +/** Orientation gizmo of a 3D viewport. It orbits as the page scrolls and returns to the top when pressed. */ +export default function Gizmo() { + const progress = useScrollProgress() + const yaw = 0.62 + progress * Math.PI * 1.35 + + const ends = AXES.flatMap((axis) => + ([1, -1] as const).map((sign) => ({ + axis, + positive: sign === 1, + ...project([axis.vector[0] * sign, axis.vector[1] * sign, axis.vector[2] * sign], yaw), + })), + ).sort((a, b) => a.depth - b.depth) + + return ( + + ) +} diff --git a/components/Hero.tsx b/components/Hero.tsx new file mode 100644 index 0000000..6e959ec --- /dev/null +++ b/components/Hero.tsx @@ -0,0 +1,41 @@ +'use client' + +import { useRef } from 'react' +import type { Resume } from '@/lib/types' +import styles from './hero.module.css' + +type Props = { resume: Resume; mailHref: string; showProjects: boolean } + +export default function Hero({ resume, mailHref, showProjects }: Readonly) { + const hero = useRef(null) + + // The floor sways a couple of degrees with the pointer, like nudging the viewport. + const onPointerMove = (event: React.PointerEvent) => { + if (event.pointerType !== 'mouse' || !hero.current) return + const offset = event.clientX / window.innerWidth - 0.5 + hero.current.style.setProperty('--sway', `${(offset * 3).toFixed(2)}deg`) + } + + return ( +
+
+

+ + {resume.availability} +

+

{resume.name}

+

{resume.role}

+

{resume.bio}

+
+ {showProjects && See projects} + Email me +
+
+
+ ) +} diff --git a/components/Projects.tsx b/components/Projects.tsx new file mode 100644 index 0000000..de8cfc4 --- /dev/null +++ b/components/Projects.tsx @@ -0,0 +1,108 @@ +'use client' + +import { useMemo, useState } from 'react' +import { planSpans, type Span } from '@/lib/plan' +import type { Project } from '@/lib/types' +import Cover from './Cover' +import styles from './projects.module.css' + +const monthYear = (iso?: string) => (iso ? new Date(iso).toLocaleDateString('en', { month: 'short', year: 'numeric' }) : '') + +// Aspect ratio of a plate for each span on desktop, used to decide whether a demo image can be cropped to fill it. +const PLATE_RATIO: Record = { 2: 4 / 3, 3: 3 / 2, 4: 16 / 9, 6: 16 / 10 } + +function Plate({ project, span }: Readonly<{ project: Project; span: Span }>) { + const [broken, setBroken] = useState(false) + const demo = project.demo + const title = project.title ?? project.name + if (!demo || broken) return + + const drift = Math.abs(Math.log(demo.width / demo.height / PLATE_RATIO[span])) + const fits = drift < Math.log(1.7) + const image = (className: string, extra: React.ImgHTMLAttributes) => ( + // eslint-disable-next-line @next/next/no-img-element + + ) + return ( + <> + {/* An image that does not match the plate is shown whole, over a blurred copy of itself. */} + {!fits && image(styles.backdrop, { alt: '', 'aria-hidden': true, loading: 'lazy' })} + {image(fits ? styles.cover : styles.contain, { alt: `${title}, demo`, loading: 'lazy', onError: () => setBroken(true) })} + + ) +} + +function Item({ project, span }: Readonly<{ project: Project; span: Span }>) { + const title = project.title ?? project.name + const links = [ + { label: 'Repository', href: project.url }, + ...(project.homepage ? [{ label: 'Live site', href: project.homepage }] : []), + ...(project.links ?? []), + ] + return ( +
+ + + +
+

{title}

+ {(project.kind ?? project.language) &&

{project.kind ?? project.language}

} + {project.description &&

{project.description}

} + {project.highlights && project.highlights.length > 0 && ( +
    {project.highlights.map((point) =>
  • {point}
  • )}
+ )} +
+ {project.tech.length > 0 &&
    {project.tech.map((tag) =>
  • {tag}
  • )}
} +

+ {links.map((link) => ( + {link.label} + ))} +

+
+
+
+ ) +} + +type Props = { + projects: Project[] + status: 'loading' | 'live' | 'offline' + generatedAt?: string + profileUrl: string +} + +export default function Projects({ projects, status, generatedAt, profileUrl }: Readonly) { + const spans = useMemo(() => planSpans(projects.length), [projects.length]) + return ( +
+
+
+

Selected work

+ {status === 'live' &&

Read live from Gitea, updated {monthYear(generatedAt)}

} +
+ + {status === 'loading' && ( + + )} + {status === 'loading' && ( + + )} + {status === 'offline' && ( +

+ The project list could not be loaded right now. All repositories are on {profileUrl.replace('https://', '')}. +

+ )} + +
+ {projects.map((project, index) => ( + + ))} +
+
+
+ ) +} diff --git a/components/Sections.tsx b/components/Sections.tsx new file mode 100644 index 0000000..e80fab1 --- /dev/null +++ b/components/Sections.tsx @@ -0,0 +1,103 @@ +import type { Resume } from '@/lib/types' +import styles from './sections.module.css' + +export function Skills({ resume }: Readonly<{ resume: Resume }>) { + return ( +
+
+

What I work with

+
+ {resume.skills.map((skill) => ( +
+

{skill.title}

+

{skill.text}

+
    {skill.stack.map((tag) =>
  • {tag}
  • )}
+
+ ))} +
+
+
+ ) +} + +export function Experience({ resume }: Readonly<{ resume: Resume }>) { + return ( +
+
+

Experience

+
+ {resume.experience.map((entry) => ( +
+

{entry.meta}

+
+

{entry.title}

+
    {entry.points.map((point) =>
  • {point}
  • )}
+
+
+ ))} +
+
+
+ ) +} + +export function Education({ resume }: Readonly<{ resume: Resume }>) { + return ( +
+
+

Education and languages

+
+
+

Education

+
+ {resume.education.map((entry) => ( +
+

{entry.institution}

+

{entry.program}

+

{entry.period}

+
+ ))} +
+
+
+

Languages

+
+ {resume.languages.map((language) => ( +
+
{language.name}
+
{language.level}
+
+ ))} +
+
+
+

Interests

+

{resume.interests.join(', ')}.

+
+
+
+
+ ) +} + +export function Contact({ resume }: Readonly<{ resume: Resume }>) { + const [primary, ...others] = resume.contacts + return ( +
+
+

Get in touch

+

Email is the fastest way to reach me.

+ {primary.value} +
    + {others.map((contact) => ( +
  • + {contact.label} + {contact.value} +
  • + ))} +
+

© 2026 {resume.name}. The text and the projects on this page are read live from Gitea.

+
+
+ ) +} diff --git a/components/Site.tsx b/components/Site.tsx new file mode 100644 index 0000000..dd159a2 --- /dev/null +++ b/components/Site.tsx @@ -0,0 +1,58 @@ +'use client' + +import { useEffect, useState } from 'react' +import type { Live, Project, Resume } from '@/lib/types' +import Gizmo from './Gizmo' +import Hero from './Hero' +import Projects from './Projects' +import { Contact, Education, Experience, Skills } from './Sections' +import TopBar from './TopBar' + +// Deployed on shanaty.ru the build points at the same-origin file; elsewhere (dev, GitHub Pages) it uses the public URL. +const DATA_URL = process.env.NEXT_PUBLIC_DATA_URL ?? 'https://shanaty.ru/data/resume.json' +const GITEA_PROFILE = 'https://git.shanaty.ru/Emil_Shanaty' + +type Status = 'loading' | 'live' | 'offline' + +export default function Site({ initial }: Readonly<{ initial: Resume }>) { + const [resume, setResume] = useState(initial) + const [projects, setProjects] = useState([]) + const [generatedAt, setGeneratedAt] = useState() + const [status, setStatus] = useState('loading') + + useEffect(() => { + const controller = new AbortController() + fetch(DATA_URL, { cache: 'no-store', signal: controller.signal }) + .then((response) => (response.ok ? response.json() : Promise.reject(new Error(`HTTP ${response.status}`)))) + .then((data: Live) => { + if (!data?.resume || !Array.isArray(data.projects)) throw new Error('unexpected data') + setResume(data.resume) + setProjects(data.projects) + setGeneratedAt(data.generated_at) + setStatus('live') + }) + .catch((error: Error) => { + if (error.name !== 'AbortError') setStatus('offline') + }) + return () => controller.abort() + }, []) + + // Once the list has loaded and is empty (no repository carries the `resume` topic yet) the section is left out. + const showProjects = status !== 'live' || projects.length > 0 + const mailHref = resume.contacts[0].href + + return ( + <> + + +
+ + {showProjects && } + + + +
+ + + ) +} diff --git a/components/TopBar.tsx b/components/TopBar.tsx new file mode 100644 index 0000000..24c1d92 --- /dev/null +++ b/components/TopBar.tsx @@ -0,0 +1,24 @@ +'use client' + +import { useScrolled } from '@/lib/useScroll' +import styles from './topbar.module.css' + +type Props = { name: string; mailHref: string; showProjects: boolean } + +export default function TopBar({ name, mailHref, showProjects }: Readonly) { + const scrolled = useScrolled() + return ( +
+
+ {name} + + Email me +
+
+ ) +} diff --git a/components/gizmo.module.css b/components/gizmo.module.css new file mode 100644 index 0000000..ca064e9 --- /dev/null +++ b/components/gizmo.module.css @@ -0,0 +1,38 @@ +.gizmo { + position: fixed; + z-index: 40; + top: 84px; + right: max(16px, calc((100vw - 1240px) / 2 - 8px)); + width: 88px; + height: 88px; + padding: 0; + border: 0; + border-radius: 50%; + background: rgba(244, 246, 248, 0.62); + box-shadow: 0 0 0 1px rgba(21, 24, 29, 0.08); + -webkit-backdrop-filter: blur(8px); + backdrop-filter: blur(8px); + cursor: pointer; +} + +.gizmo svg { + display: block; + width: 100%; + height: 100%; +} + +.letter { + fill: #fff; + font: 700 10.5px var(--font-body); + pointer-events: none; +} + +@media (max-width: 760px) { + .gizmo { + top: auto; + bottom: 16px; + right: 16px; + width: 64px; + height: 64px; + } +} diff --git a/components/hero.module.css b/components/hero.module.css new file mode 100644 index 0000000..5bed102 --- /dev/null +++ b/components/hero.module.css @@ -0,0 +1,191 @@ +.hero { + --sway: 0deg; + position: relative; + isolation: isolate; + display: flex; + flex-direction: column; + min-height: min(100svh, 1000px); + overflow: clip; + background: linear-gradient(180deg, #f5f7fa 0%, #e6e9ee 100%); +} + +/* The floor is a stage of its own below the text, so the grid never runs through the copy at any window height. */ +.stage { + position: relative; + flex: 1; + min-height: 260px; + overflow: hidden; + background: linear-gradient(180deg, #d8dde4 0%, var(--studio-deep) 100%); + border-top: 1px solid rgba(21, 24, 29, 0.2); +} + +.stage::after { + content: ''; + position: absolute; + inset: auto 0 0 0; + height: 45%; + background: linear-gradient(180deg, transparent, var(--paper)); +} + +.floor { + position: absolute; + inset: 0; + perspective: 620px; + perspective-origin: 50% 0; + animation: open 1.7s cubic-bezier(0.2, 0.7, 0.2, 1) 0.1s both; +} + +.plane { + position: absolute; + left: -70%; + right: -70%; + top: 0; + height: 300%; + transform-origin: 50% 0; + transform: rotateX(76deg) rotateZ(var(--sway)); + background-image: + linear-gradient(to right, rgba(21, 24, 29, 0.2) 1px, transparent 1px), + linear-gradient(to bottom, rgba(21, 24, 29, 0.2) 1px, transparent 1px); + background-size: 80px 80px; + background-position: center top; + -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 18%, #000 100%); + mask-image: linear-gradient(to bottom, transparent 0%, #000 18%, #000 100%); +} + +/* The red X axis crosses the floor; the blue Z axis runs into the distance, like the axes of a 3D viewport. */ +.plane::before, +.plane::after { + content: ''; + position: absolute; +} + +.plane::before { + left: 0; + right: 0; + top: 240px; + height: 3px; + background: var(--x); +} + +.plane::after { + top: 0; + bottom: 0; + left: calc(50% - 1.5px); + width: 3px; + background: var(--z); +} + +.content { + position: relative; + width: var(--shell); + margin: 0 auto; + padding: 136px 0 72px; +} + +.status { + display: inline-flex; + align-items: center; + gap: 10px; + max-width: 100%; + padding: 8px 16px 8px 13px; + border-radius: 999px; + background: rgba(255, 255, 255, 0.72); + box-shadow: inset 0 0 0 1px var(--line); + font-size: 15px; + font-weight: 500; + line-height: 1.35; +} + +.dot { + flex: none; + width: 9px; + height: 9px; + border-radius: 50%; + background: var(--y); + box-shadow: 0 0 0 4px rgba(90, 163, 0, 0.2); +} + +.name { + margin: 30px 0 0 -0.045em; + font: 800 clamp(56px, 12.6vw, 204px) / 0.88 var(--font-head); + letter-spacing: -0.048em; +} + +.role { + margin-top: 22px; + font: 500 clamp(22px, 2.7vw, 38px) / 1.15 var(--font-head); + letter-spacing: -0.022em; +} + +.bio { + max-width: 58ch; + margin-top: 44px; + font-size: 19px; + line-height: 1.62; + color: rgba(21, 24, 29, 0.88); +} + +.actions { + display: flex; + flex-wrap: wrap; + gap: 12px; + margin-top: 32px; +} + +.button { + padding: 14px 24px; + border-radius: var(--radius-control); + font: 600 16px/1.2 var(--font-body); + text-decoration: none; + transition: background-color 0.2s, color 0.2s, box-shadow 0.2s; +} + +.primary { + background: var(--ink); + color: var(--paper); +} + +.primary:hover { + background: var(--z); +} + +.secondary { + box-shadow: inset 0 0 0 1.5px var(--ink); +} + +.secondary:hover { + background: var(--ink); + color: var(--paper); +} + +/* One orchestrated moment on load: the floor opens out from the Z axis while the text settles in. */ +.status, +.name, +.role, +.bio, +.actions { + animation: rise 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) both; +} + +.name { animation-delay: 0.06s; } +.role { animation-delay: 0.16s; } +.bio { animation-delay: 0.26s; } +.actions { animation-delay: 0.34s; } + +@keyframes rise { + from { opacity: 0; transform: translateY(16px); } + to { opacity: 1; transform: none; } +} + +@keyframes open { + from { clip-path: inset(0 50% 0 50%); } + to { clip-path: inset(0 0 0 0); } +} + +@media (max-width: 760px) { + .content { padding: 112px 0 72px; } + .bio { margin-top: 32px; font-size: 18px; } + .stage { min-height: 200px; } + .plane::before { top: 170px; } + .plane { background-size: 56px 56px; } +} diff --git a/components/projects.module.css b/components/projects.module.css new file mode 100644 index 0000000..cf5011a --- /dev/null +++ b/components/projects.module.css @@ -0,0 +1,237 @@ +.section { + padding: 24px 0 var(--section); +} + +.shell { + width: var(--shell); + margin: 0 auto; +} + +.head { + display: flex; + flex-wrap: wrap; + align-items: baseline; + justify-content: space-between; + gap: 8px 24px; + margin-bottom: clamp(36px, 5vw, 64px); +} + +.head h2 { + font: 700 clamp(40px, 5.6vw, 80px) / 1 var(--font-head); + letter-spacing: -0.04em; +} + +.note { + font-size: 15px; + color: var(--muted); +} + +.notice { + padding: 28px 0; + border-top: 1px solid var(--line); + border-bottom: 1px solid var(--line); + color: var(--muted); +} + +.notice a { + color: var(--z-text); +} + +/* Mobile first: one column. Tablet: two. Desktop: six columns, with the spans planned per project count. */ +.grid { + display: grid; + grid-template-columns: minmax(0, 1fr); + gap: 56px 28px; +} + +.item { + display: flex; + flex-direction: column; + gap: 20px; + min-width: 0; +} + +.plate { + position: relative; + display: block; + aspect-ratio: 3 / 2; + overflow: hidden; + border-radius: var(--radius-plate); + background: radial-gradient(120% 90% at 50% 0%, #f3f5f8 0%, var(--studio) 55%, #d3d9e0 100%); + box-shadow: inset 0 0 0 1px rgba(21, 24, 29, 0.09); +} + +.plate img, +.plate svg { + display: block; + width: 100%; + height: 100%; +} + +.cover { + object-fit: cover; +} + +.contain { + position: relative; + object-fit: contain; + padding: 6%; + filter: drop-shadow(0 10px 24px rgba(21, 24, 29, 0.28)); +} + +.backdrop { + position: absolute; + inset: 0; + object-fit: cover; + transform: scale(1.3); + filter: blur(26px) saturate(1.2); + opacity: 0.55; +} + +.caption { + display: flex; + flex: 1; + flex-direction: column; + gap: 10px; +} + +.caption h3 { + font: 700 clamp(24px, 2.2vw, 30px) / 1.1 var(--font-head); + letter-spacing: -0.03em; +} + +.kind { + font-size: 15px; + font-weight: 500; + color: var(--muted); +} + +.description { + max-width: 62ch; + color: rgba(21, 24, 29, 0.86); +} + +.points { + display: grid; + gap: 4px; + font-size: 15px; + color: rgba(21, 24, 29, 0.78); +} + +.points li { + position: relative; + padding-left: 18px; +} + +.points li::before { + content: ''; + position: absolute; + left: 2px; + top: 0.62em; + width: 6px; + height: 6px; + border-radius: 1px; + background: var(--z); +} + +.foot { + display: flex; + flex-direction: column; + gap: 16px; + margin-top: auto; + padding-top: 8px; +} + +.tags { + display: flex; + flex-wrap: wrap; + gap: 6px; +} + +.tags li { + padding: 3px 11px; + border-radius: 999px; + box-shadow: inset 0 0 0 1px var(--line); + font-size: 13.5px; + line-height: 1.5; +} + +.links { + display: flex; + flex-wrap: wrap; + gap: 4px 20px; + font-size: 15px; + font-weight: 600; +} + +.links a { + text-decoration: underline; + text-decoration-thickness: 1.5px; + text-underline-offset: 4px; + text-decoration-color: rgba(21, 24, 29, 0.3); + transition: text-decoration-color 0.2s, color 0.2s; +} + +.links a:hover { + color: var(--z-text); + text-decoration-color: currentColor; +} + +/* Placeholder while the list loads: three empty plates that hold the space. */ +.skeleton { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 28px; +} + +.skeleton span { + aspect-ratio: 3 / 2; + border-radius: var(--radius-plate); + background: linear-gradient(160deg, #eef1f4, var(--studio)); +} + +@media (min-width: 641px) and (max-width: 1000px) { + .grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + /* An odd last project spans the full row instead of leaving a hole. */ + .item:last-child:nth-child(odd) { + grid-column: 1 / -1; + } + .item:last-child:nth-child(odd):not(:only-child) .plate { + aspect-ratio: 16 / 9; + } +} + +@media (max-width: 640px) { + .skeleton { + grid-template-columns: minmax(0, 1fr); + } + .skeleton span:nth-child(n + 2) { + display: none; + } +} + +@media (min-width: 1001px) { + .grid { + grid-template-columns: repeat(6, minmax(0, 1fr)); + gap: 72px 32px; + } + .item[data-span='2'] { grid-column: span 2; } + .item[data-span='3'] { grid-column: span 3; } + .item[data-span='4'] { grid-column: span 4; } + .item[data-span='6'] { grid-column: span 6; } + + .item[data-span='2'] .plate { aspect-ratio: 4 / 3; } + .item[data-span='3'] .plate { aspect-ratio: 3 / 2; } + .item[data-span='4'] .plate { aspect-ratio: 16 / 9; } + + /* A single project gets the whole width: plate and text side by side. */ + .item[data-span='6'] { + display: grid; + grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); + align-items: center; + gap: 40px; + } + .item[data-span='6'] .plate { aspect-ratio: 16 / 10; } +} diff --git a/components/sections.module.css b/components/sections.module.css new file mode 100644 index 0000000..e62bd7d --- /dev/null +++ b/components/sections.module.css @@ -0,0 +1,226 @@ +.section { + padding: var(--section) 0 0; +} + +.shell { + width: var(--shell); + margin: 0 auto; +} + +.title { + margin-bottom: clamp(32px, 4.5vw, 56px); + font: 700 clamp(36px, 5vw, 72px) / 1 var(--font-head); + letter-spacing: -0.04em; +} + +/* Skills: two columns of rows divided by a rule, no boxes. */ +.skills { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0 clamp(32px, 6vw, 96px); +} + +.skill { + display: flex; + flex-direction: column; + gap: 10px; + padding: 28px 0 36px; + border-top: 1px solid var(--line); +} + +.skill h3, +.entry h3 { + font: 700 clamp(22px, 2.2vw, 28px) / 1.15 var(--font-head); + letter-spacing: -0.03em; +} + +.skill p { + max-width: 52ch; + color: rgba(21, 24, 29, 0.82); +} + +.tags { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-top: 6px; +} + +.tags li { + padding: 3px 11px; + border-radius: 999px; + background: rgba(21, 24, 29, 0.06); + font-size: 13.5px; + line-height: 1.5; +} + +/* Experience */ +.entry { + display: grid; + grid-template-columns: minmax(150px, 1fr) minmax(0, 3fr); + gap: 24px 32px; + padding: 32px 0 40px; + border-top: 1px solid var(--line); +} + +.meta { + color: var(--muted); + font-size: 15px; +} + +.list { + display: grid; + gap: 10px; + margin-top: 18px; + max-width: 66ch; +} + +.list li { + position: relative; + padding-left: 22px; +} + +.list li::before { + content: ''; + position: absolute; + left: 2px; + top: 0.7em; + width: 7px; + height: 7px; + border-radius: 1px; + background: var(--z); +} + +/* Education, languages, interests */ +.columns { + display: grid; + grid-template-columns: 1.4fr 1fr 1.2fr; + gap: 40px clamp(32px, 5vw, 72px); + padding-top: 28px; + border-top: 1px solid var(--line); +} + +.label { + margin-bottom: 14px; + font: 700 20px/1.2 var(--font-head); + letter-spacing: -0.02em; +} + +.stack { + display: grid; + gap: 22px; +} + +.strong { + font-weight: 600; +} + +.languages { + display: grid; + gap: 8px; +} + +.languages div { + display: flex; + justify-content: space-between; + gap: 16px; + padding-bottom: 8px; + border-bottom: 1px solid var(--line); +} + +.languages dd { + color: var(--muted); +} + +/* Contact: the one inverted band, closing the page. */ +.contact { + margin-top: var(--section); + padding: clamp(72px, 9vw, 128px) 0 40px; + background: var(--ink); + color: var(--paper); +} + +.contactTitle { + font: 700 clamp(36px, 5vw, 72px) / 1 var(--font-head); + letter-spacing: -0.04em; +} + +.contactLead { + margin-top: 16px; + color: rgba(244, 246, 248, 0.7); +} + +.mail { + display: inline-block; + margin-top: clamp(28px, 4vw, 48px); + font: 700 clamp(26px, 6.4vw, 96px) / 1.05 var(--font-head); + letter-spacing: -0.045em; + overflow-wrap: anywhere; + text-decoration: none; + background: linear-gradient(var(--z), var(--z)) left bottom / 100% 0.08em no-repeat; + transition: background-size 0.25s, color 0.25s; +} + +.mail:hover { + background-size: 100% 100%; +} + +.contacts { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 0 32px; + margin-top: clamp(56px, 7vw, 96px); +} + +.contacts li { + display: flex; + flex-direction: column; + gap: 2px; + padding: 18px 0; + border-top: 1px solid rgba(244, 246, 248, 0.2); +} + +.contacts span { + font-size: 14px; + color: rgba(244, 246, 248, 0.6); +} + +.contacts a { + text-decoration: underline; + text-decoration-thickness: 1.5px; + text-underline-offset: 4px; + text-decoration-color: rgba(244, 246, 248, 0.35); + overflow-wrap: anywhere; +} + +.contacts a:hover { + text-decoration-color: currentColor; +} + +.legal { + margin-top: clamp(48px, 6vw, 80px); + font-size: 14px; + color: rgba(244, 246, 248, 0.55); +} + +@media (max-width: 900px) { + .skills { + grid-template-columns: minmax(0, 1fr); + } + .columns { + grid-template-columns: minmax(0, 1fr); + } +} + +@media (max-width: 760px) { + .legal { + padding-right: 76px; /* keeps clear of the floating gizmo */ + } +} + +@media (max-width: 700px) { + .entry { + grid-template-columns: minmax(0, 1fr); + gap: 10px; + } +} diff --git a/components/topbar.module.css b/components/topbar.module.css new file mode 100644 index 0000000..6b34037 --- /dev/null +++ b/components/topbar.module.css @@ -0,0 +1,69 @@ +.bar { + position: fixed; + z-index: 50; + inset: 0 0 auto 0; + border-bottom: 1px solid transparent; + transition: background-color 0.25s, border-color 0.25s; +} + +.solid { + background: rgba(244, 246, 248, 0.86); + border-bottom-color: var(--line); + -webkit-backdrop-filter: blur(12px); + backdrop-filter: blur(12px); +} + +.inner { + width: var(--shell); + height: 68px; + margin: 0 auto; + display: flex; + align-items: center; + gap: 32px; +} + +.mark { + margin-right: auto; + font: 700 20px/1 var(--font-head); + letter-spacing: -0.03em; + text-decoration: none; +} + +.nav { + display: flex; + gap: 28px; + font-size: 15px; + font-weight: 500; +} + +.nav a { + text-decoration: none; + padding: 6px 0; + background: linear-gradient(currentColor, currentColor) left bottom / 0 1.5px no-repeat; + transition: background-size 0.25s; +} + +.nav a:hover { + background-size: 100% 1.5px; +} + +.mail { + padding: 10px 18px; + border-radius: var(--radius-control); + background: var(--ink); + color: var(--paper); + font-size: 15px; + font-weight: 600; + text-decoration: none; + transition: background-color 0.2s; +} + +.mail:hover { + background: var(--z); +} + +@media (max-width: 860px) { + .nav { + display: none; + } +} diff --git a/data/resume.json b/data/resume.json index 370389b..295d3e2 100644 --- a/data/resume.json +++ b/data/resume.json @@ -1,10 +1,10 @@ { "name": "Emil Shanayev", - "eyebrow": "backend · devops · AI systems · scientific computing · game tech", + "eyebrow": "Backend, DevOps, AI systems, scientific computing and game tech", "role": "Backend, DevOps & AI Systems Developer", "bio": "I build AI-native products, backend services and the infrastructure to run them: from Python/FastAPI and Go services, WebSocket APIs and containerised CI/CD pipelines to distributed molecular workloads, LLM-controlled worlds and a Vulkan game engine. I run self-hosted services on my own Linux servers.", "location": "Russia", - "availability": "Open to internships, full-time, part-time and project work · remote, hybrid or on-site", + "availability": "Open to internships, and to full-time, part-time or project work. Remote, hybrid or on-site.", "contacts": [ { "label": "Email", @@ -13,7 +13,7 @@ "note": "preferred" }, { - "label": "Email", + "label": "Email, alternative", "value": "emil28092005@gmail.com", "href": "mailto:emil28092005@gmail.com" }, @@ -140,14 +140,14 @@ ], "education": [ { - "period": "2026 — 2030", + "period": "2026 to 2030", "institution": "HSE University, Moscow", - "program": "Bachelor’s programme · Game and Digital Product Development · 1st-year student" + "program": "Bachelor’s programme in Game and Digital Product Development. First year." }, { - "period": "2023 — 2025", + "period": "2023 to 2025", "institution": "Innopolis University", - "program": "Data Structures and Artificial Intelligence (DSAI) · 2 years, incomplete higher education" + "program": "Data Structures and Artificial Intelligence (DSAI). Two years, higher education not completed." } ], "languages": [ @@ -161,12 +161,12 @@ } ], "interests": [ - "DevOps & Infrastructure as Code", - "High-load backend systems", - "Linux & systems administration", - "Computer graphics & game development", - "Open source", - "Learning from documentation and by building" + "DevOps and Infrastructure as Code", + "high-load backend systems", + "Linux and systems administration", + "computer graphics and game development", + "open source", + "learning from documentation and by building" ], "projectNotes": { "Cortex_Engine": { diff --git a/lib/plan.ts b/lib/plan.ts new file mode 100644 index 0000000..3d1ab6c --- /dev/null +++ b/lib/plan.ts @@ -0,0 +1,39 @@ +export type Span = 2 | 3 | 4 | 6 + +/** + * Column spans (out of 6) for `count` projects, so that every row is exactly full whatever the count: + * rows of two or three, a feature row first, and never a lone project in the last row (a single project + * spans the whole width). Two-project rows alternate 4+2 and 2+4 for rhythm. + */ +export function planSpans(count: number): Span[] { + if (count <= 0) return [] + if (count === 1) return [6] + + const sizes: number[] = [] + const pattern = [2, 3, 3] + let remaining = count + for (let i = 0; remaining > 0; i++) { + const size = Math.min(pattern[i % pattern.length], remaining) + sizes.push(size) + remaining -= size + } + + const last = sizes.length - 1 + if (sizes[last] === 1) { + if (sizes[last - 1] === 3) { + sizes[last - 1] = 2 + sizes[last] = 2 + } else { + sizes[last - 1] = 3 + sizes.pop() + } + } + + const spans: Span[] = [] + let pairs = 0 + for (const size of sizes) { + if (size === 3) spans.push(2, 2, 2) + else spans.push(...(pairs++ % 2 === 0 ? ([4, 2] as const) : ([2, 4] as const))) + } + return spans +} diff --git a/lib/types.ts b/lib/types.ts index 39030da..3f663ae 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -20,6 +20,8 @@ export type Resume = { } // A public Gitea repository tagged `resume`, merged with the optional notes from data/resume.json. +export type Demo = { url: string; width: number; height: number } + export type Project = { name: string title?: string @@ -33,6 +35,9 @@ export type Project = { language?: string stars?: number updated?: string + rank?: number + // Image copied from `demo.*` in the repo root by the server sync; the size lets the layout reserve space. + demo?: Demo } // Shape of /data/resume.json, written every minute by the server-side sync. diff --git a/lib/useScroll.ts b/lib/useScroll.ts new file mode 100644 index 0000000..b362cfd --- /dev/null +++ b/lib/useScroll.ts @@ -0,0 +1,43 @@ +'use client' + +import { useEffect, useState } from 'react' + +const reducedMotion = () => window.matchMedia('(prefers-reduced-motion: reduce)').matches + +/** Scroll position of the page as 0..1. Updates at most once per frame; frozen when the user prefers reduced motion. */ +export function useScrollProgress(): number { + const [progress, setProgress] = useState(0) + useEffect(() => { + if (reducedMotion()) return + let frame = 0 + const update = () => { + frame = 0 + const max = document.documentElement.scrollHeight - window.innerHeight + setProgress(max > 0 ? Math.min(1, Math.max(0, window.scrollY / max)) : 0) + } + const schedule = () => { + if (!frame) frame = requestAnimationFrame(update) + } + update() + window.addEventListener('scroll', schedule, { passive: true }) + window.addEventListener('resize', schedule) + return () => { + window.removeEventListener('scroll', schedule) + window.removeEventListener('resize', schedule) + if (frame) cancelAnimationFrame(frame) + } + }, []) + return progress +} + +/** True once the page has scrolled past the very top; only changes state when that flips. */ +export function useScrolled(threshold = 8): boolean { + const [scrolled, setScrolled] = useState(false) + useEffect(() => { + const update = () => setScrolled(window.scrollY > threshold) + update() + window.addEventListener('scroll', update, { passive: true }) + return () => window.removeEventListener('scroll', update) + }, [threshold]) + return scrolled +}
-