# FERMENKOL — Social Media Landing Page

Production-ready landing page with email template and Bitrix integration.

## Stack

| Tool | Purpose |
|------|---------|
| Vite 6 | Build tool + dev server |
| SCSS | Styles (BEM methodology) |
| PostCSS + Autoprefixer | Cross-browser CSS |
| ESLint 9 | JavaScript linting |
| Stylelint | SCSS linting |
| Prettier | Code formatting |
| Vite HTML partials plugin | Section-based HTML composition (`{{> section }}`) |

---

## Quick Start

### Prerequisites

- **Node.js** >= 18
- **pnpm** >= 8

```bash
# Install dependencies
pnpm install

# Start dev server
pnpm dev

# Open http://localhost:5173
```

### Build for production

```bash
pnpm build
```

Output goes to `dist/`.

### Preview production build

```bash
pnpm preview
```

---

## Scripts

| Command | Description |
|---------|-------------|
| `pnpm dev` | Start dev server with HMR |
| `pnpm build` | Build for production (minified, optimized) |
| `pnpm preview` | Preview production build locally |
| `pnpm lint` | Run ESLint + Stylelint (check only) |
| `pnpm lint:fix` | Fix auto-fixable lint issues + format with Prettier |
| `pnpm format` | Format all code with Prettier |

---

## Project Structure

```
fermentkol-landing/
├── email/                      # Email templates (table-based)
│   └── confirmation.html       # Registration confirmation email
├── src/
│   ├── partials/                # HTML partials for page sections
│   │   ├── hero.html
│   │   ├── features.html
│   │   ├── speaker.html
│   │   ├── giveaway.html
│   │   ├── bonuses.html
│   │   ├── form-section.html
│   │   ├── faq.html
│   │   ├── footer.html
│   │   └── thank-you-modal.html
│   ├── assets/
│   │   ├── fonts/              # Web fonts (woff2)
│   │   └── images/             # Images (webp + fallback)
│   ├── js/
│   │   ├── index.js            # Entry point — initializes all modules
│   │   ├── modal.js            # Modal component (a11y, focus trap)
│   │   ├── form-handler.js     # Form validation + submit (Bitrix-ready)
│   │   └── utils.js            # Utility functions (debounce, validation)
│   └── styles/
│       ├── base/
│       │   ├── reset.scss      # CSS reset + cross-browser fixes
│       │   └── typography.scss # Typography + container + focus states
│       ├── components/
│       │   ├── _globals.scss   # Reusable button/section classes
│       │   ├── header.scss     # Header + mobile burger menu
│       │   ├── footer.scss     # Footer
│       │   └── modal.scss      # Modal overlay + content
│       ├── sections/
│       │   ├── hero.scss       # Hero section
│       │   ├── about.scss      # About section (3-column cards)
│       │   ├── features.scss   # Features/Program section (numbered list)
│       │   ├── speaker.scss    # Speaker section (photo + info)
│       │   ├── giveaway.scss   # Giveaway section (prizes + CTA)
│       │   ├── bonuses.scss    # Bonuses section (2-column grid)
│       │   ├── form-section.scss # Form section (validated form)
│       │   └── faq.scss        # FAQ accordion
│       ├── tokens.scss         # Design tokens (CSS vars + SCSS vars)
│       └── main.scss           # Main SCSS entry (imports all)
├── index.html                  # Main HTML shell with partial includes
├── vite.config.js              # Vite config (alias, SCSS injection, partials)
├── postcss.config.js           # PostCSS config (autoprefixer)
├── eslint.config.js            # ESLint flat config
├── .stylelintrc.json           # Stylelint config
├── .prettierrc                 # Prettier config
├── .browserslistrc             # Browser support targets
└── package.json
```

---

## Adding Sections

### 1. Create SCSS file

```scss
// src/styles/sections/new-section.scss
.new-section {
  padding-block: var(--space-4xl);
  background-color: var(--clr-bg-primary);

  &__container {
    max-width: var(--container-max);
    margin-inline: auto;
    padding-inline: var(--container-padding);
  }
}
```

### 2. Import in main.scss

```scss
// src/styles/main.scss
@use 'sections/new-section.scss';
```

### 3. Add HTML partial in `src/partials/`

```html
<!-- src/partials/new-section.html -->
<section class="new-section" id="newSection" aria-labelledby="newSection-title">
  <div class="new-section__container">
    <h2 class="new-section__title section-title" id="newSection-title">Title</h2>
    <!-- content -->
  </div>
</section>
```

### 4. Include partial in `index.html`

```html
{{> new-section }}
```

---

## Bitrix Integration

### Form endpoint

The form submits to `/bitrix/tools/submit.php` by default. Change it in `src/js/index.js`:

```js
const formHandler = new FormHandler({
  formSelector: '#signupForm',
  submitUrl: '/your/bitrix/endpoint.php', // <-- change this
  onSuccess: () => {
    thankYouModal.open();
  },
});
```

### Bitrix PHP endpoint example

Create `/bitrix/tools/submit.php`:

```php
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');

header('Content-Type: application/json');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
  http_response_code(405);
  echo json_encode(['success' => false, 'message' => 'Method not allowed']);
  exit;
}

$data = json_decode(file_get_contents('php://input'), true);

$name = trim($data['name'] ?? '');
$email = trim($data['email'] ?? '');
$phone = trim($data['phone'] ?? '');

// Validation
if (!$name || !$email || !$phone) {
  echo json_encode(['success' => false, 'message' => 'Required fields missing']);
  exit;
}

// Save to Bitrix IBLOCK or send email
// ... your Bitrix logic here ...

echo json_encode(['success' => true]);
```

### Form data structure

The form sends JSON:

```json
{
  "name": "Иван Иванов",
  "email": "ivan@example.com",
  "phone": "+79991234567",
  "agreement": "on"
}
```

---

## Safari / Cross-Browser Testing

### What's already handled

| Issue | Solution in code |
|-------|-----------------|
| `100vh` bug on iOS | Uses `100dvh` |
| Input styling | `-webkit-appearance: none` |
| Autofill background | `-webkit-box-shadow` inset fix |
| `backdrop-filter` | `-webkit-backdrop-filter` prefix |
| Flex gap | Supported (Safari 14.1+) |
| Font smoothing | `-webkit-font-smoothing: antialiased` |

### Testing on Safari (Windows / WSL)

1. **BrowserStack** — cloud testing for Safari on macOS/iOS
   ```
   https://www.browserstack.com/
   ```

2. **LambdaTest** — alternative cloud testing
   ```
   https://www.lambdatest.com/
   ```

3. **Local testing** — if you have access to a Mac:
   ```bash
   pnpm build
   # Copy dist/ folder to Mac and serve with:
   npx serve dist/
   ```

4. **Responsive design mode** — DevTools in Chrome/Edge:
   - Press `F12` → Toggle device toolbar
   - Select iPhone / iPad presets

---

## Email Template

### Location

```
email/confirmation.html
```

### Rules followed

- **Only tables** for layout
- **Inline styles** on every element
- **Width: 600px** (standard email width)
- **VML fallback** for Outlook buttons (MSO conditional comments)
- **No flex, no grid, no external CSS**
- **Fallback fonts**: Arial, Helvetica, sans-serif
- **Apple data detectors** disabled
- **Preview text** hidden but visible in email clients

### Testing email

1. **Putsmail** — test email rendering
   ```
   https://putsmail.com/
   ```

2. **Email on Acid** — comprehensive testing
   ```
   https://www.emailonacid.com/
   ```

3. **Litmus** — professional email testing
   ```
   https://litmus.com/
   ```

### How to use

1. Copy `email/confirmation.html` to your email sending service
2. Replace placeholder URLs (`https://example.com/...`) with actual links
3. Replace dynamic content (date, time, name) with your template engine variables
4. Send as HTML email

---

## Design Tokens

All colors, spacing, typography, and breakpoints are centralized in:

```
src/styles/tokens.scss
```

### Colors

```scss
--clr-primary: #6C5CE7;       // Main brand
--clr-accent: #00CEC9;        // Accent
--clr-dark: #1A1A2E;          // Dark background
--clr-success: #00B894;       // Success state
--clr-error: #E17055;         // Error state
```

### Breakpoints

```scss
--bp-xl: 1920px;    // Large desktop
--bp-lg: 1440px;    // Desktop
--bp-md: 992px;     // Tablet landscape
--bp-sm: 768px;     // Tablet portrait
--bp-xs: 576px;     // Large phone
--bp-xxs: 360px;    // Small phone
```

---

## Accessibility (a11y)

### Implemented

- `aria-label` on navigation, logo, modal
- `aria-expanded` on FAQ accordion and burger menu
- `aria-controls` linking buttons to content
- `aria-describedby` on form inputs
- `role="alert"` on form error messages
- `role="dialog"` + `aria-modal="true"` on modal
- Focus trap inside modal
- Focus restoration after modal close
- `:focus-visible` styles (keyboard-only)
- Semantic HTML (`<header>`, `<main>`, `<section>`, `<nav>`, `<footer>`)
- `aria-labelledby` on all sections

### Lighthouse a11y checklist

- [x] All images have `alt` attributes
- [x] Form inputs have associated `<label>` elements
- [x] Interactive elements are keyboard accessible
- [x] Color contrast meets WCAG AA (4.5:1 text, 3:1 UI)
- [x] No content relies solely on color
- [x] Page has a `<title>`
- [x] Language is set (`lang="ru"`)

---

## Lighthouse Recommendations

### Already implemented

- Preload critical fonts (commented in `<head>`, uncomment when fonts are added)
- `loading="lazy"` on below-fold images
- `fetchpriority="high"` on hero image
- Minified output via Vite production build
- CSS/JS code splitting
- Semantic HTML for SEO

### To optimize further

- Convert images to WebP format
- Add actual font files to `src/assets/fonts/`
- Add Open Graph image (`og:image` meta tag)
- Add `sitemap.xml`
- Add `robots.txt`

---

## Code Style

### BEM naming

```
block__element--modifier
```

Example:
```html
<div class="hero">
  <div class="hero__container">
    <h1 class="hero__title">Text</h1>
    <a href="#" class="hero__btn hero__btn--primary">Button</a>
  </div>
</div>
```

### Linting

```bash
# Check for issues
pnpm lint

# Auto-fix what's possible
pnpm lint:fix
```

---

## Deploy

### Static hosting (Netlify, Vercel, GitHub Pages)

```bash
pnpm build
# Upload dist/ folder
```

### Bitrix (copy to server)

```bash
pnpm build
# Copy contents of dist/ to your Bitrix site directory
# e.g., /home/bitrix/www/landing/
```

### Nginx config

```nginx
server {
    listen 80;
    server_name example.com;
    root /var/www/fermentkol/dist;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    # Cache static assets
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}
```
