.section-pad{ padding: 34px clamp(20px,4vw,56px) 70px; }
  .listing-head{ display:flex; align-items:flex-end; justify-content:space-between; margin-bottom:26px; flex-wrap:wrap; gap:14px;}
  .listing-head h1{ font-size:clamp(28px,3.4vw,40px); }
  .listing-head p{ color:var(--ink-soft); margin-top:6px; font-size:14px; }
  /* "Не показывать ИИ-контент" — переключатель в Проекты/Кейсы (см.
     toggleNoAiFilter() в js/catalog.js). Кнопка перенесена в узкую aside-
     колонку под баннер CTA (см. .listing-cta-banner ниже) — сплошная
     чёрная заливка активного состояния рядом с приметным баннером была
     слишком контрастной, поэтому теперь прозрачный фон и всего лишь
     чуть более тёмная, чем обычно, обводка. */
  .no-ai-toggle-btn.active{ background:transparent; color:var(--ink); border-color:#c7c9d6; }

  /* phone swipe deck */
  .swipe-zone{
    display:grid; grid-template-columns: 300px 1fr; gap:40px; align-items:center;
    background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-lg);
    padding:30px clamp(20px,3vw,40px); margin-bottom:44px;
  }
  .phone{
    width:240px; height:400px; border-radius:34px; background:var(--ink); padding:10px;
    margin:0 auto; box-shadow:var(--shadow-soft); position:relative;
  }
  .phone-screen{
    width:100%; height:100%; border-radius:26px; background:var(--bg); position:relative; overflow:hidden;
  }
  .deck{ position:absolute; inset:14px; }
  .swipe-card{
    position:absolute; inset:0; border-radius:20px; overflow:hidden; box-shadow:0 10px 24px -12px rgba(0,0,0,0.35);
    touch-action:none; user-select:none; display:flex; flex-direction:column; justify-content:flex-end;
    color:#fff; transition: transform .35s cubic-bezier(.2,.8,.2,1), opacity .35s ease;
  }
  .swipe-card .sc-info{
    padding:14px; background:linear-gradient(to top, rgba(0,0,0,0.75), transparent);
    /* Пункт "В свайпере не отображается имя (если промомедиа — видео)":
       у видео внутри карточки position:absolute (см. js/swipe-deck.js),
       а .sc-info раньше был обычным статичным блоком без своего
       позиционирования — браузер всегда рисует позиционированные элементы
       поверх статичных, независимо от z-index видео (даже z-index:0).
       С картинкой имя было видно случайно, просто из-за другого порядка
       наложения слоёв фона. position:relative создаёт свой стекинг-контекст,
       так что z-index здесь уже реально сравнивается с видео и выигрывает. */
    position:relative; z-index:2;
  }
  .swipe-card .sc-name{ font-family:'Unbounded',sans-serif; font-weight:700; font-size:15px; }
  .swipe-card .sc-spec{ font-size:11px; opacity:0.85; margin-top:2px; }
  .swipe-stamp{
    position:absolute; top:24px; padding:6px 14px; border:3px solid; border-radius:8px;
    font-family:'Unbounded',sans-serif; font-weight:800; font-size:16px; letter-spacing:0.05em;
    opacity:0; transform: rotate(-18deg);
  }
  .stamp-like{ left:20px; border-color:var(--teal); color:var(--teal); }
  .stamp-pass{ right:20px; border-color:var(--coral); color:var(--coral); transform: rotate(18deg); }
  .swipe-controls{ display:flex; justify-content:center; gap:16px; margin-top:16px; }
  .circle-btn{
    width:52px; height:52px; border-radius:50%; border:1.5px solid var(--border); background:var(--surface);
    display:flex; align-items:center; justify-content:center; font-size:20px; box-shadow:var(--shadow-card);
    transition: transform .15s ease;
  }
  .circle-btn:hover{ transform: scale(1.08); }
  .circle-btn.pass{ color:var(--coral); }
  .circle-btn.like{ color:var(--teal); }
  .swipe-copy h3{ font-size:22px; margin-bottom:10px; }
  .swipe-copy p{ color:var(--ink-soft); font-size:14px; line-height:1.6; max-width:420px; }
  .swipe-copy .hint{ margin-top:14px; font-size:12px; color:var(--ink-faint); font-family:'JetBrains Mono',monospace; display:flex; gap:8px; align-items:center; }
  .hint-action{ cursor:pointer; text-decoration:underline; text-underline-offset:3px; transition:color .15s ease; }
  .hint-action:hover{ color:var(--ink); }

  /* filters */
  .filters{
    display:flex; flex-wrap:wrap; gap:12px; align-items:center; margin-bottom:28px;
    background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-md); padding:14px 18px;
  }
  .filters input[type=text]{
    flex:1 1 220px; border:none; background:transparent; font-size:14px; font-family:inherit; padding:8px 4px;
  }
  .filters input[type=text]:focus{ outline:none; }
  .filters select{
    border:1.5px solid var(--border); border-radius:10px; padding:9px 34px 9px 14px; font-size:13px; font-family:inherit;
    background-color:#FCFCFE; color:var(--ink);
    appearance:none; -webkit-appearance:none; -moz-appearance:none;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235B5F6B' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat:no-repeat;
    background-position: right 12px center;
    background-size:14px;
    cursor:pointer;
  }
  /* Было margin-bottom:4px — когда чип активного фильтра показан, ряды под
     ним (группы тегов «Навыки»/«Клиенты») визуально слипались с ним почти
     без отступа. Увеличено, чтобы совпадать по «воздуху» с остальными
     отступами блока тегов (.tags-group имеет margin-bottom:16px). */
  .active-tag-chip{ margin:12px 0 18px; }
  .chip-toggle{
    border:1.5px solid var(--border); background:#FCFCFE; border-radius:999px; padding:8px 14px; font-size:12.5px;
    font-weight:600; color:var(--ink-soft);
  }
  .chip-toggle.active{ background:var(--ink); color:#fff; border-color:var(--ink); }
  .chip-toggle.chip-more{ border-style:dashed; color:var(--ink-faint); background:transparent; }
  .chip-toggle.chip-more:hover{ border-color:var(--ink); color:var(--ink); }
  .shuffle-btn{
    margin-left:auto; border:1.5px solid var(--border); background:#FCFCFE; border-radius:999px; padding:9px 16px;
    font-size:13px; font-weight:700; display:flex; align-items:center; gap:6px;
  }
  .shuffle-btn:hover{ border-color:var(--ink); }

  /* ============================================================
     «Профили»: сортировка + кнопка «Теги» (вместо прежних выпадающих
     списков «Специализации / Страна / Город» и открытой россыпи тегов).
     ============================================================ */

  /* Скрытый нативный <select id="sort-filter"> — по-прежнему источник значения
     сортировки для js/catalog.js, но не показывается: вместо него свой список. */
  .filters .sort-native{ display:none; }

  /* Сортировка — тот же вид, что у сворачиваемого меню «Возможностей» и кабинета
     на мобильном (.opp-side-toggle/.opp-nav-item в css/opportunities-tabs.css,
     .cab-tab-toggle/.cab-tab-dd-item в css/responsive.css): белая карточка со
     скруглением, иконка в сером квадрате, жирная подпись, стрелка; пункты — с
     иконками, активный подсвечен фиолетовым, иконка активного — на белом. */
  .sort-dd{
    position:relative; flex:0 0 auto; min-width:300px;
    background:var(--surface); border:1px solid var(--border); border-radius:20px; padding:3px;
  }
  .sort-dd-toggle{
    display:flex; align-items:center; justify-content:space-between; gap:10px; width:100%;
    padding:5px 12px 5px 5px; border:none; background:transparent;
    font-family:inherit; font-size:14px; font-weight:700; color:var(--ink); cursor:pointer; text-align:left;
  }
  .sort-dd-cur{ display:flex; align-items:center; gap:12px; flex:1; min-width:0; }
  .sort-dd-label{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .sort-dd-toggle .sort-dd-ic{ width:30px; height:30px; }
  .sort-dd-toggle .caret{ width:16px; height:16px; color:var(--ink-soft); flex-shrink:0; transition:transform .2s ease; }
  .sort-dd.open .sort-dd-toggle .caret{ transform:rotate(180deg); }
  .sort-dd-ic{
    width:36px; height:36px; border-radius:11px; background:var(--icon-tint,#ECEDF4);
    display:flex; align-items:center; justify-content:center; flex-shrink:0; color:var(--ink);
  }
  .sort-dd-ic svg{ width:18px; height:18px; }
  .sort-dd-list{
    display:none; position:absolute; left:0; right:0; top:calc(100% + 8px); z-index:70;
    background:var(--surface); border:1px solid var(--border); border-radius:20px; padding:6px;
    box-shadow:var(--shadow-soft);
  }
  .sort-dd.open .sort-dd-list{ display:block; }
  .sort-dd-item{
    display:flex; align-items:center; gap:12px; width:100%; text-align:left; padding:7px 10px 7px 8px;
    border-radius:16px; border:none; background:transparent; font-family:inherit; font-size:14px;
    font-weight:700; color:var(--ink-soft); cursor:pointer; transition:.15s ease;
  }
  .sort-dd-item:hover{ background:var(--bg); color:var(--ink); }
  .sort-dd-item.active{ background:var(--violet-tint); color:#5847c9; }
  .sort-dd-item.active .sort-dd-ic{ background:#fff; color:#5847c9; }

  /* Кнопка «Теги» — копия кнопки «Фильтры» из «Возможностей» (.opp-chip.opp-filter):
     в закрытом виде светлая рамка, в открытом (.open) — тёмная рамка и тёмный текст. */
  .catalog-tags-toggle{
    border:1px solid var(--border); background:var(--surface); color:var(--ink-soft); border-radius:999px; padding:7px 10px;
    font-family:inherit; font-size:13px; font-weight:600; cursor:pointer; white-space:nowrap; transition:.15s ease;
    display:inline-flex; align-items:center; gap:6px; position:relative;
  }
  .catalog-tags-toggle:hover{ border-color:#c7c9d6; color:var(--ink); }
  .catalog-tags-toggle.open{ border-color:var(--ink); color:var(--ink); }
  .catalog-tags-toggle svg{ width:14px; height:14px; }
  /* точка на кнопке: выбран тег, а панель тегов закрыта — чтобы фильтр не «терялся» */
  .catalog-tags-toggle.has-active::after{
    content:''; position:absolute; top:-2px; right:-2px; width:9px; height:9px; border-radius:50%;
    background:var(--coral); border:2px solid var(--surface); box-sizing:content-box;
  }

  /* Панель с облаками тегов («Навыки» / «Клиенты») — как .opp-filters в «Возможностях». */
  .catalog-tags-panel{
    display:none; background:var(--surface); border:1px solid var(--border); border-radius:20px;
    padding:22px 24px 8px; margin-bottom:22px;
  }
  .catalog-tags-panel.open{ display:block; }
  .catalog-tags-panel .tags-groups{ margin-bottom:0; }
  .catalog-tags-panel .tags-groups .tags-group{ margin-bottom:20px; }
  .catalog-tags-panel .tags-groups:empty{ display:none; }

  @media(max-width:880px){
    /* на мобильном — ровно те же размеры, что у .opp-side / .opp-side-toggle */
    .sort-dd{ padding:6px; border-radius:20px; }
    .sort-dd-toggle{ padding:8px 14px 8px 8px; }
  }
  @media(max-width:640px){
    .sort-dd{ flex:1 1 100%; min-width:0; }
    .catalog-tags-toggle, .shuffle-btn{ flex:1 1 auto; justify-content:center; }
    .catalog-tags-panel{ padding:18px 16px 4px; }
  }

  .tags-row{ display:flex; flex-wrap:wrap; gap:8px; margin-bottom:22px; }
  .tags-groups{ margin-bottom:30px; }
  .tags-group{ margin-bottom:16px; }
  .tags-group:last-child{ margin-bottom:0; }
  .tags-group-label{ font-size:12px; font-weight:600; color:var(--ink-faint); text-transform:uppercase; letter-spacing:.04em; margin-bottom:8px; }
  .tags-group .tags-row{ margin-bottom:0; }

  /* ============================================================
     Проекты/Кейсы/Альбомы: тот же приём, что «Профили» выше — поиск +
     кнопка «Теги» вместо открытого облака тегов (само облако по-прежнему
     рисуют renderProjectsTagsRow()/renderCasesTagsRow()/renderAlbumsTagsRow(),
     просто теперь в скрытую .catalog-tags-panel). Разница только в том, что
     колонка узкая (aside, ~3fr) — сортировки и «Перемешать» тут никогда не
     было, так что вместо ряда «поиск + сортировка + Теги + Перемешать» —
     просто «поиск» и «Теги» друг под другом на всю ширину колонки.
     Баг (правки 23 сентября): .filters input[type=text] выше рассчитан на
     строку (flex:1 1 220px — 220px это ШИРИНА). В колонке (flex-direction:
     column) тот же flex-basis:220px читается уже как ВЫСОТА, да ещё и с
     flex-grow:1 тянется на всё свободное место — поле поиска раздувалось в
     огромный пустой прямоугольник. flex:0 0 auto возвращает полю обычную
     высоту однострочного инпута. */
  .listing-filters{ flex-direction:column; align-items:stretch; margin-bottom:14px; }
  .listing-filters input[type=text]{ flex:0 0 auto; padding:9px 6px; }
  /* Правка 23 сентября: кнопка «Теги» была заметно ниже остальных кнопок
     колонки (CTA «Создать свой проект», «Не показывать ИИ-контент» — обе
     .btn с padding:14px 26px, см. css/buttons.css). Даём тот же вертикальный
     паддинг и размер шрифта, чтобы высота совпадала. */
  .listing-filters .catalog-tags-toggle{
    justify-content:center; flex:0 0 auto; padding:14px 18px; font-size:14px;
  }
  .listing-aside .catalog-tags-panel{ margin-bottom:16px; }

  /* Баннер CTA — сразу под поиском/«Теги» (было ниже, под панелью тегов —
     подняли выше, ближе к началу колонки, как более важный призыв к
     действию). Кнопка — та же приметная «Создать портфолио», что на
     мобильном главном экране (.btn-primary.btn-block, см. css/landing.css).
     Фон — та же супрематическая композиция, что и у самого hero-блока
     мобильной версии: те же классы .onb-supr/.onb-rect--a..d, что уже
     переиспользует модалка «Открой возможности!» (см. css/modals.css,
     комментарий там же — "стиль... должен повторять стиль hero-блока
     мобильной версии") — просто ещё одно место с тем же приёмом, а не
     третья копия одних и тех же значений фигур. */
  /* Правка 23 сентября: баннер был низкий и прижат к верху — контент
     (текст + кнопка) шёл сверху вниз обычным потоком. Теперь высота равна
     ширине колонки (квадрат), а содержимое центрируется по обеим осям. */
  .listing-cta-banner{
    position:relative; overflow:hidden; aspect-ratio:1/1;
    display:flex; align-items:center; justify-content:center;
    background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-md);
    padding:20px; margin-bottom:16px; text-align:center;
  }
  .listing-cta-inner{ position:relative; z-index:1; width:100%; }
  .listing-cta-text{ font-size:13px; color:var(--ink-soft); margin:0 0 14px; line-height:1.5; }

  /* Two-column page layout — Кейсы / Проекты on desktop: cards on the left
     (≈70%), tags in a right-hand rail (≈30%). On mobile/tablet this collapses
     back to a single column with the tags above the cards (their original
     DOM order — .listing-aside comes first in the markup), unchanged from
     before this restyle. */
  @media(min-width:881px){
    .listing-layout{ display:grid; grid-template-columns:7fr 3fr; gap:48px; align-items:start; }
    .listing-layout .listing-aside{ order:2; margin-bottom:0; position:sticky; top:28px; }
    /* Правка 23 сентября: с открытой панелью тегов aside мог оказаться
       выше окна браузера — из-за sticky верх колонки «примерзал» к
       top:28px и часть тегов внизу panels оставалась недоступной (сама
       страница уже не скроллится, а прокрутки внутри sticky-блока нет).
       Пока панель открыта (.aside-tags-open, см. toggleListingTagsPanel()
       в js/catalog.js), убираем sticky — колонка ведёт себя как обычный
       блок в потоке, и вся её высота, включая все теги, доступна
       обычной прокруткой страницы. */
    .listing-layout .listing-aside.aside-tags-open{ position:static; }
    .listing-layout .listing-main{ order:1; min-width:0; }
    /* Проекты: extra breathing room on wide screens — one column of cards
       reading like an article list rather than stretching edge-to-edge. */
    #view-projects .listing-main{ max-width:760px; }
  }

  .results-count{ font-size:12.5px; color:var(--ink-faint); margin-bottom:16px; font-family:'JetBrains Mono',monospace; }

  .grid{
    display:grid; grid-template-columns: repeat(auto-fill, minmax(220px,1fr)); gap:22px;
  }
  .card{
    background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-md); overflow:hidden;
    cursor:pointer; transition: transform .2s ease, box-shadow .2s ease;
  }
  .card:hover{ transform: translateY(-5px); box-shadow:var(--shadow-card); }
  .card-media{
    aspect-ratio:192/352; position:relative; display:flex; align-items:center; justify-content:center; color:#fff;
  }
  .card-media svg{ width:44px; height:44px; opacity:0.9; }
  .win-chip{
    position:absolute; top:10px; left:10px; display:flex; align-items:center; gap:4px;
    background:rgba(0,0,0,0.32); backdrop-filter:blur(4px); color:#fff; border-radius:999px;
    padding:4px 9px; font-family:'JetBrains Mono',monospace; font-size:11px; font-weight:700;
  }
  .win-chip svg{ width:11px; height:11px; }
  .card-fav-btn{
    position:absolute; top:10px; right:10px; width:32px; height:32px; border-radius:50%;
    background:rgba(0,0,0,0.32); backdrop-filter:blur(4px); display:flex; align-items:center; justify-content:center;
    transition: transform .15s ease, background .15s ease; z-index:2;
  }
  .card-fav-btn svg{ width:16px; height:16px; fill:none; stroke:#fff; stroke-width:2; transition: fill .15s ease, stroke .15s ease; }
  .card-fav-btn:hover{ transform:scale(1.08); background:rgba(0,0,0,0.5); }
  .card-fav-btn.active{ background:rgba(255,77,109,0.9); }
  .card-fav-btn.active svg{ fill:#fff; stroke:#fff; }
  .card-like-btn{
    position:absolute; bottom:10px; left:10px; display:flex; align-items:center; gap:4px;
    background:rgba(0,0,0,0.32); backdrop-filter:blur(4px); color:#fff; border-radius:999px;
    padding:5px 10px; font-size:11.5px; font-weight:700; z-index:2; transition: transform .15s ease, background .15s ease;
  }
  .card-like-btn svg{ width:13px; height:13px; fill:none; stroke:#fff; stroke-width:2; transition: fill .15s ease, stroke .15s ease; }
  .card-like-btn:hover{ transform:scale(1.06); background:rgba(0,0,0,0.5); }
  .card-like-btn.liked{ background:rgba(255,77,109,0.9); }
  .card-like-btn.liked svg{ fill:#fff; stroke:#fff; }
  .card-body{ padding:16px 16px 18px; }
  .card-body .c-name{ font-family:'Unbounded',sans-serif; font-weight:700; font-size:15px; }
  .card-body .c-spec{ font-size:12.5px; color:var(--ink-soft); margin-top:4px; }
  .card-body .c-loc{ font-size:11.5px; color:var(--ink-faint); margin-top:3px; font-family:'JetBrains Mono',monospace; }
  .card-foot{ display:flex; align-items:center; justify-content:space-between; margin-top:12px; }
  .rating{ display:flex; align-items:center; gap:5px; font-size:12.5px; font-weight:700; color:var(--ink); }
  .rating svg{ width:13px; height:13px; fill:var(--gold); }
  .status-dot{ font-size:10.5px; color:var(--ink-faint); font-family:'JetBrains Mono',monospace; }

  /* ================= PROFILE ================= */
/* ============ Бесконечная подгрузка (ТЗ "Бесконечный скроллинг") ============
   Общие стили для спиннера/сообщения "всё загружено"/блока ошибки с повтором —
   переиспользуются во всех разделах с бесконечной подгрузкой: каталог анкет,
   проекты, кейсы, кофаундер, возможности. */
.feed-loader{ display:flex; justify-content:center; align-items:center; padding:28px 0; }
.feed-spinner{
  width:26px; height:26px; border-radius:50%;
  border:3px solid rgba(0,0,0,0.1); border-top-color: var(--ink, #16161f);
  animation: feed-spin .7s linear infinite;
}
@keyframes feed-spin{ to{ transform: rotate(360deg); } }
.feed-end-msg{ text-align:center; padding:20px 0; color:var(--ink-faint); font-size:13px; }
.feed-error{ text-align:center; padding:20px 0; display:flex; flex-direction:column; align-items:center; gap:10px; color:var(--ink-soft); font-size:13px; }
.feed-sentinel{ height:1px; }