Files
nahodka-front/src/styles/layout.css
2026-09-14 01:49:49 +03:00

812 lines
26 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ─────────────────────────────────────────────────────────────────────
СТЕКЛЯННАЯ ШАПКА + ЗАТУХАНИЕ ЛЕНТЫ (Telegram Web style)
─────────────────────────────────────────────────────────────────────
Регистрация кастомного свойства: именно благодаря @property смена
--feed-fade-height анимируется transition'ом. В браузерах без поддержки
@property значение просто меняется мгновенно (graceful degradation).
*/
@property --feed-fade-height {
syntax: '<length>';
inherits: false;
initial-value: 48px;
}
/* ── App Shell (Instagram-style) ── */
.f-app {
display: flex; height: 100vh; height: 100dvh;
background: var(--bg-app);
overflow: hidden; font-family: var(--font); position: relative;
}
/* ── Overlay (mobile sidebar backdrop) ── */
.f-overlay {
position: fixed; inset: 0; background: var(--bg-overlay);
z-index: 40; opacity: 0; pointer-events: none; transition: opacity .32s;
}
.f-overlay.show { opacity: 1; pointer-events: all; }
/* ── Main Column ── */
.f-main {
flex: 1; display: flex; flex-direction: column;
min-width: 0; height: 100vh; height: 100dvh; overflow: hidden;
}
/* ── Topbar (telegram-style; mobile only; desktop uses the nav sidebar) ──
«Стекло»: полупрозрачный фон темы + мягкий blur по содержимому под шапкой.
blur/saturate явно умеренные — сильно агрессивное размытие даёт
пересвеченное «стекло» (blur 12px + saturate ~135%). */
.f-topbar {
position: sticky;
top: 0;
z-index: 10;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 8px 12px;
padding-top: calc(8px + env(safe-area-inset-top));
/* Без backdrop-filter: blur имеет жёсткую границу по кромке прямоугольника,
которую маской не убрать. Плавность даёт только сквозной альфа-градиент,
сходящийся к 0 уже к низу бара. */
background: linear-gradient(
to bottom,
rgba(var(--bg-rgb), 0.14) 0%,
rgba(var(--bg-rgb), 0.07) 55%,
rgba(var(--bg-rgb), 0.05) 100%
);
transition: transform 0.25s ease, background-color 0.25s ease;
}
/* Продолжение того же сквозного градиента ниже бара: цвет уходит в 0,
резкой границы нет, «плашки» не видно вообще. */
.f-topbar::after {
content: "";
position: absolute;
left: 0;
right: 0;
top: 100%;
height: 64px;
pointer-events: none;
background: linear-gradient(
to bottom,
rgba(var(--bg-rgb), 0.05) 0%,
rgba(var(--bg-rgb), 0) 100%
);
}
/* Кнопка-логотип по центру: wordmark «Находка» в округлой стеклянной капсуле */
.f-logo-btn {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 1 auto;
min-width: 0;
height: 38px;
padding: 0 30px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(8px) saturate(150%);
-webkit-backdrop-filter: blur(8px) saturate(150%);
border: 1px solid rgba(255, 255, 255, 0.25);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
cursor: pointer;
line-height: 0;
transition: background .15s;
}
.f-logo-btn:hover { background: rgba(255, 255, 255, 0.22); }
.f-logo-btn .f-topbar-logo {
height: 26px;
width: auto;
display: block;
min-width: 0;
transform: translateY(2px);
}
[data-theme="dark"] .f-logo-btn .f-topbar-logo .f-logo-word {
fill: url(#nahodkaLogoCoral);
}
[data-theme="dark"] .f-logo-btn .f-topbar-logo .f-logo-heart {
fill: #FF4B3A;
}
/* Галочка-индикатор фильтра на кнопке-логотипе: поворачивается при открытии */
.f-topbar-chevron {
position: absolute;
right: 8px;
top: 50%;
width: 14px;
height: 14px;
color: var(--text-primary);
transform: translateY(-50%);
transition: transform .25s ease;
}
.f-topbar-chevron.open {
transform: translateY(-50%) rotate(180deg);
}
/* Кнопка вызова SideBar: стеклянный squircle (приближение iOS) */
.f-menu-btn {
width: 38px;
height: 38px;
border-radius: 22%;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(12px) saturate(150%);
-webkit-backdrop-filter: blur(12px) saturate(150%);
border: 1px solid rgba(255, 255, 255, 0.25);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
flex-shrink: 0;
padding: 0;
cursor: pointer;
line-height: 0;
color: var(--text-primary);
transition: background .15s, transform .1s;
}
.f-menu-btn:hover { background: rgba(255, 255, 255, 0.22); }
.f-menu-btn:active { transform: scale(.92); }
.f-menu-btn svg { width: 45%; height: 45%; }
.f-topbar-center { flex: 1; display: flex; justify-content: center; min-width: 0; }
.f-topbar-wordmark {
color: var(--text-primary); font-weight: 900; font-size: 1.05rem;
letter-spacing: -.4px; white-space: nowrap; margin-left: 2px;
}
.f-topbar img,
.f-topbar svg { flex-shrink: 0; }
/* Когда открыт левый SideBar — верхний TopBar уходит за него (ниже по z-index) */
.f-app.f-sb-open .f-topbar,
.f-app.f-sb-open .f-feed > .f-topbar-dropdown-wrap {
z-index: 10;
}
/* Мобильный drawer делаем полупрозрачным, чтобы TopBar просвечивал за ним */
@media (max-width: 900px) {
.f-app.f-sb-open .f-sidebar {
background: var(--bg-filter);
-webkit-backdrop-filter: blur(20px) saturate(180%);
backdrop-filter: blur(20px) saturate(180%);
}
}
/* ── Topbar Profile ── */
.f-topbar-profile {
width: 32px; height: 32px; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
cursor: pointer; border-radius: 50%;
transition: background .15s;
}
.f-topbar-profile:hover { background: var(--hover-bg); }
.f-topbar-profile .f-profile-avatar {
width: 28px; height: 28px; border-width: 1.5px;
}
.f-topbar-profile .f-profile-avatar-placeholder {
width: 28px; height: 28px; font-size: 1rem;
}
.f-topbar-login-icon { font-size: 1.1rem; line-height: 1; }
/* ── Search Bar ── */
.f-search-bar {
display: flex; align-items: center; gap: 10px;
padding: 10px 16px;
background: var(--bg-surface);
border-bottom: 1px solid var(--border);
}
.f-search-icon {
width: 18px; height: 18px; flex-shrink: 0;
color: var(--muted);
}
.f-search-input {
flex: 1; min-width: 0;
background: var(--bg-input);
border: 1px solid transparent;
border-radius: 999px;
padding: 10px 18px;
font-family: var(--font); font-size: 0.9rem;
color: var(--text-primary);
outline: none;
transition: border-color .2s, box-shadow .2s, background .2s;
}
.f-search-input::placeholder { color: var(--muted); }
.f-search-input:focus {
border-color: var(--border);
background: var(--bg-surface);
box-shadow: 0 1px 6px rgba(0,0,0,.06);
}
.f-search-clear {
background: none; border: none; cursor: pointer;
color: var(--muted); padding: 4px; border-radius: 50%;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0; transition: color .15s, background .15s;
}
.f-search-clear:hover { color: var(--text-primary); background: var(--hover-bg); }
/* ── Filter Bar ── */
.f-filter-bar {
display: flex; gap: 8px;
padding: 10px 16px;
border-bottom: 1px solid var(--border);
background: var(--bg-surface);
justify-content: center;
}
.f-filter-btn {
display: flex; align-items: center; gap: 6px;
padding: 8px 16px; border-radius: 999px;
font-family: var(--font); font-size: 0.85rem; font-weight: 600;
background: var(--bg-input); border: 1px solid var(--border);
color: var(--muted); cursor: pointer;
transition: all 0.2s ease;
}
.f-filter-btn:hover {
background: var(--hover-bg); color: var(--text-primary);
}
.f-filter-btn.active {
background: rgba(var(--teal-rgb), .08);
border-color: rgba(var(--teal-rgb), .5);
color: var(--teal); font-weight: 700;
}
/* ── Topbar Dropdown (фильтр типа привязан к кнопке-логотипу) ── */
.f-topbar-dropdown-wrap {
position: relative;
}
.f-topbar-dropdown-wrap .f-topbar.f-topbar-hidden {
/* Плавное скрытие шапки при скролле вниз (translateY вверх, за кромку .f-feed).
Висим на самом .f-topbar, а НЕ на обёртке: transform на обёртке создал бы
containing block для position:fixed оверлея дропдауна и сломал бы клик вне. */
transform: translateY(-100%);
}
/* В ленте шапка лежит ПОВЕРХ маскированного скролл-контейнера (.f-feed-scroll):
по z-index она выше «слоя затухания», но ниже, чем сам контент не бывает
никогда — жёстко прижата к верху .f-feed. */
.f-feed > .f-topbar-dropdown-wrap {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 10;
margin: 0;
}
.f-topbar-dropdown-overlay {
position: fixed; inset: 0; z-index: 45;
background: transparent;
}
.f-topbar-dropdown-menu {
position: absolute; top: 100%; left: 0; right: 0;
z-index: 50;
display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 6px;
padding: 8px 12px;
margin-top: 6px;
background: rgba(0, 0, 0, .72);
backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, .08);
border-radius: 999px;
box-shadow: 0 12px 40px rgba(0, 0, 0, .35);
}
:root:not([data-theme="dark"]) .f-topbar-dropdown-menu {
background: rgba(255, 255, 255, .92);
border-color: rgba(0, 0, 0, .08);
box-shadow: 0 12px 40px rgba(0, 0, 0, .12);
}
.f-topbar-dropdown-item {
display: flex; align-items: center; justify-content: center;
padding: 8px 16px;
border: none; border-radius: 999px;
background: rgba(255, 255, 255, .08);
color: rgba(255, 255, 255, .85);
font-family: var(--font); font-size: 0.85rem; font-weight: 600;
white-space: nowrap;
cursor: pointer;
transition: background .15s, color .15s;
}
.f-topbar-dropdown-item:hover {
background: rgba(255, 255, 255, .14);
color: #fff;
}
.f-topbar-dropdown-item.active {
background: rgba(var(--teal-rgb), .25);
color: var(--teal);
}
:root:not([data-theme="dark"]) .f-topbar-dropdown-item {
background: rgba(0, 0, 0, .06);
color: rgba(0, 0, 0, .75);
}
:root:not([data-theme="dark"]) .f-topbar-dropdown-item:hover {
background: rgba(0, 0, 0, .1);
color: #000;
}
:root:not([data-theme="dark"]) .f-topbar-dropdown-item.active {
background: rgba(var(--teal-rgb), .15);
color: var(--teal);
}
/* ── City Multiselect ── */
.f-city-filter-wrap {
position: relative; z-index: 20;
display: flex; align-items: center;
padding: 10px 16px;
border-bottom: 1px solid var(--border);
background: var(--bg-surface);
}
.f-city-multiselect {
position: relative; flex: 1;
width: 100%; max-width: 440px; margin: 0 auto;
}
.f-city-ms-control {
display: flex; align-items: center; gap: 8px;
background: var(--bg-input);
border: 1px solid var(--border);
border-radius: 999px;
padding: 6px 14px;
min-height: 42px;
cursor: text;
transition: border-color .2s, box-shadow .2s;
}
.f-city-ms-control.open {
border-color: rgba(var(--teal-rgb), .5);
box-shadow: 0 0 0 3px rgba(var(--teal-rgb), .12);
}
.f-city-ms-icon {
width: 18px; height: 18px; flex-shrink: 0; color: var(--muted);
}
.f-city-ms-tags {
display: flex; flex-wrap: wrap; gap: 6px;
flex: 1; min-width: 0; align-items: center;
}
.f-city-ms-tag {
display: inline-flex; align-items: center; gap: 4px;
background: rgba(var(--teal-rgb), .1);
border: 1px solid rgba(var(--teal-rgb), .35);
color: var(--teal);
border-radius: 999px;
padding: 3px 10px;
font-size: 0.78rem; font-weight: 600;
white-space: nowrap;
}
.f-city-ms-tag-remove {
background: none; border: none; color: inherit; cursor: pointer;
padding: 0; display: flex; align-items: center; line-height: 0;
opacity: .7; transition: opacity .15s;
}
.f-city-ms-tag-remove:hover { opacity: 1; }
.f-city-ms-input {
flex: 1; min-width: 90px;
border: none; outline: none; background: transparent;
color: var(--text-primary);
font-family: var(--font); font-size: 0.9rem;
padding: 2px 0;
}
.f-city-ms-input::placeholder { color: var(--muted); }
.f-city-ms-clear {
background: none; border: none; cursor: pointer;
color: var(--muted); padding: 4px; border-radius: 6px;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0; transition: color .15s, background .15s;
}
.f-city-ms-clear:hover { color: var(--text-primary); background: var(--hover-bg); }
.f-city-ms-chevron {
width: 16px; height: 16px; flex-shrink: 0; color: var(--muted);
transition: transform .2s;
}
.f-city-ms-control.open .f-city-ms-chevron { transform: rotate(180deg); }
.f-city-ms-dropdown {
position: absolute; top: calc(100% + 6px); left: 0; right: 0;
background: var(--bg-surface-solid);
border: 1px solid var(--border);
border-radius: 12px;
box-shadow: 0 12px 32px rgba(0, 0, 0, .18);
max-height: 260px; overflow-y: auto;
z-index: 30; padding: 6px;
}
.f-city-ms-dropdown::-webkit-scrollbar { width: 4px; }
.f-city-ms-dropdown::-webkit-scrollbar-track { background: transparent; }
.f-city-ms-dropdown::-webkit-scrollbar-thumb { background: var(--muted2); border-radius: 2px; }
.f-city-ms-option {
display: flex; align-items: center; gap: 10px;
width: 100%; text-align: left;
padding: 9px 10px; border: none; border-radius: 8px;
background: none; color: var(--text-primary);
font-family: var(--font); font-size: 0.9rem; cursor: pointer;
transition: background .15s;
}
.f-city-ms-option:hover { background: var(--hover-bg); }
.f-city-ms-option.selected { color: var(--teal); font-weight: 600; }
.f-city-ms-option.f-city-ms-add { color: var(--teal); font-weight: 600; }
.f-city-ms-check {
width: 18px; height: 18px; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
border: 1.5px solid var(--border); border-radius: 5px;
font-size: 0.8rem; color: var(--teal);
}
.f-city-ms-option.selected .f-city-ms-check {
border-color: var(--teal);
background: rgba(var(--teal-rgb), .12);
}
.f-city-ms-option.f-city-ms-add .f-city-ms-check {
border-color: rgba(var(--teal-rgb), .5);
}
.f-city-ms-empty {
padding: 10px; text-align: center; color: var(--muted); font-size: 0.85rem;
}
/* ── Bottom Navigation (Telegram-style floating pill) ── */
.f-bottom-nav {
position: fixed; bottom: 12px;
left: 50%; transform: translateX(-50%);
display: flex; align-items: center; justify-content: space-evenly; gap: 32px;
padding: 6px 28px;
width: calc(100% - 24px);
max-width: 500px;
background: rgba(20, 20, 20, .55);
backdrop-filter: blur(30px) saturate(1.6); -webkit-backdrop-filter: blur(30px) saturate(1.6);
border: 1px solid rgba(255, 255, 255, .12);
border-radius: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, .3), inset 0 0.5px 0 rgba(255,255,255,.08);
z-index: 35;
}
:root:not([data-theme="dark"]) .f-bottom-nav {
background: rgba(255, 255, 255, .6);
border-color: rgba(0, 0, 0, .08);
box-shadow: 0 8px 32px rgba(0, 0, 0, .08), inset 0 0.5px 0 rgba(255,255,255,.7);
}
.f-bn-item {
position: relative;
display: flex; align-items: center; justify-content: center;
width: 44px; height: 40px;
border: none; background: none; cursor: pointer;
color: rgba(255, 255, 255, .6);
border-radius: 14px;
transition: color .15s, background .15s, transform .1s;
}
.f-bn-item:active { transform: scale(.9); }
.f-bn-item svg { width: 24px; height: 24px; }
.f-bn-item:hover { background: rgba(255, 255, 255, .1); color: rgba(255, 255, 255, .9); }
.f-bn-item.active { color: var(--teal); background: rgba(var(--teal-rgb), .15); }
:root:not([data-theme="dark"]) .f-bn-item {
color: rgba(0, 0, 0, .45);
}
:root:not([data-theme="dark"]) .f-bn-item:hover {
background: rgba(0, 0, 0, .06);
color: rgba(0, 0, 0, .75);
}
:root:not([data-theme="dark"]) .f-bn-item.active {
color: var(--teal);
background: rgba(var(--teal-rgb), .12);
}
/* Create button */
.f-bn-create {
width: 56px; height: 40px;
border-radius: 14px;
background: var(--teal);
color: #fff;
box-shadow: 0 2px 10px rgba(var(--teal-rgb), .35);
}
.f-bn-create:hover { background: var(--teal2); }
.f-bn-create svg { color: #fff; }
/* Profile avatar inside the nav */
.f-bn-profile .f-profile-avatar,
.f-bn-profile .f-profile-avatar-placeholder {
width: 32px; height: 32px;
border-width: 2px;
border-color: rgba(255, 255, 255, .45);
border-radius: 9px;
}
.f-bn-profile .f-profile-avatar-placeholder { font-size: .95rem; }
:root:not([data-theme="dark"]) .f-bn-profile .f-profile-avatar,
:root:not([data-theme="dark"]) .f-bn-profile .f-profile-avatar-placeholder {
border-color: rgba(0, 0, 0, .35);
}
.f-bn-item.f-bn-profile.active::before {
display: none;
}
.f-bn-item.f-bn-profile.active {
background: none;
}
/* Indicator: активные фильтры поиска */
.f-bn-dot {
position: absolute; top: 6px; right: 5px;
width: 7px; height: 7px; border-radius: 50%;
background: #ff3040;
box-shadow: 0 0 0 2px rgba(0, 0, 0, .4);
}
:root:not([data-theme="dark"]) .f-bn-dot {
box-shadow: 0 0 0 2px rgba(255, 255, 255, .8);
}
/* Search panel — видна только во вкладке «Поиск» (на десктопе всегда) */
.f-search-panel { display: none; }
.f-app.f-search-view .f-search-panel { display: block; }
/* Map view */
.f-mapview {
position: relative;
width: 100%; height: 100%;
flex: 1; min-height: 0;
border-radius: 12px;
overflow: hidden;
background: var(--bg-card);
}
.f-mapview-canvas {
width: 100%; height: 100%;
}
.f-mapview-status {
position: absolute; inset: 0;
display: flex; align-items: center; justify-content: center;
z-index: 5;
background: var(--bg-card);
}
.f-mapview-error {
font-size: .9rem; color: var(--err);
}
/* Geolocation hint on map view */
.f-mapview-geo {
position: absolute;
top: 12px; left: 50%; transform: translateX(-50%);
z-index: 6;
padding: 8px 14px; border-radius: 999px;
font-size: .8rem; font-weight: 600;
background: var(--bg-surface-solid);
border: 1px solid var(--border);
color: var(--text-primary);
box-shadow: 0 2px 10px rgba(0,0,0,.12);
white-space: nowrap;
}
.f-mapview-geo-info { color: var(--muted); }
.f-mapview-geo-warn { color: var(--err); border-color: rgba(237,73,86,.35); }
/* Back-to-feed button on map view */
.f-mapview-back {
position: absolute;
bottom: 24px; left: 50%;
transform: translateX(-50%);
z-index: 8;
display: flex; align-items: center; gap: 8px;
padding: 12px 22px;
border: 1px solid rgba(255, 255, 255, .12);
border-radius: 999px;
background: rgba(20, 20, 20, .55);
backdrop-filter: blur(30px) saturate(1.6); -webkit-backdrop-filter: blur(30px) saturate(1.6);
color: #fff;
font-family: var(--font);
font-size: .92rem; font-weight: 700;
cursor: pointer;
white-space: nowrap;
box-shadow: 0 8px 32px rgba(0,0,0,.3), inset 0 0.5px 0 rgba(255,255,255,.08);
transition: background .15s, border-color .15s, transform .15s, box-shadow .15s;
}
.f-mapview-back-icon { width: 18px; height: 18px; flex-shrink: 0; }
:root:not([data-theme="dark"]) .f-mapview-back {
background: rgba(255, 255, 255, .6);
border-color: rgba(0, 0, 0, .08);
color: var(--text-primary);
box-shadow: 0 8px 32px rgba(0,0,0,.08), inset 0 0.5px 0 rgba(255,255,255,.7);
}
.f-mapview-back:hover {
background: rgba(255, 255, 255, .22);
border-color: rgba(255, 255, 255, .28);
transform: translateX(-50%) translateY(-2px);
box-shadow: 0 10px 36px rgba(0,0,0,.35), inset 0 0.5px 0 rgba(255,255,255,.12);
}
:root:not([data-theme="dark"]) .f-mapview-back:hover {
background: rgba(255, 255, 255, .85);
border-color: rgba(0, 0, 0, .14);
}
.f-mapview-back:active {
transform: translateX(-50%) translateY(0);
box-shadow: 0 4px 16px rgba(0,0,0,.2), inset 0 0.5px 0 rgba(255,255,255,.08);
}
/* ── Feed Wrap + Scroll ── */
.f-wrap { display: flex; flex: 1; overflow: hidden; min-height: 0; }
/* Внешний контейнер ленты: не скроллится, лишь позиционирует слои.
Сверху — стеклянная шапка (абсолютный слой), под ней — маскированный
скролл-список; такой порядок даёт нужную иерархию z-index. */
.f-feed {
position: relative;
overflow: hidden;
flex: 1;
min-height: 0;
width: 100%;
max-width: 660px;
margin: 0 auto;
}
/* ── Слой затухания ленты ──
mask-image на самом контейнере списка (НЕ blur, НЕ opacity карточек):
верхние элементы, доезжающие до кромки под FeedTopBar, «растворяются».
Маска якорена к border-box скролл-контейнера, т.е. НЕ уезжает вместе
с карточками — зона затухания всегда под шапкой. Высота зоны задаётся
--feed-fade-height (управляется из React/ResizeObserver) и через
@property + transition анимируется при изменении.
padding-top синхронизирован с этой же переменной, чтобы первая карточка
в состоянии покоя не проваливалась под шапку. */
.f-feed-scroll {
position: absolute;
inset: 0;
overflow-y: scroll;
overflow-x: hidden;
overscroll-behavior: contain;
display: flex;
flex-direction: column;
gap: 16px;
padding: calc(var(--feed-fade-height, 48px) + 20px) 16px 20px;
-webkit-mask-image: linear-gradient(to bottom, transparent 0, black var(--feed-fade-height, 48px));
mask-image: linear-gradient(to bottom, transparent 0, black var(--feed-fade-height, 48px));
transition: --feed-fade-height 0.2s ease;
}
.f-feed-scroll::-webkit-scrollbar { width: 4px; }
.f-feed-scroll::-webkit-scrollbar-track { background: transparent; }
.f-feed-scroll::-webkit-scrollbar-thumb { background: var(--muted2); border-radius: 2px; }
/* ── Pull-to-refresh ──
Индикатор живёт внутри .f-feed-scroll первым элементом и своим
текущим ростом «вытягивает» ленту вниз. Чтобы он был виден на фоне
карточек во время жеста, на скролл-контейнер вешается класс
.f-ptr-active, снимающий mask (иначе верхняя зона «растворяется»). */
.f-ptr {
height: 0;
overflow: hidden;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
transition: height 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
/* Пока палец на экране — без transition, чтобы индикатор мгновенно
следовал за жестом и не «отставал» от толщины натяжения. */
.f-ptr.f-ptr-dragging {
transition: none;
}
/* Пружинистое возвращение к состоянию обновления: лёгкий довод/перелёт */
.f-ptr.f-ptr-refreshing {
transition: height 0.5s cubic-bezier(0.34, 1.3, 0.64, 1);
}
.f-ptr-scale {
flex-shrink: 0;
opacity: 0;
transform: scale(0.5);
transition:
transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) 0.03s,
opacity 0.25s ease 0.03s;
}
.f-ptr-visible .f-ptr-scale {
opacity: 1;
transform: scale(1);
}
.f-ptr-spinner {
width: 26px;
height: 26px;
border: 3px solid rgba(var(--teal-rgb), 0.25);
border-top-color: var(--teal);
border-radius: 50%;
flex-shrink: 0;
}
.f-ptr-refreshing .f-ptr-spinner {
animation: spin 0.7s linear infinite;
transition: transform 0.3s ease;
}
.f-feed-scroll.f-ptr-active {
-webkit-mask-image: none;
mask-image: none;
}
@media (min-width: 900px) {
.f-main-feed .f-topbar {
display: none;
}
.f-search-panel {
display: block;
}
.f-bottom-nav {
display: none;
}
}
@media (max-width: 900px) {
/* Мобильная версия: прижимаем логотип-капсулу влево (к кнопке-гамбургеру) */
.f-main-feed .f-topbar {
justify-content: flex-start;
}
.f-main-feed .f-logo-btn { margin-left: 64px; }
.f-main-feed .f-topbar-spacer { flex: 1; }
.f-mapview-back {
/* Поднимаем кнопку выше плавающей нижней навигации */
bottom: calc(84px + env(safe-area-inset-bottom));
}
.f-feed-scroll {
padding: calc(var(--feed-fade-height, 48px) + 10px) 10px calc(150px + env(safe-area-inset-bottom));
gap: 12px;
}
.f-post-btn {
padding: 8px 14px;
font-size: 0.78rem;
}
.f-login-btn {
padding: 6px 14px;
font-size: 0.78rem;
}
.f-filter-bar {
padding: 8px 12px;
gap: 6px;
}
.f-filter-btn {
padding: 7px 13px;
font-size: 0.82rem;
}
.f-city-filter-wrap { padding: 8px 12px; }
.f-city-ms-control { padding: 5px 12px; min-height: 38px; }
.f-city-ms-input { font-size: 0.85rem; }
.f-city-ms-tag { font-size: 0.75rem; padding: 2px 8px; }
.f-topbar-dropdown-menu {
padding: 6px 10px; gap: 5px;
margin-top: 4px; border-radius: 999px;
}
.f-topbar-dropdown-item { padding: 7px 13px; font-size: 0.8rem; }
}
@media (max-width: 600px) {
.f-post-btn {
padding: 7px 10px;
font-size: 0.7rem;
gap: 4px;
border-radius: 8px;
}
.f-post-btn span {
width: 12px;
height: 12px;
font-size: 0.7rem;
}
.f-login-btn {
padding: 4px 10px;
font-size: 0.7rem;
border-radius: 8px;
}
.f-filter-btn {
padding: 7px 12px;
font-size: 0.78rem;
}
}