4702614896
Мобилка: - Header: hide-on-scroll, мобильный burger-menu, тонкая адаптация - Hero: текст и кнопки оптимизированы под узкие экраны (full-width buttons) - ArticleCard featured: на мобилке в столбик, картинка сверху - Stats: компактная сетка 2x2 с уменьшенным шрифтом - Глобально: scroll-behavior smooth, safe-area-inset, tap targets 40px+ - prefers-reduced-motion respected Страница статьи: - ReadingProgress: прогресс-бар сверху при скролле - ScrollToTop: круглая кнопка наверху после 800px скролла - ShareButton: Web Share API на мобилках, копирование URL на десктопе - Related articles: подбираем по пересечению тегов (max 3) - Мобильная типографика: prose-base sm:prose-lg, leading-relaxed SEO/инфра: - /api/search: простой поиск по title/excerpt/tags с подсветкой и скорингом - SearchBox: оверлей с / хоткеем, дебаунс 250ms, мобиле-friendly - /rss.xml: полноценный RSS-фид - sitemap.xml: динамический через next sitemap() - robots.txt: динамический - viewport metadata + theme-color для светлой/тёмной темы - alternates rel=alternate type=application/rss+xml
120 lines
3.4 KiB
CSS
120 lines
3.4 KiB
CSS
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
/* === Theme tokens === */
|
|
:root {
|
|
--bg: 250 250 249;
|
|
--surface: 255 255 255;
|
|
--surface-2: 245 245 244;
|
|
--border: 231 229 228;
|
|
--ink: 28 25 23;
|
|
--mute: 120 113 108;
|
|
--accent: 16 185 129;
|
|
--accent-2: 5 150 105;
|
|
--accent-soft: 209 250 229;
|
|
}
|
|
|
|
.dark {
|
|
--bg: 10 10 10;
|
|
--surface: 20 20 20;
|
|
--surface-2: 28 28 28;
|
|
--border: 42 42 42;
|
|
--ink: 229 231 235;
|
|
--mute: 156 163 175;
|
|
--accent: 16 185 129;
|
|
--accent-2: 52 211 153;
|
|
--accent-soft: 6 78 59;
|
|
}
|
|
|
|
@layer base {
|
|
html {
|
|
background: rgb(var(--bg));
|
|
color: rgb(var(--ink));
|
|
scroll-behavior: smooth;
|
|
/* лучше для мобильных WebKit */
|
|
-webkit-text-size-adjust: 100%;
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
body {
|
|
@apply font-sans antialiased;
|
|
/* safe areas на iOS */
|
|
padding-left: env(safe-area-inset-left);
|
|
padding-right: env(safe-area-inset-right);
|
|
}
|
|
::selection { background: rgb(var(--accent) / 0.25); }
|
|
|
|
/* tap target минимум 44px для кнопок и ссылок в навигации/действиях */
|
|
button, a.btn {
|
|
min-height: 40px;
|
|
}
|
|
|
|
/* плавный скролл к якорям с учётом sticky header */
|
|
:where(h1, h2, h3, h4, [id]) {
|
|
scroll-margin-top: 80px;
|
|
}
|
|
}
|
|
|
|
@layer components {
|
|
.btn {
|
|
@apply inline-flex items-center justify-center gap-2 px-4 py-2 rounded-lg font-medium transition-all disabled:opacity-50 disabled:cursor-not-allowed;
|
|
}
|
|
.btn-primary { background: rgb(var(--accent)); color: white; }
|
|
.btn-primary:hover { background: rgb(var(--accent-2)); }
|
|
|
|
.btn-ghost { color: rgb(var(--mute)); }
|
|
.btn-ghost:hover { background: rgb(var(--surface-2)); color: rgb(var(--ink)); }
|
|
|
|
.container-narrow { @apply max-w-3xl mx-auto px-4; }
|
|
.container-wide { @apply max-w-6xl mx-auto px-4; }
|
|
|
|
.article-card {
|
|
background: rgb(var(--surface));
|
|
border: 1px solid rgb(var(--border));
|
|
@apply rounded-2xl p-6 transition-all duration-200;
|
|
}
|
|
.article-card:hover {
|
|
border-color: rgb(var(--accent) / 0.4);
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 10px 25px -10px rgb(0 0 0 / 0.08);
|
|
}
|
|
.dark .article-card:hover {
|
|
box-shadow: 0 10px 25px -10px rgb(0 0 0 / 0.5);
|
|
}
|
|
/* на мобилке hover-эффект transform не нужен (тач) */
|
|
@media (hover: none) {
|
|
.article-card:hover { transform: none; box-shadow: none; }
|
|
.article-card:active { transform: scale(0.99); }
|
|
}
|
|
|
|
.tag {
|
|
display: inline-block;
|
|
@apply text-xs px-2.5 py-1 rounded-full transition-colors whitespace-nowrap;
|
|
background: rgb(var(--surface-2));
|
|
color: rgb(var(--mute));
|
|
}
|
|
.tag:hover {
|
|
background: rgb(var(--accent-soft));
|
|
color: rgb(var(--accent-2));
|
|
}
|
|
|
|
.surface { background: rgb(var(--surface)); }
|
|
.surface-2 { background: rgb(var(--surface-2)); }
|
|
.ink { color: rgb(var(--ink)); }
|
|
.mute { color: rgb(var(--mute)); }
|
|
.accent { color: rgb(var(--accent)); }
|
|
.border-soft { border-color: rgb(var(--border)); }
|
|
.border-b-soft { border-bottom: 1px solid rgb(var(--border)); }
|
|
.border-t-soft { border-top: 1px solid rgb(var(--border)); }
|
|
}
|
|
|
|
/* Уважаем системную настройку "меньше анимаций" */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
html { scroll-behavior: auto; }
|
|
*, *::before, *::after {
|
|
animation-duration: 0.01ms !important;
|
|
animation-iteration-count: 1 !important;
|
|
transition-duration: 0.01ms !important;
|
|
}
|
|
}
|