Загрузка данных


Теперь полный код есть, и причина найдена: две карточки действительно оказались за пределами контейнера .features. Поэтому первые восемь карточек образуют сетку 2 × 4, а «VPN наоборот» и «Ищем партнёров» выпадают из неё.
Исправим это прямо в /opt/smuf-landing/site/index.html:
- уберём точки после четырёх фраз;
- переместим обе карточки внутрь общей сетки — получится 10 карточек, по две в ряд на компьютере;
- усилим синее свечение, подсветку границ и эффект подъёма при наведении;
- на телефонах сохраним одну колонку, как сейчас.
Другие тексты, кнопки, ссылки, блок предложения и настройки Caddy не меняем.
Внеси изменения одной командой
Скопируй блок целиком в терминал VPS. Скрипт проверит исходные фрагменты, изменит только нужные места и не создаст резервных копий.
python3 - <<'PY'
from pathlib import Path

p = Path("/opt/smuf-landing/site/index.html")
s = p.read_text(encoding="utf-8")
original = s

# Убираем точки в четырёх заголовках
replacements = {
    "Интернет без границ.<br><span class=\"gradient-text\">Всё под контролем.</span>":
    "Интернет без границ<br><span class=\"gradient-text\">Всё под контролем</span>",

    "Больше возможностей.<br>Меньше ограничений.":
    "Больше возможностей<br>Меньше ограничений",
}

for old, new in replacements.items():
    if s.count(old) != 1:
        raise SystemExit(f"ОШИБКА: не найден однозначно фрагмент: {old}")
    s = s.replace(old, new, 1)

# Возвращаем две карточки внутрь общей сетки .features
old = '        </div>\n      </section>\n\n          <article class="feature-card">'
if s.count(old) != 1:
    raise SystemExit("ОШИБКА: не удалось однозначно определить место карточек")
s = s.replace(old, '          <article class="feature-card">', 1)

# Усиливаем свечение карточек при наведении
old = """      background: radial-gradient(circle at 100% 0%, rgba(94, 161, 255, .12), transparent 52%);
      content: "";
      opacity: .6;"""
new = """      background:
        radial-gradient(circle at 100% 0%, rgba(65, 142, 255, .32), transparent 55%),
        radial-gradient(circle at 0% 100%, rgba(92, 169, 255, .16), transparent 52%);
      content: "";
      opacity: .72;"""
if s.count(old) != 1:
    raise SystemExit("ОШИБКА: не найден исходный градиент карточек")
s = s.replace(old, new, 1)

old = """    .feature-card:hover {
      transform: translateY(-5px);
      border-color: rgba(83, 151, 247, .5);
      background: rgba(255, 255, 255, .94);
      box-shadow: 0 20px 48px rgba(44, 108, 196, .15);
    }"""
new = """    .feature-card:hover {
      transform: translateY(-7px);
      border-color: rgba(55, 132, 255, .9);
      background: rgba(255, 255, 255, .98);
      box-shadow:
        0 24px 60px rgba(44, 108, 196, .24),
        0 0 0 1px rgba(62, 133, 232, .28),
        0 0 34px rgba(45, 125, 255, .30);
    }"""
if s.count(old) != 1:
    raise SystemExit("ОШИБКА: не найден исходный стиль наведения")
s = s.replace(old, new, 1)

if s == original:
    raise SystemExit("Изменений нет")

p.write_text(s, encoding="utf-8")
print("Готово: заголовки, сетка карточек и свечение обновлены.")
print("Карточек:", s.count('<article class="feature-card">'))
PY


Проверка
После выполнения проверь структуру HTML и настройки CSS:
grep -n -E 'Интернет без границ|Всё под контролем|Больше возможностей|Меньше ограничений|VPN наоборот|Ищем партнёров|grid-template-columns|0 0 34px' /opt/smuf-landing/site/index.html


Caddy перезагружать не нужно: он уже раздаёт файлы лендинга из каталога. Открой https://smufvpn.com/ и нажми Ctrl + F5.
На широком экране карточки будут располагаться по две в ряд, а на мобильном останутся в одной колонке. Если всё применилось, но карточки визуально стоят неправильно, пришли вывод проверки — продолжим точечно.
















полностью убираем этот текст

SMUF VPN · НОВЫЙ УРОВЕНЬ СВОБОДЫ  
вместо него ставим лого а снизу лого текст: 
Smuf VPN
удаляем лого и тескст слева вверху

делаем вторичный текст в карточках темнее, и чуть больше

делаем плавный анимированный задний фон, будто еле еле видные плавающие волны линии чет в таком духе















Сделаем следующий этап оформления Smuf VPN в том же светлом стиле с синими акцентами.
- Верхний логотип и надпись Smuf VPN уберём из левой части шапки.
- В центре первого экрана удалим строку SMUF VPN · НОВЫЙ УРОВЕНЬ СВОБОДЫ, поставим логотип, а непосредственно под ним — Smuf VPN.
- Текст описаний внутри карточек сделаем темнее и немного крупнее, чтобы он легче читался.
- Добавим на фон медленно движущиеся полупрозрачные волны и тонкие линии с голубым свечением. Анимация будет ненавязчивой, без резких вспышек; на мобильных устройствах тоже сохранится аккуратный вид.
Применяем правки
Выполни команду целиком. Она изменит только index.html, без резервных копий и без перезапуска контейнеров.
python3 - <<'PY'
from pathlib import Path

p = Path("/opt/smuf-landing/site/index.html")
s = p.read_text(encoding="utf-8")
original = s

def replace_once(old, new, label):
    global s
    count = s.count(old)
    if count != 1:
        raise SystemExit(
            f"ОШИБКА: {label}: найдено совпадений {count}, ожидалось 1. Файл не изменён."
        )
    s = s.replace(old, new, 1)

# 1. Убираем логотип и название из левой части шапки.
replace_once(
'''      <a class="brand" href="/" aria-label="Smuf VPN — главная">
        <span class="brand-mark"><span class="brand-fallback">S</span><img src="/logo.png" alt="" onerror="this.style.display='none'"></span>
        <span>Smuf VPN</span>
      </a>
''',
    "",
    "Логотип в шапке"
)

# Оставляем ссылку на личный кабинет справа.
replace_once(
    "      justify-content: space-between;\n      padding: 25px 0;",
    "      justify-content: flex-end;\n      padding: 25px 0;",
    "Выравнивание шапки"
)

# 2. Вместо верхней строки — логотип и название под ним.
replace_once(
'''        <p class="eyebrow"><span class="eyebrow-dot"></span> SMUF VPN · НОВЫЙ УРОВЕНЬ СВОБОДЫ</p>''',
'''        <div class="hero-brand">
          <img src="/logo.png" alt="Логотип Smuf VPN">
          <span>Smuf VPN</span>
        </div>''',
    "Брендинг первого экрана"
)

# 3. Добавляем оформление логотипа над заголовком.
replace_once(
'''    .hero {
      position: relative;
      padding: 83px 0 85px;
      text-align: center;
    }
''',
'''    .hero {
      position: relative;
      padding: 65px 0 85px;
      text-align: center;
    }

    .hero-brand {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 12px;
      margin: 0 auto 28px;
    }

    .hero-brand img {
      display: block;
      width: 88px;
      height: 88px;
      object-fit: contain;
      border-radius: 22px;
      box-shadow: 0 12px 34px rgba(40, 105, 226, .2);
    }

    .hero-brand span {
      color: var(--ink);
      font-size: 23px;
      font-weight: 780;
      letter-spacing: -.045em;
    }
''',
    "Стили логотипа"
)

# 4. Делаем описания карточек крупнее и темнее.
replace_once(
'''    .feature-card p {
      max-width: 470px;
      margin: 0;
      color: var(--muted);
      font-size: 14px;
      line-height: 1.8;
    }''',
'''    .feature-card p {
      max-width: 470px;
      margin: 0;
      color: #4b5d75;
      font-size: 15.5px;
      line-height: 1.75;
    }''',
    "Текст карточек"
)

# 5. Добавляем медленно движущиеся светлые волны на фон.
replace_once(
'''    a { color: inherit; }
''',
'''    body::before,
    body::after {
      content: "";
      position: fixed;
      inset: -25%;
      z-index: 0;
      pointer-events: none;
      will-change: transform;
    }

    body::before {
      background:
        radial-gradient(ellipse at 18% 28%, rgba(93, 166, 255, .17), transparent 38%),
        radial-gradient(ellipse at 82% 66%, rgba(133, 157, 255, .13), transparent 36%),
        repeating-linear-gradient(
          118deg,
          transparent 0 115px,
          rgba(56, 126, 229, .035) 116px 117px,
          transparent 118px 225px
        );
      animation: ambient-drift 38s ease-in-out infinite alternate;
    }

    body::after {
      inset: -35%;
      opacity: .55;
      background: repeating-radial-gradient(
        ellipse at 68% 48%,
        transparent 0 115px,
        rgba(66, 139, 239, .055) 116px 117px,
        transparent 118px 205px
      );
      animation: ambient-flow 52s ease-in-out infinite alternate;
    }

    @keyframes ambient-drift {
      from { transform: translate3d(-1.2%, -1%, 0) scale(1); }
      to   { transform: translate3d(1.2%, 1%, 0) scale(1.04); }
    }

    @keyframes ambient-flow {
      from { transform: rotate(-7deg) translate3d(-1%, 0, 0); }
      to   { transform: rotate(-3deg) translate3d(1%, -1%, 0); }
    }

    a { color: inherit; }
''',
    "Анимированный фон"
)

# Содержимое страницы должно располагаться над декоративным фоном.
replace_once(
'''    .page {
      width: min(1120px, calc(100% - 40px));
      margin: 0 auto;
    }''',
'''    .page {
      position: relative;
      z-index: 1;
      width: min(1120px, calc(100% - 40px));
      margin: 0 auto;
    }''',
    "Слой содержимого"
)

if s == original:
    raise SystemExit("Изменений нет.")

p.write_text(s, encoding="utf-8")
print("Готово: все 6 изменений применены.")
print("Размер HTML:", len(s.encode("utf-8")), "байт")
PY


Проверяем результат
grep -n -E 'hero-brand|SMUF VPN · НОВЫЙ УРОВЕНЬ СВОБОДЫ|feature-card p|ambient-drift|ambient-flow|class="brand"' /opt/smuf-landing/site/index.html


После этого открой https://smufvpn.com/ и нажми Ctrl + F5.
Анимация будет работать на фоне всей страницы, а содержимое останется поверх неё. При включённой в системе настройке уменьшения движения уже предусмотренное правило prefers-reduced-motion отключит анимации.
















root@1984996:~# python3 - <<'PY'
from pathlib import Path

p = Path("/opt/smuf-landing/site/index.html")
s = p.read_text(encoding="utf-8")
original = s

def replace_once(old, new, label):
    global s
    count = s.count(old)
    if count != 1:
        raise SystemExit(
            f"ОШИБКА: {label}: найдено совпадений {count}, ожидалось 1. Файл не изменён."
        )
    s = s.replace(old, new, 1)

# 1. Убираем логотип и название из левой части шапки.
replace_once(
'''      <a class="brand" href="/" aria-label="Smuf VPN — главная">
        <span class="brand-mark"><span class="brand-fallback">S</span><img src="/logo.png" alt="" onerror="this.style.display='none'"></span>
        <span>Smuf VPN</span>
      </a>
''',
    "",
    "Логотип в шапке"
)

# Оставляем ссылку на личный кабинет справа.
replace_once(
    "      justify-content: space-between;\n      padding: 25px 0;",
    "      justify-content: flex-end;\n      padding: 25px 0;",
    "Выравнивание шапки"
)

# 2. Вместо верхней строки — логотип и название под ним.
replace_once(
'''        <p class="eyebrow"><span class="eyebrow-dot"></span> SMUF VPN · НОВЫЙ УРОВЕНЬ СВОБОДЫ</p>''',
'''        <div class="hero-brand">
          <img src="/logo.png" alt="Логотип Smuf VPN">
PYint("Размер HTML:", len(s.encode("utf-8")), "байт")тивным фоном.3), transparent 36%),
ОШИБКА: Логотип в шапке: найдено совпадений 2, ожидалось 1. Файл не изменён.
root@1984996:~#













Ошибка понятна: блок с логотипом встречается в HTML дважды, поэтому скрипт остановился до записи изменений. Файл остался без изменений. Ничего страшного — просто уточним, где находится шапка.
Выполни эту команду. Она только покажет оба места с логотипом и ничего не изменит:
grep -n -B 3 -A 5 'class="brand" href="/" aria-label="Smuf VPN' /opt/smuf-landing/site/index.html


Пришли вывод. Я подстрою команду так, чтобы убрать логотип и текст только слева вверху, поставить логотип с надписью Smuf VPN в центре первого экрана, сделать текст карточек темнее и немного крупнее, а фон — с плавными едва заметными анимированными волнами. Остальные элементы сайта трогать не будем.
















root@1984996:~# grep -n -B 3 -A 5 'class="brand" href="/" aria-label="Smuf VPN' /opt/smuf-landing/site/index.html
512-<body>
513-  <div class="page">
514-    <header class="topbar">
515:      <a class="brand" href="/" aria-label="Smuf VPN — главная">
516-        <span class="brand-mark"><span class="brand-fallback">S</span><img src="/logo.png" alt="" onerror="this.style.display='none'"></span>
517-        <span>Smuf VPN</span>
518-      </a>
519-      <a class="top-link" href="/?open=app">Личный кабинет ↗</a>
520-    </header>
--
686-    </main>
687-
688-    <footer>
689:      <a class="brand" href="/" aria-label="Smuf VPN — главная">
690-        <span class="brand-mark"><span class="brand-fallback">S</span><img src="/logo.png" alt="" onerror="this.style.display='none'"></span>
691-        <span>Smuf VPN</span>
692-      </a>
693-      <span>Свобода в сети начинается с Smuf.</span>
694-      <a href="/?open=app">Подключиться ↗</a>
root@1984996:~#













Отлично, теперь причина ясна: логотип есть и в шапке, и в подвале. Уберём его только из шапки, а подвал оставим без изменений.
Выполни команду целиком. Она проверит все совпадения до записи и применит изменения только при однозначном результате.
python3 - <<'PY'
from pathlib import Path

p = Path("/opt/smuf-landing/site/index.html")
s = p.read_text(encoding="utf-8")

def replace_once(old, new, label):
    global s
    n = s.count(old)
    if n != 1:
        raise SystemExit(f"ОШИБКА: {label}: найдено {n} совпадений. Файл не изменён.")
    s = s.replace(old, new, 1)

# Убираем бренд только из верхней шапки.
replace_once(
'''    <header class="topbar">
      <a class="brand" href="/" aria-label="Smuf VPN — главная">
        <span class="brand-mark"><span class="brand-fallback">S</span><img src="/logo.png" alt="" onerror="this.style.display='none'"></span>
        <span>Smuf VPN</span>
      </a>
      <a class="top-link" href="/?open=app">Личный кабинет ↗</a>
    </header>''',
'''    <header class="topbar">
      <a class="top-link" href="/?open=app">Личный кабинет ↗</a>
    </header>''',
"Шапка сайта"
)

# Меняем слоган над заголовком на логотип с названием.
replace_once(
'''        <p class="eyebrow"><span class="eyebrow-dot"></span> SMUF VPN · НОВЫЙ УРОВЕНЬ СВОБОДЫ</p>''',
'''        <div class="hero-brand">
          <img src="/logo.png" alt="Логотип Smuf VPN">
          <span>Smuf VPN</span>
        </div>''',
"Брендинг первого экрана"
)

# Добавляем оформление логотипа, не затрагивая остальные стили hero.
replace_once(
'''    .hero {
      position: relative;
      padding: 83px 0 85px;
      text-align: center;
    }''',
'''    .hero {
      position: relative;
      padding: 65px 0 85px;
      text-align: center;
    }

    .hero-brand {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 12px;
      margin: 0 auto 28px;
    }

    .hero-brand img {
      display: block;
      width: 88px;
      height: 88px;
      object-fit: contain;
      border-radius: 22px;
      box-shadow: 0 12px 34px rgba(40, 105, 226, .2);
    }

    .hero-brand span {
      color: var(--ink);
      font-size: 23px;
      font-weight: 780;
      letter-spacing: -.045em;
    }''',
"Стили логотипа"
)

# Делаем описание карточек темнее и немного крупнее.
replace_once(
'''    .feature-card p {
      max-width: 470px;
      margin: 0;
      color: var(--muted);
      font-size: 14px;
      line-height: 1.8;
    }''',
'''    .feature-card p {
      max-width: 470px;
      margin: 0;
      color: #4b5d75;
      font-size: 15.5px;
      line-height: 1.75;
    }''',
"Текст карточек"
)

# Добавляем ненавязчивые плавающие световые волны на задний план.
replace_once(
'''    a { color: inherit; }''',
'''    body::before,
    body::after {
      content: "";
      position: fixed;
      inset: -25%;
      z-index: 0;
      pointer-events: none;
      will-change: transform;
    }

    body::before {
      background:
        radial-gradient(ellipse at 18% 28%, rgba(93, 166, 255, .17), transparent 38%),
        radial-gradient(ellipse at 82% 66%, rgba(133, 157, 255, .13), transparent 36%),
        repeating-linear-gradient(
          118deg,
          transparent 0 115px,
          rgba(56, 126, 229, .035) 116px 117px,
          transparent 118px 225px
        );
      animation: ambient-drift 38s ease-in-out infinite alternate;
    }

    body::after {
      inset: -35%;
      opacity: .55;
      background: repeating-radial-gradient(
        ellipse at 68% 48%,
        transparent 0 115px,
        rgba(66, 139, 239, .055) 116px 117px,
        transparent 118px 205px
      );
      animation: ambient-flow 52s ease-in-out infinite alternate;
    }

    @keyframes ambient-drift {
      from { transform: translate3d(-1.2%, -1%, 0) scale(1); }
      to   { transform: translate3d(1.2%, 1%, 0) scale(1.04); }
    }

    @keyframes ambient-flow {
      from { transform: rotate(-7deg) translate3d(-1%, 0, 0); }
      to   { transform: rotate(-3deg) translate3d(1%, -1%, 0); }
    }

    @media (prefers-reduced-motion: reduce) {
      body::before,
      body::after {
        animation: none !important;
      }
    }

    a { color: inherit; }''',
"Анимированный фон"
)

# Поднимаем содержимое над декоративным фоном.
replace_once(
'''    .page {
      width: min(1120px, calc(100% - 40px));
      margin: 0 auto;
    }''',
'''    .page {
      position: relative;
      z-index: 1;
      width: min(1120px, calc(100% - 40px));
      margin: 0 auto;
    }''',
"Слой содержимого"
)

p.write_text(s, encoding="utf-8")
print("Готово: изменения применены.")
print("Размер HTML:", len(s.encode("utf-8")), "байт")
PY


Если увидишь Готово: изменения применены., обнови сайт https://smufvpn.com/ сочетанием Ctrl + F5. Перезапуск Caddy не требуется.
Если скрипт сообщит об ошибке совпадений, пришли её текст — файл при этом не будет перезаписан.
















вот это еще просто на текст наверное поменяй - Почему Smuf VPN  , а то выглядит как кнопка















Да, сделаем «Почему Smuf VPN» обычным заголовком, без оформления кнопки.
Сначала найди этот элемент:
grep -n -B 4 -A 5 'Почему Smuf VPN' /opt/smuf-landing/site/index.html


Пришли вывод — подскажу точечную замену, чтобы убрать только вид кнопки и не задеть остальные элементы.
















root@1984996:~# grep -n -B 4 -A 5 'Почему Smuf VPN' /opt/smuf-landing/site/index.html
611-      </section>
612-
613-      <section aria-labelledby="features-title">
614-        <div class="section-heading">
615:          <p class="section-kicker">Почему Smuf VPN</p>
616-          <h2 id="features-title">Больше возможностей<br>Меньше ограничений</h2>
617-          <p class="section-description">
618-            Всё необходимое для комфортного использования интернета — в одном месте.
619-          </p>
620-        </div>
root@1984996:~#













Нашли. Это <p class="section-kicker"> — скорее всего, именно CSS-класс section-kicker придаёт тексту вид кнопки.
Выполни команду — заменим его на обычный текстовый класс, не меняя сам текст и заголовок ниже:
python3 - <<'PY'
from pathlib import Path

p = Path("/opt/smuf-landing/site/index.html")
s = p.read_text(encoding="utf-8")

old = '<p class="section-kicker">Почему Smuf VPN</p>'
new = '<p class="section-label">Почему Smuf VPN</p>'

if s.count(old) != 1:
    raise SystemExit("Ожидаемый элемент не найден ровно один раз. Файл не изменён.")

s = s.replace(old, new, 1)

# Добавляем спокойный стиль обычной подписи.
marker = '    .section-kicker'
if marker in s:
    insert = '''    .section-label {
      margin: 0 0 14px;
      color: #3976d8;
      font-size: 13px;
      font-weight: 650;
      letter-spacing: .08em;
    }

'''
    # Вставляем рядом с существующими стилями kicker.
    pos = s.find(marker)
    s = s[:pos] + insert + s[pos:]
else:
    raise SystemExit("CSS-класс section-kicker не найден. HTML не записан.")

p.write_text(s, encoding="utf-8")
print("Готово: «Почему Smuf VPN» теперь обычная текстовая подпись.")
PY


После этого обнови страницу через Ctrl + F5. Перезапуск Caddy не нужен.



=== Файлы в архиве ===
01-security.webp                         14636 байт
02-speed.webp                            14948 байт
03-connection.webp                       13530 байт
04-no-ads.webp                           15176 байт
05-global-access.webp                    15896 байт
06-privacy.webp                          12162 байт
07-global-servers.webp                   15230 байт
08-devices.webp                          14490 байт
09-special-offer.webp                    14056 байт
10-easy-setup.webp                       10572 байт
README.txt                                 381 байт

=== HTML первой и остальных карточек ===
      <section aria-labelledby="features-title">
        <div class="section-heading">
          <p class="section-label">Почему Smuf VPN</p>
          <h2 id="features-title">Больше возможностей<br>Меньше ограничений</h2>
          <p class="section-description">
            Всё необходимое для комфортного использования интернета — в одном месте.
          </p>
        </div>

        <div class="features">
          <article class="feature-card">
            <div class="feature-top">
              <span class="feature-icon">
                <svg viewBox="0 0 24 24"><path d="M12 3 4.5 7v5.5c0 4.3 3.2 7.3 7.5 8.5 4.3-1.2 7.5-4.2 7.5-8.5V7L12 3Z"/><path d="m8.5 12 2.2 2.2 4.8-5"/></svg>
              </span>
            </div>
            <h3>Современные протоколы</h3>
            <p>Используем передовые VPN-протоколы, такие как VLESS, для высокой скорости, стабильности и безопасности соединения в самых разных условиях.</p>
          </article>

          <article class="feature-card">
            <div class="feature-top">
              <span class="feature-icon">
                <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a15 15 0 0 1 0 18M12 3a15 15 0 0 0 0 18"/></svg>
              </span>
            </div>
            <h3>Доступ к ресурсам</h3>
            <p>Пользуйтесь сайтами, социальными сетями и стриминговыми платформами в поездках и повседневной жизни — где бы вы ни находились.</p>
          </article>

          <article class="feature-card">
            <div class="feature-top">
              <span class="feature-icon">
                <svg viewBox="0 0 24 24"><path d="M4 5h16v12H8l-4 3V5Z"/><path d="M8 9h8M8 13h5"/></svg>
              </span>
            </div>
            <h3>Круглосуточная поддержка</h3>
            <p>Общайтесь с поддержкой в чате приложения — в привычном формате мессенджера, без лишних сложностей.</p>
          </article>

          <article class="feature-card">
            <div class="feature-top">
              <span class="feature-icon">
                <svg viewBox="0 0 24 24"><path d="M3 17 9 11l4 4 8-9"/><path d="M15 6h6v6"/></svg>
              </span>
            </div>
            <h3>Высокая скорость</h3>
            <p>Серверы оптимизированы для производительности: смотрите видео, играйте, работайте и общайтесь с комфортом.</p>
          </article>

          <article class="feature-card">
            <div class="feature-top">
              <span class="feature-icon">
                <svg viewBox="0 0 24 24"><rect x="5" y="10" width="14" height="11" rx="2"/><path d="M8 10V7a4 4 0 0 1 8 0v3M12 14v3"/></svg>
              </span>
            </div>
            <h3>Защита данных</h3>
            <p>Шифрование соединения помогает защитить передаваемые данные от перехвата в сети и постороннего доступа.</p>
          </article>

          <article class="feature-card">
            <div class="feature-top">
              <span class="feature-icon">
                <svg viewBox="0 0 24 24"><path d="M3 7h18v13H3z"/><path d="M3 11h18M7 4v6M17 4v6"/><path d="m8 16 2 2 5-5"/></svg>
              </span>
            </div>
            <h3>Экономия на онлайн-покупках</h3>
            <p>Открывайте для себя региональные предложения на авиабилеты, отели, товары и подписки. Цены и доступность могут различаться в зависимости от страны.</p>
          </article>

          <article class="feature-card">
            <div class="feature-top">
              <span class="feature-icon">
                <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 22s8-4 8-11V5l-8-3-8 3v6c0 7 8 11 8 11Z"/><rect x="7" y="8" width="10" height="7" rx="1.5"/><path d="M9 11h6M9 13h3M8 16 16 8"/></svg>
              </span>
            </div>
            <h3>Забудьте о рекламе</h3>
            <p>Встроенный блокировщик рекламы помогает убрать отвлекающие баннеры и сделать просмотр страниц комфортнее. Доступность функции зависит от конфигурации сервиса.</p>
          </article>

          <article class="feature-card">
            <div class="feature-top">
              <span class="feature-icon">
                <svg viewBox="0 0 24 24"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M19 8v6M16 11h6"/></svg>
              </span>
            </div>
            <h3>Рефералы и бонусы</h3>
            <p>Приглашайте друзей в Smuf VPN и получайте приятные бонусы.</p>
          </article>
          <article class="feature-card">
            <div class="feature-top">
              <span class="feature-icon">
                <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a15 15 0 0 1 0 18M12 3a15 15 0 0 0 0 18"/></svg>
              </span>
            </div>
            <h3>VPN наоборот</h3>
            <p>Доступ к российским сервисам из-за границы? Легко! Наш сервер в России открывает вам российский интернет.</p>
          </article>

          <article class="feature-card">
            <div class="feature-top">
              <span class="feature-icon">
                <svg viewBox="0 0 24 24"><circle cx="9" cy="8" r="3.5"/><path d="M2.5 20v-1.5A4.5 4.5 0 0 1 7 14h4a4.5 4.5 0 0 1 4.5 4.5V20M16 5.5a3.5 3.5 0 0 1 0 6.8M18 14.5a4.5 4.5 0 0 1 3.5 4.3V20"/></svg>
              </span>
            </div>
            <h3>Ищем партнёров</h3>
            <p>Делитесь с миром быстрым и надёжным VPN.</p>
            <a class="button partner-button" href="/?open=app">СТАТЬ ПАРТНЁРОМ <span class="button-arrow" aria-hidden="true">→</span></a>
          </article>
        </div>
      </section>

      <section class="offer" aria-labelledby="offer-title">
        <div class="offer-main">
          <span class="offer-label">Специальное предложение</span>
          <h2 id="offer-title">Уже купили другой VPN, но он перестал работать?</h2>
          <p class="offer-intro">
            Если у вас есть активная платная подписка на другой VPN, которая
            вас больше не устраивает, мы подготовили для вас специальное предложение.
            <br><br>
            Отправьте в чат поддержки скриншот чека, письма или личного кабинета

=== Стили карточек ===
      line-height: 1.75;
    }

    .features {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 19px;
      padding-bottom: 88px;
    }

    .feature-card {
      position: relative;
      min-height: 245px;
      overflow: hidden;
      padding: 29px 30px 31px;
      border: 1px solid rgba(255, 255, 255, .95);
      border-radius: 25px;
      background: var(--surface);
      box-shadow: var(--shadow);
      backdrop-filter: blur(18px);
      -webkit-backdrop-filter: blur(18px);
      transition:
        transform .28s ease,
        border-color .28s ease,
        box-shadow .28s ease,
        background .28s ease;
      animation: rise-in .65s ease both;
    }

    .feature-card::before {
      position: absolute;
      inset: 0;
      z-index: 0;
      background:
        radial-gradient(circle at 100% 0%, rgba(65, 142, 255, .32), transparent 55%),
        radial-gradient(circle at 0% 100%, rgba(92, 169, 255, .16), transparent 52%);
      content: "";
      opacity: .72;
      transition: opacity .28s ease;
      pointer-events: none;
    }

    .feature-card:hover {
      transform: translateY(-7px);
      border-color: rgba(55, 132, 255, .9);
      background: rgba(255, 255, 255, .98);
      box-shadow:
        0 24px 60px rgba(44, 108, 196, .24),
        0 0 0 1px rgba(62, 133, 232, .28),
        0 0 34px rgba(45, 125, 255, .30);
    }

    .feature-card:hover::before { opacity: 1; }

    .feature-card > * { position: relative; z-index: 1; }

    .feature-top {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 12px;
      margin-bottom: 25px;
    }

    .feature-icon {
      display: grid;
      width: 49px;
      height: 49px;
      place-items: center;
      border: 1px solid rgba(88, 148, 231, .15);
      border-radius: 16px;
      color: #347ee9;
      background: linear-gradient(145deg, #f4f9ff, #e6f0ff);
      transition: transform .28s ease, background .28s ease;
    }

root@1984996:~#