Initial commit

This commit is contained in:
2026-02-05 18:09:28 +03:00
commit d6ee21c9d7
24 changed files with 2645 additions and 0 deletions

49
src/css/animations.css Normal file
View File

@@ -0,0 +1,49 @@
/* ===== IntersectionObserver fallback ===== */
[data-reveal] {
opacity: 0;
transform: translateY(24px);
transition: opacity 0.6s ease, transform 0.6s ease;
}
[data-reveal].is-visible {
opacity: 1;
transform: translateY(0);
}
/* ===== Scroll-driven animations (progressive enhancement) ===== */
.has-scroll-driven [data-reveal] {
opacity: 1;
transform: none;
transition: none;
animation: reveal-in linear both;
animation-timeline: view();
animation-range: entry 0% entry 30%;
}
@keyframes reveal-in {
from {
opacity: 0;
transform: translateY(24px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Details open/close transition */
.services__content {
animation: accordion-open 0.25s ease;
}
@keyframes accordion-open {
from {
opacity: 0;
transform: translateY(-8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

53
src/css/base.css Normal file
View File

@@ -0,0 +1,53 @@
body {
font-family: var(--font-body);
font-size: var(--body-size);
line-height: var(--body-lh);
color: var(--color-dark);
background-color: var(--color-bg);
font-weight: 400;
}
.h1 {
font-family: var(--font-headline);
font-size: var(--h1-size);
line-height: var(--h1-lh);
font-weight: 900;
font-stretch: 125%;
text-transform: uppercase;
letter-spacing: -0.02em;
}
.h2 {
font-family: var(--font-headline);
font-size: var(--h2-size);
line-height: var(--h2-lh);
font-weight: 900;
font-stretch: 125%;
text-transform: uppercase;
letter-spacing: -0.01em;
}
.h3 {
font-family: var(--font-headline);
font-size: var(--h3-size);
line-height: var(--h3-lh);
font-weight: 900;
font-stretch: 125%;
text-transform: uppercase;
}
.body-text {
font-family: var(--font-body);
font-size: var(--body-size);
line-height: calc(var(--body-lh) + 6px);
font-weight: 400;
}
.caption {
font-family: var(--font-body);
font-size: var(--caption-size);
line-height: var(--caption-lh);
font-weight: 400;
text-transform: uppercase;
letter-spacing: 0.05em;
}

52
src/css/cases.css Normal file
View File

@@ -0,0 +1,52 @@
.cases {
padding: var(--section-gap) 0;
background-color: var(--color-dark);
color: var(--color-white);
}
.cases__heading {
margin-bottom: 60px;
}
.cases__grid {
row-gap: var(--grid-gutter);
}
.cases__tile {
display: grid;
grid-template: 1fr / 1fr;
overflow: hidden;
cursor: pointer;
}
.cases__tile-image {
grid-area: 1 / 1;
width: 100%;
aspect-ratio: 4 / 3;
transition: transform 0.4s ease;
}
.cases__tile:hover .cases__tile-image {
transform: scale(1.03);
}
.cases__tile-title {
grid-area: 1 / 1;
align-self: end;
padding: 24px;
color: var(--color-white);
mix-blend-mode: difference;
z-index: 1;
line-height: 1.2;
}
@media (max-width: 768px) {
.cases__heading {
margin-bottom: 32px;
}
.cases__tile-title {
padding: 16px;
font-size: 16px;
}
}

89
src/css/components.css Normal file
View File

@@ -0,0 +1,89 @@
.btn {
display: inline-block;
font-family: var(--font-body);
font-size: 14px;
font-weight: 400;
letter-spacing: 0.05em;
text-transform: uppercase;
padding: 14px 32px;
border-radius: var(--btn-radius);
border: 1.5px solid transparent;
cursor: pointer;
transition: background-color 0.2s, color 0.2s, border-color 0.2s;
text-align: center;
}
.btn--primary {
background-color: var(--color-dark);
color: var(--color-white);
border-color: var(--color-dark);
}
.btn--primary:hover {
background-color: transparent;
color: var(--color-dark);
}
.btn--outline {
background-color: transparent;
color: var(--color-dark);
border-color: var(--color-dark);
}
.btn--outline:hover {
background-color: var(--color-dark);
color: var(--color-white);
}
.btn--light {
background-color: var(--color-white);
color: var(--color-dark);
border-color: var(--color-white);
}
.btn--light:hover {
background-color: transparent;
color: var(--color-white);
}
.hairline {
width: 1px;
background-color: var(--color-dark);
opacity: 0.3;
}
.hairline--h {
width: 100%;
height: 1px;
}
.annotation {
position: relative;
padding-left: 16px;
}
.annotation::before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 1px;
background-color: var(--color-dark);
opacity: 0.3;
}
.annotation__label {
font-family: var(--font-body);
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.1em;
opacity: 0.5;
margin-bottom: 4px;
}
.annotation__text {
font-family: var(--font-body);
font-size: 13px;
line-height: 1.4;
}

31
src/css/footer.css Normal file
View File

@@ -0,0 +1,31 @@
.footer {
padding: 40px 0;
border-top: 1px solid rgba(26, 26, 26, 0.15);
}
.footer__inner {
display: flex;
align-items: center;
justify-content: space-between;
}
.footer__copy,
.footer__telegram,
.footer__privacy {
font-family: var(--font-body);
font-size: 13px;
opacity: 0.5;
}
.footer__telegram:hover,
.footer__privacy:hover {
opacity: 0.8;
}
@media (max-width: 768px) {
.footer__inner {
flex-direction: column;
gap: 12px;
text-align: center;
}
}

76
src/css/grid.css Normal file
View File

@@ -0,0 +1,76 @@
.container {
width: 100%;
max-width: var(--grid-max);
margin: 0 auto;
padding: 0 var(--grid-margin);
}
.grid {
display: grid;
grid-template-columns: repeat(var(--grid-columns), 1fr);
gap: var(--grid-gutter);
}
/* Column span utilities */
.col-span-1 { grid-column: span 1; }
.col-span-2 { grid-column: span 2; }
.col-span-3 { grid-column: span 3; }
.col-span-4 { grid-column: span 4; }
.col-span-5 { grid-column: span 5; }
.col-span-6 { grid-column: span 6; }
.col-span-7 { grid-column: span 7; }
.col-span-8 { grid-column: span 8; }
.col-span-9 { grid-column: span 9; }
.col-span-10 { grid-column: span 10; }
.col-span-11 { grid-column: span 11; }
.col-span-12 { grid-column: span 12; }
/* Column start utilities */
.col-start-1 { grid-column-start: 1; }
.col-start-2 { grid-column-start: 2; }
.col-start-3 { grid-column-start: 3; }
.col-start-4 { grid-column-start: 4; }
.col-start-5 { grid-column-start: 5; }
.col-start-6 { grid-column-start: 6; }
.col-start-7 { grid-column-start: 7; }
.col-start-8 { grid-column-start: 8; }
.col-start-9 { grid-column-start: 9; }
.col-start-10 { grid-column-start: 10; }
.col-start-11 { grid-column-start: 11; }
.col-start-12 { grid-column-start: 12; }
@media (max-width: 768px) {
.container {
padding: 0 var(--grid-margin);
}
.col-span-1,
.col-span-2,
.col-span-3,
.col-span-4,
.col-span-5,
.col-span-6,
.col-span-7,
.col-span-8,
.col-span-9,
.col-span-10,
.col-span-11,
.col-span-12 {
grid-column: span 4;
}
.col-start-1,
.col-start-2,
.col-start-3,
.col-start-4,
.col-start-5,
.col-start-6,
.col-start-7,
.col-start-8,
.col-start-9,
.col-start-10,
.col-start-11,
.col-start-12 {
grid-column-start: 1;
}
}

59
src/css/header.css Normal file
View File

@@ -0,0 +1,59 @@
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
height: var(--header-height);
background-color: rgba(231, 242, 234, 0.85);
border-bottom: 1px solid rgba(26, 26, 26, 0.1);
transition: backdrop-filter 0.3s;
}
.header--scrolled {
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
.header__inner {
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
}
.header__wordmark {
font-family: var(--font-headline);
font-weight: 900;
font-stretch: 125%;
font-size: 14px;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.header__nav {
display: flex;
gap: 32px;
}
.header__link {
font-family: var(--font-body);
font-size: 13px;
letter-spacing: 0.03em;
opacity: 0.7;
transition: opacity 0.2s;
}
.header__link:hover {
opacity: 1;
}
@media (max-width: 768px) {
.header__nav {
gap: 16px;
}
.header__link {
font-size: 12px;
}
}

72
src/css/hero.css Normal file
View File

@@ -0,0 +1,72 @@
.hero {
min-height: 100vh;
display: flex;
align-items: center;
padding-top: var(--header-height);
padding-bottom: 80px;
}
.hero__inner {
align-items: start;
row-gap: 60px;
}
.hero__headline-block {
display: flex;
flex-direction: column;
gap: 32px;
padding-top: 80px;
}
.hero__title {
max-width: 600px;
}
.hero__subtitle {
max-width: 420px;
opacity: 0.7;
}
.hero__editorial {
display: flex;
align-items: center;
justify-content: center;
padding-top: 80px;
}
.hero__image-placeholder {
width: 100%;
aspect-ratio: 3 / 4;
background-color: var(--color-primary);
max-height: 500px;
}
.hero__annotations {
display: flex;
gap: 40px;
}
@media (max-width: 768px) {
.hero {
min-height: auto;
padding-top: calc(var(--header-height) + 40px);
padding-bottom: 60px;
}
.hero__headline-block {
padding-top: 40px;
}
.hero__editorial {
padding-top: 0;
}
.hero__image-placeholder {
max-height: 300px;
}
.hero__annotations {
flex-direction: column;
gap: 24px;
}
}

73
src/css/journal.css Normal file
View File

@@ -0,0 +1,73 @@
.journal {
padding: var(--section-gap) 0;
position: relative;
overflow: hidden;
}
.journal::after {
content: attr(data-number);
position: absolute;
top: -40px;
right: 5%;
font-family: var(--font-headline);
font-weight: 900;
font-stretch: 125%;
font-size: clamp(200px, 30vw, 400px);
line-height: 1;
color: var(--color-dark);
opacity: 0.04;
pointer-events: none;
z-index: 0;
}
.journal__inner {
position: relative;
z-index: 1;
align-items: end;
}
.journal__image-block {
overflow: hidden;
}
.journal__image-placeholder {
width: 100%;
height: 500px;
background-color: var(--color-surface);
object-fit: cover;
}
.journal__text-block {
display: flex;
flex-direction: column;
gap: 20px;
align-self: end;
}
.journal__body {
opacity: 0.7;
}
.journal__buttons {
display: flex;
gap: 16px;
margin-top: 12px;
}
@media (max-width: 768px) {
.journal__image-placeholder {
height: 300px;
}
.journal__text-block {
align-self: start;
}
.journal__buttons {
flex-direction: column;
}
.journal__buttons .btn {
text-align: center;
}
}

39
src/css/manifest.css Normal file
View File

@@ -0,0 +1,39 @@
.manifest {
padding: var(--section-gap) 0;
}
.manifest__inner {
align-items: start;
}
.manifest__text {
display: flex;
flex-direction: column;
gap: 28px;
}
.manifest__heading {
color: var(--color-dark);
}
.manifest__body {
opacity: 0.7;
max-width: 400px;
}
.manifest__caption {
text-align: right;
padding-top: 8px;
}
.manifest__caption .caption {
opacity: 0.5;
}
@media (max-width: 768px) {
.manifest__caption {
text-align: left;
order: -1;
margin-bottom: 16px;
}
}

61
src/css/reset.css Normal file
View File

@@ -0,0 +1,61 @@
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
-moz-text-size-adjust: none;
-webkit-text-size-adjust: none;
text-size-adjust: none;
scroll-behavior: smooth;
}
body {
min-height: 100vh;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
img,
picture,
video,
svg {
display: block;
max-width: 100%;
}
input,
button,
textarea,
select {
font: inherit;
}
h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
font-weight: normal;
}
a {
color: inherit;
text-decoration: none;
}
ul, ol {
list-style: none;
}
details summary {
cursor: pointer;
}
details summary::-webkit-details-marker {
display: none;
}
details summary::marker {
content: '';
}

150
src/css/services.css Normal file
View File

@@ -0,0 +1,150 @@
.services {
padding: var(--section-gap) 0;
}
.services__heading {
margin-bottom: 48px;
}
.services__item {
border-top: 1px solid rgba(26, 26, 26, 0.2);
}
.services__item:last-of-type {
border-bottom: 1px solid rgba(26, 26, 26, 0.2);
}
.services__summary {
display: flex;
align-items: center;
gap: 24px;
padding: 24px 0;
list-style: none;
user-select: none;
}
.services__number {
font-family: var(--font-body);
font-size: 13px;
opacity: 0.4;
min-width: 28px;
}
.services__title {
font-family: var(--font-headline);
font-size: clamp(16px, 1.5vw, 20px);
font-weight: 900;
font-stretch: 125%;
text-transform: uppercase;
flex: 1;
}
.services__icon {
font-size: 24px;
font-weight: 300;
opacity: 0.5;
transition: transform 0.3s;
}
.services__item[open] .services__icon {
transform: rotate(45deg);
}
.services__content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 40px;
padding: 8px 0 40px 52px;
}
.services__section {
margin-bottom: 24px;
}
.services__section-title {
font-family: var(--font-body);
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.1em;
opacity: 0.5;
margin-bottom: 12px;
}
.services__list {
display: flex;
flex-direction: column;
gap: 6px;
}
.services__list li {
font-family: var(--font-body);
font-size: 14px;
line-height: 1.5;
padding-left: 12px;
position: relative;
}
.services__list li::before {
content: '\2022';
position: absolute;
left: 0;
opacity: 0.4;
}
.services__steps {
display: flex;
flex-direction: column;
gap: 8px;
counter-reset: step;
}
.services__steps li {
font-family: var(--font-body);
font-size: 14px;
line-height: 1.5;
padding-left: 20px;
position: relative;
counter-increment: step;
}
.services__steps li::before {
content: counter(step) '.';
position: absolute;
left: 0;
opacity: 0.5;
}
.services__cta {
margin-top: 8px;
}
.services__footer {
margin-top: 60px;
display: flex;
flex-direction: column;
gap: 16px;
align-items: flex-start;
}
.services__footer-text {
opacity: 0.7;
max-width: 500px;
}
@media (max-width: 768px) {
.services__block {
grid-column: span 4;
grid-column-start: 1;
}
.services__content {
grid-template-columns: 1fr;
gap: 24px;
padding-left: 0;
}
.services__summary {
gap: 12px;
padding: 20px 0;
}
}

60
src/css/tokens.css Normal file
View File

@@ -0,0 +1,60 @@
:root {
/* Colors */
--color-primary: #007DDA;
--color-bg: #E7F2EA;
--color-surface: #FCC3C3;
--color-ink: #BD5E24;
--color-accent: #FB9322;
--color-dark: #1A1A1A;
--color-white: #FFFFFF;
/* Typography — Families */
--font-headline: 'Archivo', sans-serif;
--font-body: 'Inter', sans-serif;
/* Typography — Sizes (Desktop) */
--h1-size: clamp(32px, 4vw, 48px);
--h1-lh: 40px;
--h2-size: clamp(24px, 2.5vw, 31px);
--h2-lh: 30px;
--h3-size: clamp(18px, 2vw, 24px);
--h3-lh: 20px;
--body-size: 16px;
--body-lh: 18px;
--caption-size: 16px;
--caption-lh: 44px;
/* Grid */
--grid-columns: 12;
--grid-container: 1200px;
--grid-max: 1424px;
--grid-gutter: 32px;
--grid-margin: 96px;
/* Spacing */
--section-gap: clamp(120px, 15vw, 220px);
--headline-spacing: 160px;
/* Misc */
--btn-radius: 3px;
--header-height: 64px;
}
@media (max-width: 768px) {
:root {
--h1-size: 32px;
--h1-lh: 40px;
--h2-size: 34px;
--h2-lh: 30px;
--h3-size: 20px;
--h3-lh: 80px;
--body-size: 16px;
--body-lh: 14px;
--caption-size: 14px;
--caption-lh: 12px;
--grid-columns: 4;
--grid-gutter: 16px;
--grid-margin: 20px;
}
}

75
src/main.js Normal file
View File

@@ -0,0 +1,75 @@
import './style.css'
function initScrollReveal() {
const supportsScrollDriven = CSS.supports('animation-timeline', 'view()')
if (supportsScrollDriven) {
document.documentElement.classList.add('has-scroll-driven')
return
}
const reveals = document.querySelectorAll('[data-reveal]')
if (!reveals.length) return
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible')
observer.unobserve(entry.target)
}
})
},
{ threshold: 0.15 }
)
reveals.forEach((el) => observer.observe(el))
}
function initSmoothScroll() {
document.querySelectorAll('a[href^="#"]').forEach((anchor) => {
anchor.addEventListener('click', (e) => {
const targetId = anchor.getAttribute('href')
if (targetId === '#') return
const target = document.querySelector(targetId)
if (!target) return
e.preventDefault()
const headerOffset = parseInt(
getComputedStyle(document.documentElement)
.getPropertyValue('--header-height'),
10
)
const top = target.getBoundingClientRect().top + window.scrollY - headerOffset - 20
window.scrollTo({ top, behavior: 'smooth' })
})
})
}
function initHeaderScroll() {
const header = document.getElementById('header')
if (!header) return
let ticking = false
window.addEventListener(
'scroll',
() => {
if (!ticking) {
requestAnimationFrame(() => {
header.classList.toggle('header--scrolled', window.scrollY > 100)
ticking = false
})
ticking = true
}
},
{ passive: true }
)
}
document.addEventListener('DOMContentLoaded', () => {
initScrollReveal()
initSmoothScroll()
initHeaderScroll()
})

13
src/style.css Normal file
View File

@@ -0,0 +1,13 @@
@import './css/reset.css';
@import './css/tokens.css';
@import './css/base.css';
@import './css/grid.css';
@import './css/components.css';
@import './css/header.css';
@import './css/hero.css';
@import './css/manifest.css';
@import './css/journal.css';
@import './css/cases.css';
@import './css/services.css';
@import './css/footer.css';
@import './css/animations.css';