commit d6ee21c9d73fceacc55016f5ff7e40a06d063744 Author: idchlife Date: Thu Feb 5 18:09:28 2026 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9d04925 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +!**/glob-import/dir/node_modules +.DS_Store +.idea +.pnpm-store +*.cpuprofile +*.local +*.log +/.vscode/ +/docs/.vitepress/cache +/docs/.vitepress/.temp +/packages/vite/LICENSE +dist +dist-ssr +explorations +node_modules +playground-temp +temp +TODOs.md +.eslintcache diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d2c86ee --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,55 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +A brutalist editorial landing page for Alina Mamut, a brand strategy and creative consulting professional. The site is a premium magazine-style single-page website showcasing four service offerings, with content primarily in Russian. + +**Status**: Pre-development — only `PLANNING.md` (content + design specs) and `design-spec.jpg` (visual spec) exist. No framework or build tooling has been chosen yet. + +## Design System + +Strict visual identity — do not deviate from these values. + +**Typography**: +- Headlines: **Druk Wide Bold** (tight line-height ~0.9) +- Body: **Inter Regular** only — no medium/bold weights for body text +- Desktop: H1 48px/40px, H2 31px/30px, H3 24px/20px, Body 16px/18px, Caption 16px/44px +- Mobile: H1 32px/40px, H2 34px/30px, H3 20px/80px, Body 16px/14px, Caption 14px/12px + +**Color palette** (flat only — no gradients, shadows, or cards): +| Name | Hex | +|------|-----| +| Blue | `#007DDA` | +| Warm White | `#E7F2EA` | +| Stone Grey | `#FCC3C3` | +| Ink Black | `#BD5E24` | +| Oxide Red | `#FB9322` | + +**Grid**: +- Desktop: 12 columns, 1200px container, 1424px max-width, 32px gutters +- Mobile: 4 columns, 20px margins +- Vertical spacing between sections: 160–220px + +**Design don'ts**: No phone mockups, no SaaS/startup patterns, no subscription-style UI, no shadowed text, no icons, pills, or card components. + +## Page Structure (5 Screens) + +1. **Hero** — Massive left-aligned headline (~7 cols), smartphone mockup center-right (~4 cols), small editorial annotations with thin hairline connectors, primary CTA +2. **Manifest** — Asymmetric layout, large text block (5 cols), opposite side mostly empty with small caption +3. **Journal Preview** — Large image breaking grid (~7 cols), offset text block (~4 cols), oversized faded number in background +4. **Selected Cases** — Dark background, 2×2 editorial image tiles (6 cols each), overlapping titles +5. **Access/FAQ** — Editorial accordion (8 cols centered), numbered thin rows, one-at-a-time expand behavior + +**Header**: Minimal sticky nav — wordmark left, text anchors right. Buttons: rectangular, 2–4px border-radius. + +## Content + +All service descriptions and UI copy are in Russian (see `PLANNING.md` for full text). Four service sections expand via accordion: +1. Creative & strategy consultations +2. Brand platform development +3. Communication strategies +4. Special projects & creative concepts + +CTA directs to Telegram: @alinamamut diff --git a/IMPLEMENTATION.md b/IMPLEMENTATION.md new file mode 100644 index 0000000..8db66d6 --- /dev/null +++ b/IMPLEMENTATION.md @@ -0,0 +1,43 @@ +# Implementation Summary + +## Tech Stack +- **Vite 6** + Vanilla HTML/CSS/JS (no framework) +- **Archivo** (Google Fonts, expanded width, weight 900) for headlines +- **Inter** (Google Fonts, weight 400) for body text + +## Project Structure +``` +├── index.html # Single page with all 5 screens +├── package.json +├── vite.config.js +├── public/ +├── src/ +│ ├── main.js # Scroll reveal, smooth scroll, header scroll +│ ├── style.css # Master @import file +│ ├── css/ +│ │ ├── reset.css # Modern CSS reset +│ │ ├── tokens.css # Design tokens (colors, type, spacing, grid) +│ │ ├── base.css # Typography classes (.h1, .h2, .h3) +│ │ ├── grid.css # 12-col grid + utilities +│ │ ├── components.css # Buttons, annotations, hairlines +│ │ ├── header.css # Sticky header +│ │ ├── hero.css # Screen 1 +│ │ ├── manifest.css # Screen 2 +│ │ ├── journal.css # Screen 3 +│ │ ├── cases.css # Screen 4 +│ │ ├── services.css # Screen 5 (accordion) +│ │ ├── footer.css +│ │ └── animations.css # Scroll-driven + IntersectionObserver fallback +│ └── assets/ +``` + +## Running +- `npm run dev` — development server with HMR +- `npm run build` — production build to `dist/` +- `npm run preview` — preview production build + +## Design Decisions +- Native `
` for one-at-a-time accordion (zero JS) +- CSS `animation-timeline: view()` with IntersectionObserver fallback +- Colored placeholder blocks instead of images (swap with `` later) +- BEM-lite class naming diff --git a/PLANNING.md b/PLANNING.md new file mode 100644 index 0000000..cda7c71 --- /dev/null +++ b/PLANNING.md @@ -0,0 +1,142 @@ +Here is the plan, that needs to be done, combining several inputs and tasks. + +# Initial goal, reasoning and explanation of pages (in Russian): + +Раздел 1: +1. Консультации по креативу и стратегии + +Выпадающий текст: +Когда это нужно + • Бренд чувствует, что коммуникации устарели; + • Идеи есть, но они не складываются в систему и, главное, не приносят результат; + • Команда не понимает, куда двигаться дальше; + • Нужно свежее, независимое видение. + +Что вы получаете + • Разбор текущей коммуникации бренда; + • Анализ визуального языка и смыслов; + • Точки роста и возможности для отстройки; + • Направления для креатива и спецпроектов. + +Как происходит работа: + 1. Оперативный созвон-знакомство, вы заполняете бриф, по которому я готовлюсь к консультации; + 2. 2-часовая консультация; + 3. Презентация с рекомендациями и планом работ. + +⸻ +Раздел 2: +2. Бренд-платформа + +Выпадающий текст: +Когда это нужно + • Проект не растет, нет клиентов; + • Коммуникации выглядят разрозненно; + • Нет четкого позиционирования и голоса; + • Нет понимания, кто аудитория проекта; + • Сложно масштабировать маркетинг. + +Что вы получаете + • Ядро бренда: аудитория, конкуренты, миссия, ценности, характер; + • Чёткое позиционирование и big idea; + • Tone of voice и визуальные принципы; + • Основу для всех коммуникаций. + +Как происходит работа: + 1. Оперативный созвон-знакомство, вы заполняете бриф; + 2. 2-4 недели разработки бренд-платформы – анализ аудитории и конкурентов, интервью с основателем (при необходимости с командой и клиентами/потенциальными клиентами); + 3. Презентация с готовой бренд-платформой. + +⸻ +Раздел 3: +3. Коммуникационные стратегии + +Выпадающий текст: +Когда это нужно + • Бренд хочет выйти за рамки стандартной рекламы; + • Нужно привлечь новую аудиторию; + • Конкуренты выглядят ярче и смелее; + • Нет ясного сценария развития коммуникаций. + +Что вы получаете + • Стратегию коммуникаций на основе трендов и инсайтов; + • Ключевые смыслы и сообщения бренда; + • Идеи форматов, контента и спецпроектов; + • Дорожную карту – для кого, в каком канале, что необходимо сделать. + +Как происходит работа: + 1. Оперативный созвон-знакомство, вы заполняете бриф; + 2. 2-4 недели разработки коммуникационной стратегии – анализ аудитории и коммуникации конкурентов, анализ лучших релевантных зарубежных и локальных практик; + 3. Презентация с готовой коммуникационной стратегией. +⸻ + +Раздел 4: +4. Идеи спецпроектов и креативные концепции + +Выпадающий текст: +Когда это нужно + • Бренд хочет вау-эффект без банальных решений; + • Нужна идея, которую будут обсуждать; + • Важно выйти за рамки стандартных форматов. + +Что вы получаете + • Концепции спецпроектов; + • Сценарии интеграций и коллабораций; + • Решения, которые можно масштабировать. + +Как происходит работа: + 1. Оперативный созвон-знакомство, вы заполняете бриф; + 2. 2-3 недели разработки идеи – сбор референс, анализ лучших практик, подготовка идеи; + 3. Презентация с готовой коммуникационной стратегией. + +Далее колл-ту-экшен: +Я могу как разработать идею, так и взять на себя всю реализацию при помощи мой команды профессионалов. + +Чтобы ознакомиться с моим портфолио и реализованными кейсами, пожалуйста, напишите мне: @alinamamut + +Внизу подвал с политикой конфиденциальности и тд + +*** +По арт-дирекшену: +1. Шрифт заголовков – Druk Wide Bold +2. Шрифт основного текста – Inter Regular +3. Сверстать необходимо по референту – в том же стиле, что и в файле + +# WebPage coding prompt that was generated by some LLM: + +Create a premium editorial landing page for a cultural trend journal. The design must feel like a high-end magazine, not a startup. Style: brutal typography, strong grid, oversized type, large negative space, minimal color, zero friendly marketing patterns. + +Grid: desktop 12 columns, container 1280px, max-width 1560px, gutter 32px, outer margins 96px. Vertical spacing 160–220px. Mobile: 4 columns, 20px margins. + +Typography: Headlines similar to Druk Wide Bold. Body Inter Regular only. No medium weights. Massive scale contrast. Tight line-height for headers (~0.9). Large readable body (~20–22px desktop). + +Color palette: warm white (#F7F7F5), ink black (#0A0A0A), oxide red (#B3342B), dusty blue (#6F8FA6), stone grey (#D9D9D6). Flat colors only. No gradients. + +⸻ + +Screen 1 — Hero + +Massive left-aligned headline spanning ~7 columns. Center-right smartphone mockup (~4 columns). 3–4 small editorial annotations with thin hairline connector lines. Primary button below headline. Leave 30–40% empty space. + +Screen 2 — Manifest + +Asymmetric layout. Large intellectual text block (5 columns). Opposite side mostly empty with a small caption in the top corner. + +Screen 3 — Journal Preview + +Large issue image breaking grid (~7 columns). Text block offset vertically (~4 columns). Oversized faded issue number in background. Two buttons: primary + outline. + +Screen 4 — Selected Cases + +Dark background. 2×2 editorial tiles (6 columns each). No cards, no shadows. Image-led with overlapping titles. + +Screen 5 — Access + +Editorial accordion centered in grid (8 columns). Closed: thin rows with numbers. Open: split text + button. One item open at a time. + +Header: minimal sticky nav with wordmark left, text anchors right. +Buttons: rectangular, 2–4px radius. +Avoid icons, cards, gradients, pills, and SaaS visuals. Make it intellectual, cultural, and expensive. + +# Additional DESIGN specification + +Local file called design-spec.jpg diff --git a/design-spec.jpg b/design-spec.jpg new file mode 100644 index 0000000..7fdfbbe Binary files /dev/null and b/design-spec.jpg differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..e8f2b88 --- /dev/null +++ b/index.html @@ -0,0 +1,307 @@ + + + + + + Alina Mamut — Бренд-стратегия и креативный консалтинг + + + + + + + + + + + + + + + +
+
+
+

Бренд-стратегия
и креативный
консалтинг

+

Помогаю брендам находить свой голос, формировать стратегию и создавать коммуникации, которые работают.

+ Написать в Telegram +
+
+
+
+
+
+
Опыт
+
10+ лет в брендинге и стратегии
+
+
+
Подход
+
Исследования, аналитика, креатив
+
+
+
Результат
+
Система, а не разовые решения
+
+
+
+
+ + +
+
+
+

Я верю, что сильный бренд — это не логотип и не визуал. Это стратегия, смыслы и последовательность.

+

Каждый проект начинается с глубокого понимания: кто вы, для кого вы и зачем вы существуете. Я нахожу ответы, которые становятся основой для всех ваших коммуникаций — от позиционирования до рекламных кампаний.

+
+
+ О подходе +
+
+
+ + +
+
+
+
+
+
+

Стратегия — это не документ. Это способ думать о бренде каждый день.

+

Результат моей работы — не просто презентация на 50 слайдов. Это живой инструмент, который помогает принимать решения, формировать контент и развивать бренд осознанно.

+ +
+
+
+ + +
+
+

Избранные кейсы

+
+
+
+

Ребрендинг и стратегия коммуникаций

+
+
+
+

Бренд-платформа с нуля

+
+
+
+

Креативная концепция спецпроекта

+
+
+
+

Коммуникационная стратегия

+
+
+
+
+ + +
+
+
+

Услуги

+ + +
+ + 01 + Консультации по креативу и стратегии + + + +
+
+
+

Когда это нужно

+
    +
  • Бренд чувствует, что коммуникации устарели;
  • +
  • Идеи есть, но они не складываются в систему и, главное, не приносят результат;
  • +
  • Команда не понимает, куда двигаться дальше;
  • +
  • Нужно свежее, независимое видение.
  • +
+
+
+

Что вы получаете

+
    +
  • Разбор текущей коммуникации бренда;
  • +
  • Анализ визуального языка и смыслов;
  • +
  • Точки роста и возможности для отстройки;
  • +
  • Направления для креатива и спецпроектов.
  • +
+
+
+
+
+

Как происходит работа

+
    +
  1. Оперативный созвон-знакомство, вы заполняете бриф, по которому я готовлюсь к консультации;
  2. +
  3. 2-часовая консультация;
  4. +
  5. Презентация с рекомендациями и планом работ.
  6. +
+
+ Записаться +
+
+
+ + +
+ + 02 + Бренд-платформа + + + +
+
+
+

Когда это нужно

+
    +
  • Проект не растет, нет клиентов;
  • +
  • Коммуникации выглядят разрозненно;
  • +
  • Нет четкого позиционирования и голоса;
  • +
  • Нет понимания, кто аудитория проекта;
  • +
  • Сложно масштабировать маркетинг.
  • +
+
+
+

Что вы получаете

+
    +
  • Ядро бренда: аудитория, конкуренты, миссия, ценности, характер;
  • +
  • Чёткое позиционирование и big idea;
  • +
  • Tone of voice и визуальные принципы;
  • +
  • Основу для всех коммуникаций.
  • +
+
+
+
+
+

Как происходит работа

+
    +
  1. Оперативный созвон-знакомство, вы заполняете бриф;
  2. +
  3. 2-4 недели разработки бренд-платформы — анализ аудитории и конкурентов, интервью с основателем (при необходимости с командой и клиентами/потенциальными клиентами);
  4. +
  5. Презентация с готовой бренд-платформой.
  6. +
+
+ Записаться +
+
+
+ + +
+ + 03 + Коммуникационные стратегии + + + +
+
+
+

Когда это нужно

+
    +
  • Бренд хочет выйти за рамки стандартной рекламы;
  • +
  • Нужно привлечь новую аудиторию;
  • +
  • Конкуренты выглядят ярче и смелее;
  • +
  • Нет ясного сценария развития коммуникаций.
  • +
+
+
+

Что вы получаете

+
    +
  • Стратегию коммуникаций на основе трендов и инсайтов;
  • +
  • Ключевые смыслы и сообщения бренда;
  • +
  • Идеи форматов, контента и спецпроектов;
  • +
  • Дорожную карту — для кого, в каком канале, что необходимо сделать.
  • +
+
+
+
+
+

Как происходит работа

+
    +
  1. Оперативный созвон-знакомство, вы заполняете бриф;
  2. +
  3. 2-4 недели разработки коммуникационной стратегии — анализ аудитории и коммуникации конкурентов, анализ лучших релевантных зарубежных и локальных практик;
  4. +
  5. Презентация с готовой коммуникационной стратегией.
  6. +
+
+ Записаться +
+
+
+ + +
+ + 04 + Идеи спецпроектов и креативные концепции + + + +
+
+
+

Когда это нужно

+
    +
  • Бренд хочет вау-эффект без банальных решений;
  • +
  • Нужна идея, которую будут обсуждать;
  • +
  • Важно выйти за рамки стандартных форматов.
  • +
+
+
+

Что вы получаете

+
    +
  • Концепции спецпроектов;
  • +
  • Сценарии интеграций и коллабораций;
  • +
  • Решения, которые можно масштабировать.
  • +
+
+
+
+
+

Как происходит работа

+
    +
  1. Оперативный созвон-знакомство, вы заполняете бриф;
  2. +
  3. 2-3 недели разработки идеи — сбор референс, анализ лучших практик, подготовка идеи;
  4. +
  5. Презентация с готовой креативной концепцией.
  6. +
+
+ Записаться +
+
+
+ + +
+
+
+ + + + + + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..baac288 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1104 @@ +{ + "name": "alina-design-website", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "alina-design-website", + "version": "1.0.0", + "devDependencies": { + "vite": "^6.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", + "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", + "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", + "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", + "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", + "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", + "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", + "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", + "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", + "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", + "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", + "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", + "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", + "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", + "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", + "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", + "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", + "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", + "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", + "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", + "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", + "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", + "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", + "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", + "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", + "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.57.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", + "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.57.1", + "@rollup/rollup-android-arm64": "4.57.1", + "@rollup/rollup-darwin-arm64": "4.57.1", + "@rollup/rollup-darwin-x64": "4.57.1", + "@rollup/rollup-freebsd-arm64": "4.57.1", + "@rollup/rollup-freebsd-x64": "4.57.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", + "@rollup/rollup-linux-arm-musleabihf": "4.57.1", + "@rollup/rollup-linux-arm64-gnu": "4.57.1", + "@rollup/rollup-linux-arm64-musl": "4.57.1", + "@rollup/rollup-linux-loong64-gnu": "4.57.1", + "@rollup/rollup-linux-loong64-musl": "4.57.1", + "@rollup/rollup-linux-ppc64-gnu": "4.57.1", + "@rollup/rollup-linux-ppc64-musl": "4.57.1", + "@rollup/rollup-linux-riscv64-gnu": "4.57.1", + "@rollup/rollup-linux-riscv64-musl": "4.57.1", + "@rollup/rollup-linux-s390x-gnu": "4.57.1", + "@rollup/rollup-linux-x64-gnu": "4.57.1", + "@rollup/rollup-linux-x64-musl": "4.57.1", + "@rollup/rollup-openbsd-x64": "4.57.1", + "@rollup/rollup-openharmony-arm64": "4.57.1", + "@rollup/rollup-win32-arm64-msvc": "4.57.1", + "@rollup/rollup-win32-ia32-msvc": "4.57.1", + "@rollup/rollup-win32-x64-gnu": "4.57.1", + "@rollup/rollup-win32-x64-msvc": "4.57.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/vite": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c5bad64 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "alina-design-website", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "vite": "^6.0.0" + } +} diff --git a/src/css/animations.css b/src/css/animations.css new file mode 100644 index 0000000..c27b091 --- /dev/null +++ b/src/css/animations.css @@ -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); + } +} diff --git a/src/css/base.css b/src/css/base.css new file mode 100644 index 0000000..caf4d05 --- /dev/null +++ b/src/css/base.css @@ -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; +} diff --git a/src/css/cases.css b/src/css/cases.css new file mode 100644 index 0000000..4c7ed32 --- /dev/null +++ b/src/css/cases.css @@ -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; + } +} diff --git a/src/css/components.css b/src/css/components.css new file mode 100644 index 0000000..73324a3 --- /dev/null +++ b/src/css/components.css @@ -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; +} diff --git a/src/css/footer.css b/src/css/footer.css new file mode 100644 index 0000000..5280070 --- /dev/null +++ b/src/css/footer.css @@ -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; + } +} diff --git a/src/css/grid.css b/src/css/grid.css new file mode 100644 index 0000000..966dcb5 --- /dev/null +++ b/src/css/grid.css @@ -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; + } +} diff --git a/src/css/header.css b/src/css/header.css new file mode 100644 index 0000000..74a0b30 --- /dev/null +++ b/src/css/header.css @@ -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; + } +} diff --git a/src/css/hero.css b/src/css/hero.css new file mode 100644 index 0000000..a14e400 --- /dev/null +++ b/src/css/hero.css @@ -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; + } +} diff --git a/src/css/journal.css b/src/css/journal.css new file mode 100644 index 0000000..ac3bc50 --- /dev/null +++ b/src/css/journal.css @@ -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; + } +} diff --git a/src/css/manifest.css b/src/css/manifest.css new file mode 100644 index 0000000..416b769 --- /dev/null +++ b/src/css/manifest.css @@ -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; + } +} diff --git a/src/css/reset.css b/src/css/reset.css new file mode 100644 index 0000000..369df56 --- /dev/null +++ b/src/css/reset.css @@ -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: ''; +} diff --git a/src/css/services.css b/src/css/services.css new file mode 100644 index 0000000..e5a20ae --- /dev/null +++ b/src/css/services.css @@ -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; + } +} diff --git a/src/css/tokens.css b/src/css/tokens.css new file mode 100644 index 0000000..5239d81 --- /dev/null +++ b/src/css/tokens.css @@ -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; + } +} diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..d84a82e --- /dev/null +++ b/src/main.js @@ -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() +}) diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..f62ae73 --- /dev/null +++ b/src/style.css @@ -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'; diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..ced2f9d --- /dev/null +++ b/vite.config.js @@ -0,0 +1,9 @@ +import { defineConfig } from 'vite' + +export default defineConfig({ + root: '.', + publicDir: 'public', + build: { + outDir: 'dist', + }, +})