Files
site-portfolio/public/css/main.css
T

5866 lines
149 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.
/* Базовые числа темы (переопределяются из localStorage и пикера) */
html {
--theme-h: 210;
--theme-s: 90;
--theme-l: 40;
--mesh-a-x: 2%;
--mesh-a-y: 2%;
--mesh-b-x: 50%;
--mesh-b-y: 2%;
--mesh-c-x: 98%;
--mesh-c-y: 2%;
--mesh-a-mult: 1;
--mesh-b-mult: 1;
--mesh-c-mult: 1;
--mesh-size-mult: 1.5;
--mesh-opacity-max: 1;
--mesh-opacity-min: 0;
--mesh-opacity-current: 1;
--neutral-accent-tint: 4%;
--accent: hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%));
--accent-square-2-h: calc((var(--theme-h) + 90) * 1deg);
--accent-square-3-h: calc((var(--theme-h) + 180) * 1deg);
--accent-square-4-h: calc((var(--theme-h) + 270) * 1deg);
--accent-square-2: hsl(var(--accent-square-2-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%));
--accent-square-3: hsl(var(--accent-square-3-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%));
--accent-square-4: hsl(var(--accent-square-4-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%));
--accent-text: var(--accent);
--accent-btn-radial-core: color-mix(
in hsl,
hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc((var(--theme-l) + 8) * 1%)),
white 6%
);
--accent-btn-radial-mid: color-mix(in hsl, var(--accent-analog), hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)) 45%);
--accent-btn-radial-edge: color-mix(in hsl, var(--accent-analog), black 15%);
/* Базовая шкала скруглений; карточки и кнопки используют один уровень */
--radius-sm: 8px;
--radius-md: 12px;
--radius-card: 14px;
--radius-btn: 14px;
--space: clamp(1rem, 4vw, 2.75rem);
/* Единый отступ fixed-элементов (FAB, плавающее меню, header) от краёв вьюпорта */
--edge-pad: clamp(0.5rem, 2vw, 1.4rem);
/* Контент на всю ширину экрана, поля только от --space и safe area */
--max: none;
--font: "Alice", system-ui, -apple-system, serif;
--font-accent: "Merriweather", var(--font);
--neutral-s: 5%;
/* Иконки UI: фиксированный размер по типу элемента */
--icon-fab: 1.25rem;
--icon-nav-overflow: 1.125rem;
--icon-contact: 1.5rem;
--icon-contact-meta: 1.125rem;
}
html[data-theme="dark"] {
color-scheme: dark;
--bg: color-mix(in hsl, hsl(var(--theme-h), 6%, 10%), var(--accent) var(--neutral-accent-tint));
--bg-elevated: color-mix(in hsl, hsl(var(--theme-h), 6%, 13%), var(--accent) var(--neutral-accent-tint));
--surface: color-mix(in hsl, hsl(var(--theme-h), 6%, 17%), var(--accent) var(--neutral-accent-tint));
--accent-text: color-mix(in hsl, var(--accent), white 10%);
--page-bg:
radial-gradient(
calc(48% * var(--mesh-size-mult)) calc(56% * var(--mesh-size-mult)) at var(--mesh-a-x) var(--mesh-a-y),
color-mix(in srgb, var(--accent-square-3) calc(52% * var(--mesh-a-mult)), var(--bg)) 0%,
transparent 62%
),
radial-gradient(
calc(48% * var(--mesh-size-mult)) calc(56% * var(--mesh-size-mult)) at var(--mesh-b-x) var(--mesh-b-y),
color-mix(in srgb, var(--accent-square-2) calc(44% * var(--mesh-b-mult)), var(--bg)) 0%,
transparent 64%
),
radial-gradient(
calc(52% * var(--mesh-size-mult)) calc(60% * var(--mesh-size-mult)) at var(--mesh-c-x) var(--mesh-c-y),
color-mix(in srgb, var(--accent-square-4) calc(36% * var(--mesh-c-mult)), var(--bg)) 0%,
transparent 68%
);
--text: hsl(var(--theme-h), 4%, 92%);
--text-muted: color-mix(in hsl, hsl(var(--theme-h), 5%, 58%), var(--accent) 6%);
--line: color-mix(in hsl, hsla(var(--theme-h), 8%, 48%, 0.18), var(--accent) 5%);
--accent-hover: color-mix(in hsl, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)), white 18%);
--accent-soft: color-mix(in hsl, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)), transparent 82%);
--shadow-strong: 0 24px 60px hsla(0, 0%, 0%, 0.45);
/* Карточки навыков: зона решений */
--skill-solutions-bg: color-mix(in srgb, var(--bg-elevated) 55%, var(--surface));
--skill-solutions-top-border: var(--line);
--skill-solution-separator: color-mix(in srgb, var(--line) 92%, var(--text-muted));
--img-ph-shine-peak: color-mix(in srgb, var(--text) 25%, var(--surface) 75%);
/* Кнопки primary: радиальный акцент + стекло (общие с .fab--primary) */
--btn-primary-border: color-mix(
in srgb,
hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)) 55%,
hsla(0, 0%, 100%, 0.12)
);
--btn-primary-bg: radial-gradient(
circle at 0% 0%,
color-mix(in hsl, var(--accent), white 10%) 0%,
var(--accent) 100%
);
--btn-primary-hover-bg: radial-gradient(
circle at 0% 0%,
color-mix(in hsl, var(--accent), white 14%) 0%,
var(--accent) 100%
);
/* flat: без «парения» и фаски — только обводка (--btn-primary-border) */
--btn-primary-shadow-flat: none;
--btn-primary-shadow-raised:
0 14px 34px color-mix(in srgb, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)) 22%, hsla(0, 0%, 0%, 0.5)),
inset 0 1px 0 hsla(0, 0%, 100%, 0.14),
inset 0 -1px 0 color-mix(in srgb, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)) 22%, transparent);
--btn-primary-shadow-hover:
0 16px 40px color-mix(in srgb, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)) 28%, hsla(0, 0%, 0%, 0.48)),
inset 0 1px 0 hsla(0, 0%, 100%, 0.18),
inset 0 -1px 0 color-mix(in srgb, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)) 18%, transparent);
--btn-primary-backdrop: blur(16px) saturate(135%);
--btn-primary-backdrop-hover: blur(18px) saturate(140%);
--btn-primary-sheen: linear-gradient(
155deg,
hsla(0, 0%, 100%, 0.1) 0%,
hsla(0, 0%, 100%, 0.03) 50%,
color-mix(in srgb, var(--accent-soft) 32%, transparent) 100%
);
}
html[data-radius="soft"] {
--radius-sm: 4px;
--radius-md: 6px;
--radius-card: 4px;
--radius-btn: 4px;
}
html[data-radius="strong"] {
--radius-sm: 11px;
--radius-md: 16px;
--radius-card: 20px;
--radius-btn: 20px;
}
html[data-font="merriweather"] {
--font: "Alice", system-ui, -apple-system, serif;
--font-accent: "Merriweather", var(--font);
}
html[data-font="geologica"] {
--font: "PT Sans", system-ui, -apple-system, sans-serif;
--font-accent: "Geologica", var(--font);
}
html[data-font="mono"] {
--font: "PT Mono", ui-monospace, "Cascadia Code", "Consolas", monospace;
--font-accent: "Source Code Pro", var(--font);
}
html[data-theme="light"] {
color-scheme: light;
--bg: color-mix(in hsl, hsl(var(--theme-h), 6%, 97%), var(--accent) var(--neutral-accent-tint));
--bg-elevated: color-mix(in hsl, hsl(var(--theme-h), 5%, 94%), var(--accent) var(--neutral-accent-tint));
--surface: color-mix(in hsl, hsl(var(--theme-h), 6%, 100%), var(--accent) var(--neutral-accent-tint));
--accent-text: color-mix(in hsl, var(--accent), black 14%);
--page-bg:
radial-gradient(
calc(48% * var(--mesh-size-mult)) calc(56% * var(--mesh-size-mult)) at var(--mesh-a-x) var(--mesh-a-y),
color-mix(in srgb, var(--accent-square-3) calc(38% * var(--mesh-a-mult)), var(--bg)) 0%,
transparent 62%
),
radial-gradient(
calc(48% * var(--mesh-size-mult)) calc(56% * var(--mesh-size-mult)) at var(--mesh-b-x) var(--mesh-b-y),
color-mix(in srgb, var(--accent-square-2) calc(32% * var(--mesh-b-mult)), var(--bg)) 0%,
transparent 64%
),
radial-gradient(
calc(52% * var(--mesh-size-mult)) calc(60% * var(--mesh-size-mult)) at var(--mesh-c-x) var(--mesh-c-y),
color-mix(in srgb, var(--accent-square-4) calc(26% * var(--mesh-c-mult)), var(--bg)) 0%,
transparent 68%
);
--text: hsl(var(--theme-h), 8%, 14%);
--text-muted: color-mix(in hsl, hsl(var(--theme-h), 7%, 40%), var(--accent) 7%);
--line: color-mix(in hsl, hsla(var(--theme-h), 10%, 38%, 0.16), var(--accent) 6%);
--accent-hover: color-mix(in hsl, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)), black 14%);
--accent-soft: color-mix(in hsl, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)), transparent 88%);
--shadow-strong: 0 20px 48px hsla(var(--theme-h), 20%, 20%, 0.08);
/* Зона решений: светлее чем --bg-elevated (~#efeff0), ближе к странице/белому */
--skill-solutions-bg: color-mix(in srgb, var(--surface) 82%, var(--bg) 18%);
--skill-solutions-top-border: color-mix(in srgb, var(--line), var(--text) 7%);
--skill-solution-separator: color-mix(in srgb, var(--line), var(--text) 11%);
--img-ph-shine-peak: color-mix(in srgb, var(--text) 15%, var(--surface) 85%);
--btn-primary-border: color-mix(in srgb, var(--accent) 48%, hsl(0 0% 0% / 0.16));
--btn-primary-bg: radial-gradient(
circle at 0% 0%,
color-mix(in hsl, var(--accent), white 10%) 0%,
var(--accent) 100%
);
--btn-primary-hover-bg: radial-gradient(
circle at 0% 0%,
color-mix(in hsl, var(--accent), white 14%) 0%,
var(--accent) 100%
);
--btn-primary-shadow-flat: none;
--btn-primary-shadow-raised:
0 14px 28px color-mix(in srgb, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)) 24%, hsla(0, 0%, 0%, 0.18)),
inset 0 1px 0 color-mix(in srgb, var(--accent) 40%, hsl(0 0% 100%) 60%),
inset 0 -1px 0 color-mix(in srgb, var(--accent) 35%, hsl(0 0% 0%) 65%);
--btn-primary-shadow-hover:
0 16px 34px color-mix(in srgb, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)) 28%, hsla(0, 0%, 0%, 0.2)),
inset 0 1px 0 color-mix(in srgb, var(--accent) 35%, hsl(0 0% 100%) 65%),
inset 0 -1px 0 color-mix(in srgb, var(--accent) 32%, hsl(0 0% 0%) 68%);
--btn-primary-backdrop: blur(10px) saturate(142%);
--btn-primary-backdrop-hover: blur(11px) saturate(148%);
--btn-primary-sheen: linear-gradient(
155deg,
color-mix(in srgb, var(--accent) 55%, hsl(0 0% 100%) 45%) 0%,
transparent 52%,
color-mix(in srgb, var(--accent) 70%, hsl(0 0% 0%) 30%) 100%
);
}
/* Фон и цвет на корне: без этого просвечивает белый фон документа и «хвосты» светлой темы */
html[data-theme="dark"],
html[data-theme="light"] {
min-height: 100%;
background-color: var(--bg);
color: var(--text);
}
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
/* запас под sticky header; точнее задаётся --header-offset из JS */
scroll-padding-top: var(--header-offset, 4.25rem);
}
body {
margin: 0;
min-height: 100dvh;
font-family: var(--font);
font-size: 1rem;
line-height: 1.55;
color: var(--text);
background-color: transparent;
position: relative;
-webkit-font-smoothing: antialiased;
}
.page-mesh-bg {
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
overflow: hidden;
}
html[data-mesh-bg="off"] .page-mesh-bg {
visibility: hidden;
}
.page-mesh-bg::before {
content: "";
position: absolute;
inset: 0;
background-image: var(--page-bg);
background-repeat: no-repeat;
background-size: 100% 100dvh;
background-position: top center;
background-blend-mode: normal;
opacity: var(--mesh-opacity-current);
}
.mesh-panel {
position: fixed;
left: max(0.75rem, env(safe-area-inset-left, 0px));
bottom: max(0.75rem, env(safe-area-inset-bottom, 0px));
z-index: 120;
width: min(230px, calc(100vw - 1.5rem));
padding: 0.65rem 0.7rem;
border-radius: var(--radius-md);
border: 1px solid var(--line);
}
.mesh-panel__title {
margin: 0 0 0.5rem;
font-size: 0.72rem;
line-height: 1.2;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-muted);
}
.mesh-panel__row {
display: grid;
grid-template-columns: 5.2rem minmax(0, 1fr) 2.3rem;
align-items: center;
gap: 0.45rem;
}
.mesh-panel__row + .mesh-panel__row {
margin-top: 0.35rem;
}
.mesh-panel__row--toggle {
grid-template-columns: 5.2rem auto;
}
.mesh-panel__label {
font-size: 0.72rem;
line-height: 1.25;
color: var(--text-muted);
}
.mesh-panel__value {
font-size: 0.68rem;
line-height: 1;
color: var(--text-muted);
text-align: right;
font-variant-numeric: tabular-nums;
}
.mesh-panel input[type="checkbox"] {
width: 1rem;
height: 1rem;
margin: 0;
accent-color: var(--accent-text);
}
.mesh-panel input[type="range"] {
width: 100%;
margin: 0;
accent-color: var(--accent-text);
}
#main {
color: var(--text);
background-color: transparent;
margin-top: 0;
}
img {
max-width: 100%;
height: auto;
display: block;
}
/* Заглушка: ::before — статичный фон, ::after — один бегущий блеск */
.has-img-loading {
position: relative;
overflow: hidden;
background-color: transparent;
}
.has-img-loading::before {
content: "";
position: absolute;
inset: 0;
z-index: 0;
pointer-events: none;
background-color: color-mix(in srgb, var(--text-muted) 11%, var(--surface));
}
/* У обёрток со своим фоном — не дублируем серый слой */
.mp-card__media.has-img-loading::before,
.case-media-gallery__item.has-img-loading::before {
content: none;
}
.has-img-loading::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 260%;
height: 100%;
z-index: 1;
pointer-events: none;
/* Узкая полоса блеска; слой шире тайла — без обрезки краёв градиента */
background-image: linear-gradient(
105deg,
transparent 0%,
transparent 40%,
var(--img-ph-shine-peak) 50%,
transparent 60%,
transparent 100%
);
background-repeat: no-repeat;
background-size: 100% 100%;
background-position: 50% 50%;
transform: translateX(-100%);
animation: img-ph-shine-sweep 3.4s linear infinite;
}
.has-img-loading img.is-img-loading {
opacity: 0;
}
.has-img-loading img:not(.is-img-loading) {
opacity: 1;
transition: opacity 0.28s ease;
}
@keyframes img-ph-shine-sweep {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(38.5%);
}
}
@media (prefers-reduced-motion: reduce) {
.has-img-loading::after {
content: none;
}
}
.img-ph-demo {
max-width: 18rem;
aspect-ratio: 16 / 9;
margin: 0.85rem 0 1.2rem;
}
a {
color: var(--accent-text);
text-decoration-thickness: 1px;
text-underline-offset: 0.2em;
}
a:hover {
color: var(--accent-hover);
}
/* Только «текстовые» ссылки: .btn / .fab / .logo задают цвет сами, иначе :visited перебивает --on-accent */
a:visited:not(.btn):not(.fab):not(.logo):not(.skip-link) {
color: color-mix(in hsl, var(--accent) 40%, var(--text) 60%);
}
a:visited:not(.btn):not(.fab):not(.logo):not(.skip-link):hover {
color: color-mix(in hsl, var(--accent-hover) 50%, var(--text) 50%);
}
::selection {
background: var(--accent-soft);
color: var(--text);
}
.skip-link {
position: absolute;
left: -9999px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
.skip-link:focus {
position: fixed;
left: var(--space);
top: var(--space);
z-index: 100;
width: auto;
height: auto;
padding: 0.75rem 1rem;
background: var(--accent);
color: var(--on-accent);
font-weight: 600;
border-radius: var(--radius-md);
}
.header {
position: relative;
top: 0;
z-index: 50;
height: 0;
background: transparent;
transition: background 0.25s ease;
}
/* Обычный (не плавающий) header спрятан — виден только при скролле (.header--scrolled) */
.header:not(.header--scrolled) .header__inner {
display: none;
}
.header--scrolled {
background: transparent;
height: 0;
overflow: visible;
}
.header__inner {
max-width: var(--max);
width: 100%;
margin: 0 auto;
padding: 0.8rem;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
flex-wrap: nowrap;
}
.header--scrolled .header__inner {
position: fixed;
top: var(--edge-pad);
left: auto;
right: var(--edge-pad);
width: fit-content;
max-width: min(
980px,
calc(
100% - max(var(--space), env(safe-area-inset-left, 0px)) -
max(var(--space), env(safe-area-inset-right, 0px))
)
);
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 0;
padding: 0.8rem;
border: 1px solid var(--line);
border-radius: calc(var(--radius-card) * 0.7);
background: var(--bg-elevated);
box-shadow: 0 16px 38px hsla(0, 0%, 0%, 0.2);
animation: header-float-in 0.24s cubic-bezier(0.22, 0.8, 0.24, 1);
justify-content: flex-start;
gap: 0.75rem;
}
@keyframes header-float-in {
from {
transform: translateY(-118%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.header--scrolled .logo {
width: 2.15rem;
height: 2.15rem;
font-size: 0.75rem;
}
.header--scrolled .nav {
font-size: 0.84rem;
gap: 0.45rem 0.72rem;
}
.header--scrolled .nav-more__btn {
width: 32px;
height: 32px;
}
.header--scrolled .header__cluster {
flex: 0 1 auto;
margin-left: 0;
}
/* Переключатель языка в футере: лаконичная текстовая группа RU / EN */
.lang-switch {
display: inline-flex;
align-items: center;
gap: 0.45rem;
font-size: inherit;
line-height: 1;
}
.lang-switch__btn {
appearance: none;
margin: 0;
padding: 0;
border: 0;
background: none;
font: inherit;
font-weight: 400;
letter-spacing: 0.04em;
color: var(--accent);
text-decoration: none;
cursor: pointer;
transition: color 0.15s ease;
}
.lang-switch__btn:hover,
.lang-switch__btn:focus-visible {
color: var(--text);
}
.lang-switch__btn[aria-current="true"] {
color: var(--accent);
}
/* разделитель между языками */
.lang-switch__btn:not(:last-child)::after {
content: "/";
margin-left: 0.45rem;
color: var(--border);
font-weight: 400;
}
.header__cluster {
display: flex;
flex-wrap: nowrap;
align-items: center;
justify-content: flex-end;
gap: 0.5rem;
margin-left: auto;
flex: 1 1 auto;
min-width: 0;
/* overflow не hidden: иначе обрезается .nav-more__menu (position:absolute снизу) */
overflow: visible;
}
.logo {
display: grid;
flex-shrink: 0;
place-items: center;
width: 2.5rem;
height: 2.5rem;
border-radius: var(--radius-sm);
background: var(--accent-soft);
color: var(--accent-text);
font-weight: 700;
font-size: 0.85rem;
letter-spacing: 0.02em;
text-decoration: none;
}
.logo:hover {
color: var(--accent-hover);
}
.logo:visited {
color: var(--accent-text);
}
.nav {
display: flex;
flex-wrap: nowrap;
justify-content: flex-end;
gap: 0.65rem 0.95rem;
font-size: 0.9rem;
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
}
.nav a {
color: var(--text-muted);
text-decoration: none;
font-weight: 600;
letter-spacing: 0.02em;
white-space: nowrap;
}
.nav a:visited {
color: var(--text-muted);
}
.nav a:hover {
color: var(--text);
}
/* --- Overflow навигации + панель темы --- */
.nav-more {
position: relative;
flex-shrink: 0;
}
.nav-more__btn {
display: grid;
place-items: center;
width: 36px;
height: 36px;
border: 1px solid var(--line);
border-radius: var(--radius-sm);
background: var(--surface);
color: var(--text-muted);
cursor: pointer;
}
.nav-more__btn:hover {
color: var(--text);
background: var(--accent-soft);
}
.nav-more__btn svg {
width: var(--icon-nav-overflow);
height: var(--icon-nav-overflow);
display: block;
flex-shrink: 0;
}
.nav-more__btn[aria-expanded="true"] {
color: var(--accent-text);
}
/* Два отдельных контейнера: док (шапка) и плавающий (body). Общая сетка ссылок — без общего класса «menu». */
.nav-more__dock,
.nav-more__floating {
min-width: 12rem;
padding: 0.35rem;
border-radius: var(--radius-md);
border: 1px solid var(--line);
box-shadow: var(--shadow-strong);
}
.nav-more__dock {
position: absolute;
top: calc(100% + 6px);
right: 0;
z-index: 90;
background: var(--bg-elevated);
}
/* Плавающая панель: fixed + координаты из JS; фон — токены v12-glass внизу файла */
#nav-more-menu-floating.nav-more__floating {
position: fixed;
top: var(--nav-more-menu-top, 0px);
left: var(--nav-more-menu-left, 0px);
right: auto;
z-index: 140;
margin: 0;
}
.nav-more__dock a,
.nav-more__floating a {
display: block;
padding: 0.5rem 0.6rem;
border-radius: var(--radius-sm);
color: var(--text-muted);
text-decoration: none;
font-weight: 500;
}
.nav-more__dock a:hover,
.nav-more__floating a:hover {
color: var(--text);
background: var(--accent-soft);
}
.fab[data-theme-panel-btn] {
display: grid;
place-items: center;
}
.theme-panel-fab__icon {
grid-area: 1 / 1;
line-height: 1;
color: inherit;
pointer-events: none;
}
.theme-panel-fab__icon--close {
display: block;
width: var(--icon-fab);
height: var(--icon-fab);
}
.theme-panel-fab__icon--open-hide {
display: block;
flex-shrink: 0;
width: var(--icon-fab);
height: var(--icon-fab);
background: currentColor;
mask-image: url("../assets/shared/icons/design_edit.svg");
-webkit-mask-image: url("../assets/shared/icons/design_edit.svg");
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
}
.theme-mode-seg .theme-mode-seg__ico {
display: block;
width: var(--icon-fab);
height: var(--icon-fab);
background: currentColor;
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
}
.theme-mode-seg__ico--system {
mask-image: url("../assets/shared/icons/system.svg");
-webkit-mask-image: url("../assets/shared/icons/system.svg");
}
.theme-mode-seg__ico--light {
mask-image: url("../assets/shared/icons/sun.svg");
-webkit-mask-image: url("../assets/shared/icons/sun.svg");
}
.theme-mode-seg__ico--dark {
mask-image: url("../assets/shared/icons/moon.svg");
-webkit-mask-image: url("../assets/shared/icons/moon.svg");
}
.fab-primary__ico {
display: block;
width: var(--icon-fab);
height: var(--icon-fab);
background: currentColor;
mask-image: url("../assets/shared/icons/chat_start.svg");
-webkit-mask-image: url("../assets/shared/icons/chat_start.svg");
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
}
[data-theme-panel-btn][aria-expanded="true"] .theme-panel-fab__icon--open-hide {
display: none;
}
[data-theme-panel-btn][aria-expanded="false"] .theme-panel-fab__icon--close {
display: none;
}
/* Панель темы привязана к FAB настроек: абсолют внутри .theme-panel-fab-wrap */
.theme-panel-fab-wrap {
position: relative;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.theme-picker__panel {
position: absolute;
right: 0;
bottom: calc(100% + 0.5rem);
width: min(calc(320px + 2.2rem), calc(100vw - 2 * var(--space)));
max-height: min(85vh, calc(100dvh - 5rem));
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding: 1rem 1.1rem;
border-radius: var(--radius-md);
border: 1px solid var(--line);
background: var(--bg-elevated);
box-shadow: var(--shadow-strong);
z-index: 1;
}
.theme-picker__panel[hidden] {
display: none !important;
}
.fab-stack {
position: fixed;
right: var(--edge-pad);
bottom: var(--edge-pad);
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 0.6rem;
z-index: 92;
}
.fab {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 3rem;
min-height: 3rem;
padding: 0.7rem 1rem;
border-radius: 999px;
border: 1px solid var(--line);
text-decoration: none;
color: var(--text);
background: var(--surface);
box-shadow: var(--shadow-strong);
cursor: pointer;
transition:
background-color 0.15s ease,
color 0.15s ease,
border-color 0.15s ease,
box-shadow 0.15s ease;
}
.fab--primary {
position: relative;
isolation: isolate;
overflow: hidden;
width: 3rem;
min-width: 3rem;
min-height: 3rem;
padding: 0;
border: 1px solid var(--btn-primary-border);
background: var(--btn-primary-bg);
backdrop-filter: var(--btn-primary-backdrop);
-webkit-backdrop-filter: var(--btn-primary-backdrop);
box-shadow: var(--btn-primary-shadow-raised);
color: var(--on-accent);
font-weight: 600;
transition:
background 0.2s ease,
color 0.15s ease,
border-color 0.15s ease,
box-shadow 0.2s ease,
backdrop-filter 0.2s ease;
}
.fab--primary::after {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
z-index: 0;
background: var(--btn-primary-sheen);
}
html[data-theme="light"] .fab--primary::after {
opacity: 0.42;
}
.fab--primary::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
background: radial-gradient(
circle 3rem at var(--btn-shine-x, 50%) var(--btn-shine-y, 50%),
color-mix(in hsl, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)), white 52%) 0%,
transparent 55%
);
opacity: 0;
transition: opacity 0.2s ease;
pointer-events: none;
z-index: 2;
mix-blend-mode: soft-light;
}
.fab--primary:hover::before {
opacity: 0.58;
}
a.fab--primary:visited {
color: var(--on-accent);
background: var(--btn-primary-bg);
}
.fab--primary > * {
position: relative;
z-index: 3;
}
.fab--primary:hover {
color: var(--on-accent);
border-color: var(--btn-primary-border);
background: var(--btn-primary-hover-bg);
backdrop-filter: var(--btn-primary-backdrop-hover);
-webkit-backdrop-filter: var(--btn-primary-backdrop-hover);
box-shadow: var(--btn-primary-shadow-hover);
}
.fab--primary:focus-visible {
color: var(--on-accent);
border-color: var(--btn-primary-border);
background: var(--btn-primary-hover-bg);
backdrop-filter: var(--btn-primary-backdrop-hover);
-webkit-backdrop-filter: var(--btn-primary-backdrop-hover);
box-shadow: var(--btn-primary-shadow-hover);
outline: 2px solid color-mix(in hsl, var(--accent) 65%, var(--text));
outline-offset: 2px;
}
.fab--secondary {
width: 3rem;
padding: 0;
color: var(--text-muted);
}
a.fab--secondary:visited {
color: var(--text-muted);
}
.fab--secondary:hover {
color: var(--accent-text);
background: var(--bg-elevated);
border-color: color-mix(in hsl, var(--accent) 38%, var(--line));
box-shadow: var(--shadow-strong);
}
.fab--secondary:focus-visible {
color: var(--accent-text);
background: var(--bg-elevated);
border-color: color-mix(in hsl, var(--accent) 45%, var(--line));
outline: 2px solid color-mix(in hsl, var(--accent) 50%, var(--line));
outline-offset: 2px;
}
/* ── PDF download FAB ── */
.fab-primary__ico--pdf {
mask-image: url("../assets/shared/icons/cv.svg");
-webkit-mask-image: url("../assets/shared/icons/cv.svg");
}
/* ── Print FAB ── */
.fab-secondary__ico--print {
display: block;
width: var(--icon-fab);
height: var(--icon-fab);
background: currentColor;
mask-image: url("../assets/shared/icons/printer.svg");
-webkit-mask-image: url("../assets/shared/icons/printer.svg");
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
}
.fab--label {
width: auto;
padding: 0.65rem 1.1rem;
gap: 0.5rem;
}
.fab__label {
font-size: 0.85rem;
font-weight: 600;
line-height: 1;
white-space: nowrap;
}
.theme-picker__stack {
display: flex;
flex-direction: column;
gap: 1.1rem;
}
.theme-picker__section {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.theme-picker__section-title {
margin: 0;
font-size: 0.68rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.07em;
color: var(--text-muted);
}
/* Segmented: слабое / среднее / сильное скругление */
.radius-seg {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.4rem;
padding: 0;
border: none;
background: transparent;
}
.radius-seg--two {
grid-template-columns: repeat(2, 1fr);
}
.radius-seg__btn {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-width: 0;
padding: 0.5rem 0.25rem;
border: 1px solid var(--line);
border-radius: var(--radius-sm);
background: transparent;
color: var(--text-muted);
cursor: pointer;
font-family: inherit;
transition:
background 0.15s ease,
color 0.15s ease,
border-color 0.15s ease,
box-shadow 0.15s ease;
}
.radius-seg__btn:hover {
color: var(--text);
border-color: color-mix(in srgb, var(--accent) 40%, var(--line));
}
.radius-seg__btn[aria-checked="true"] {
background: var(--accent-soft);
color: var(--accent-text);
border-color: color-mix(in srgb, var(--accent) 55%, var(--line));
box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent);
}
.theme-font-seg__btn {
min-height: 44px;
padding: 0.5rem 0.25rem;
}
.theme-font-seg__label {
display: block;
font-size: 0.78rem;
line-height: 1.15;
letter-spacing: 0.01em;
}
.theme-font-seg__btn[data-font-option="merriweather"] .theme-font-seg__label {
font-family: "Merriweather", serif;
}
.theme-font-seg__btn[data-font-option="mono"] .theme-font-seg__label {
font-family: "Source Code Pro", monospace;
}
.theme-font-seg__btn[data-font-option="geologica"] .theme-font-seg__label {
font-family: "Geologica", sans-serif;
}
.theme-mesh-bg-seg__btn {
min-height: 44px;
padding: 0.5rem 0.35rem;
}
.theme-mesh-bg-seg__label {
display: block;
font-size: 0.78rem;
line-height: 1.15;
font-weight: 600;
letter-spacing: 0.01em;
}
.radius-seg__viz {
display: grid;
place-items: center;
flex-shrink: 0;
width: 44px;
height: 44px;
}
.radius-seg__arc {
display: block;
width: 28px;
height: 28px;
box-sizing: border-box;
border-left: 2px solid currentColor;
border-top: 2px solid currentColor;
opacity: 0.88;
}
.radius-seg__arc--soft {
border-top-left-radius: 4px;
}
.radius-seg__arc--medium {
border-top-left-radius: 14px;
}
.radius-seg__arc--strong {
border-top-left-radius: 26px;
}
/* Colorpicker: S/L 16:9 + горизонтальный оттенок, общая ширина блоков */
.colorpicker {
display: flex;
flex-direction: column;
gap: 0.75rem;
width: min(100%, 320px);
margin-inline: auto;
}
.colorpicker__plane-box {
position: relative;
width: 100%;
aspect-ratio: 16 / 9;
border-radius: var(--radius-md);
overflow: hidden;
border: 1px solid var(--line);
touch-action: none;
}
.colorpicker__plane {
display: block;
width: 100%;
height: 100%;
cursor: crosshair;
vertical-align: middle;
}
.colorpicker__knob {
position: absolute;
width: 20px;
height: 20px;
margin: -10px 0 0 -10px;
border: 1px solid hsla(0, 0%, 0%, 0.32);
border-radius: 50%;
background: #fff;
box-shadow: inset 0 0 0 1px hsla(0, 0%, 100%, 0.45);
pointer-events: none;
}
.colorpicker__hue-sr {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
clip-path: inset(50%);
white-space: nowrap;
border: 0;
}
.colorpicker__hue-wrap {
position: relative;
width: 100%;
box-sizing: border-box;
padding: 0;
line-height: 0;
}
.colorpicker__hue {
-webkit-appearance: none;
appearance: none;
display: block;
width: 100%;
/* Высота ≈ thumb (20px), без лишней «полки» под трек */
height: 22px;
margin: 0;
padding: 0;
cursor: pointer;
background: transparent;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
}
.colorpicker__hue::-webkit-slider-runnable-track {
height: 14px;
border-radius: 7px;
border: 1px solid var(--line);
background: linear-gradient(
to right,
hsl(0 100% 50%),
hsl(60 100% 45%),
hsl(120 100% 40%),
hsl(180 100% 40%),
hsl(240 100% 52%),
hsl(300 100% 50%),
hsl(360 100% 50%)
);
}
.colorpicker__hue::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
margin-top: -4px;
border-radius: 50%;
border: 1px solid hsla(0, 0%, 0%, 0.32);
background: #fff;
box-shadow: inset 0 0 0 1px hsla(0, 0%, 100%, 0.45);
}
.colorpicker__hue::-moz-range-track {
height: 14px;
border-radius: 7px;
border: 1px solid var(--line);
background: linear-gradient(
to right,
hsl(0 100% 50%),
hsl(60 100% 45%),
hsl(120 100% 40%),
hsl(180 100% 40%),
hsl(240 100% 52%),
hsl(300 100% 50%),
hsl(360 100% 50%)
);
}
.colorpicker__hue::-moz-range-thumb {
width: 20px;
height: 20px;
border-radius: 50%;
border: 1px solid hsla(0, 0%, 0%, 0.32);
background: #fff;
box-shadow: inset 0 0 0 1px hsla(0, 0%, 100%, 0.45);
}
.hero {
padding: calc(2 * clamp(2.5rem, 6vw, 4.5rem)) calc(2 * max(var(--space), env(safe-area-inset-right, 0px))) calc(2 * clamp(2rem, 5vw, 3.5rem)) calc(2 * max(var(--space), env(safe-area-inset-left, 0px)));
}
.hero__grid {
max-width: var(--max);
margin: 0 auto;
display: grid;
grid-template-columns: 1fr;
gap: clamp(2rem, 5vw, 3rem);
align-items: center;
}
@media (min-width: 860px) {
.hero__grid {
grid-template-columns: 1.15fr 0.85fr;
}
}
.hero__eyebrow {
margin: 0 0 0.5rem;
font-size: 0.78rem;
font-weight: 700;
color: var(--text-muted);
letter-spacing: 0.14em;
text-transform: uppercase;
}
.hero__title {
margin: 0 0 1rem;
font-family: var(--font-accent);
font-size: clamp(3.1rem, 7.2vw, 4.85rem);
font-weight: 700;
line-height: 1.2;
letter-spacing: -0.02em;
color: var(--text);
}
html[data-font="geologica"] .hero__title {
line-height: 1;
}
html[data-font="mono"] .hero__title {
line-height: 1;
}
.hero-rotator {
position: relative;
display: inline-flex;
align-items: baseline;
vertical-align: baseline;
min-width: 8.5ch;
min-height: 0.92em;
}
.hero-rotator__word {
display: inline-block;
min-width: 100%;
white-space: pre;
color: var(--accent-text);
letter-spacing: var(--hero-slot-spacing, 0);
transition: letter-spacing 0.26s ease;
}
.hero-rotator__char {
display: inline-block;
transition: color 0.12s linear;
}
/* Превью кейса: pages/cases/*.html (без полной оболочки главной) */
.case-page__h1 {
margin: 0 0 0.5rem;
font-family: var(--font-accent);
font-size: clamp(2rem, 3.9vw, 2.9rem);
font-weight: 700;
line-height: 1.2;
color: var(--text);
text-transform: none;
letter-spacing: -0.02em;
}
.case-article h2:not(.section__title),
.case-article h3:not(.section__title):not(.mp-card__title) {
font-family: var(--font-accent);
}
.case-article h3:not(.section__title):not(.mp-card__title) {
margin: 3.25rem 0 1.5rem;
}
.case-article h2 + h3:not(.section__title):not(.mp-card__title) {
margin-top: 2.25rem;
}
.case-article h3 + h3:not(.section__title):not(.mp-card__title) {
margin-top: 3.5rem;
}
.case-article figure + h3:not(.section__title):not(.mp-card__title) {
margin-top: 4rem;
}
.case-page__sub {
margin: 0 0 1.25rem;
font-size: clamp(1.5rem, 2vw, 1.65rem);
color: var(--text-muted);
font-weight: 500;
}
.case-page__code {
font-size: 0.88rem;
word-break: break-all;
}
/* Inline-код в лонгридах кейса (`metric_name` и т.п.) */
.case-article code {
font-family: ui-monospace, "Cascadia Code", "Consolas", "Courier New", monospace;
font-size: 0.86em;
font-weight: 400;
padding: 0.1em 0.4em;
border-radius: 6px;
vertical-align: 0.04em;
color: var(--accent-text);
background: color-mix(in srgb, var(--bg) 42%, var(--surface) 58%);
border: 1px solid color-mix(in srgb, var(--line) 65%, transparent);
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
word-break: break-word;
}
.case-article pre {
max-width: 100%;
overflow: auto;
padding: 0.9rem 1rem;
border-radius: var(--radius-sm);
background: color-mix(in srgb, var(--bg) 32%, var(--surface) 68%);
border: 1px solid var(--line);
}
.case-article pre code {
padding: 0;
border: none;
background: none;
font-size: inherit;
font-weight: inherit;
vertical-align: baseline;
word-break: normal;
white-space: pre;
color: inherit;
}
/* Внутренние страницы: быстрый флаг скрытия хедера (легко вернуть, убрав класс). */
body.case-page--hide-header .header {
display: none;
}
.case-links-grid {
display: grid;
gap: 0.75rem;
margin: 0.85rem 0 1.15rem;
}
.case-link-card {
display: grid;
grid-template-columns: 96px minmax(0, 1fr);
gap: 1rem;
align-items: center;
padding: 1rem 1.1rem;
border-radius: var(--radius-md);
border: 1px solid var(--line);
background: color-mix(in srgb, var(--surface) 82%, transparent);
text-decoration: none;
color: inherit;
transition:
border-color 0.2s ease,
box-shadow 0.2s ease,
transform 0.2s ease;
}
.case-link-card:hover,
.case-link-card:focus-visible {
border-color: var(--accent);
box-shadow: 0 8px 24px color-mix(in srgb, var(--accent) 18%, transparent);
transform: translateY(-1px);
}
.case-link-card:focus-visible {
outline: 2px solid color-mix(in srgb, var(--accent) 44%, transparent);
outline-offset: 2px;
}
.case-link-card__media {
display: block;
width: 96px;
height: 72px;
border-radius: calc(var(--radius-md) - 4px);
overflow: hidden;
border: 1px solid var(--line);
background: color-mix(in srgb, var(--surface-soft) 70%, transparent);
}
.case-link-card__media img {
display: block;
width: 100%;
height: 100%;
margin: 0;
object-fit: cover;
}
.case-link-card__body {
min-width: 0;
display: grid;
gap: 0.2rem;
}
.case-link-card__title {
font-weight: 700;
font-size: 0.98rem;
line-height: 1.2;
color: var(--text);
}
.case-link-card__meta {
font-size: 0.88rem;
line-height: 1.35;
color: var(--text-muted);
}
.case-link-card__url {
font-size: 0.78rem;
line-height: 1.2;
color: color-mix(in srgb, var(--accent) 72%, var(--text));
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.case-link-card--favicon {
grid-template-columns: 24px minmax(0, 1fr);
align-items: center;
}
.case-link-card--favicon .case-link-card__media {
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
min-width: 24px;
min-height: 24px;
border-radius: 6px;
padding: 0;
background: color-mix(in srgb, var(--surface) 64%, var(--accent) 7%);
overflow: hidden;
flex-shrink: 0;
line-height: 0;
box-sizing: border-box;
}
.case-link-card--favicon .case-link-card__media img {
display: block;
width: 100%;
height: 100%;
max-width: none;
max-height: none;
margin: 0;
object-fit: contain;
object-position: center;
}
/* Картинки в кейсах: 3 ширины + fullscreen viewer */
.case-media {
margin: 0.85rem 0 1.2rem;
}
.case-media img {
display: block;
height: auto;
}
.case-media .plyr {
border-radius: 0;
overflow: hidden;
--plyr-color-main: var(--accent);
--plyr-video-range-track-background: color-mix(in srgb, var(--text-muted) 36%, var(--surface));
--plyr-control-spacing: 0.75rem;
--plyr-control-icon-size: 14px;
--plyr-video-control-color: var(--text-muted);
--plyr-video-control-color-hover: var(--accent);
--plyr-control-radius: 999px;
--plyr-menu-color: var(--text);
--plyr-menu-background: color-mix(in srgb, var(--surface) 92%, var(--bg) 8%);
--plyr-tooltip-background: color-mix(in srgb, var(--surface) 92%, var(--bg) 8%);
--plyr-tooltip-color: var(--text);
--plyr-video-controls-background: linear-gradient(
to top,
color-mix(in srgb, var(--bg) 72%, transparent) 0%,
color-mix(in srgb, var(--bg) 40%, transparent) 42%,
transparent 100%
);
}
.case-media .plyr--video .plyr__controls {
margin: 0;
padding: 0;
min-height: 3rem;
width: 100%;
border-radius: 0;
border: 0;
border-top: 1px solid color-mix(in srgb, var(--line) 92%, transparent);
background: color-mix(in srgb, var(--surface) 84%, var(--bg) 16%);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
align-items: center;
}
.case-media .plyr--video .plyr__controls .plyr__control {
height: calc(3rem - 2px);
min-height: calc(3rem - 2px);
width: calc(3rem - 2px);
min-width: calc(3rem - 2px);
border-radius: 0;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
}
/* Hover на кнопках панели плеера: только иконка в акцент, фон не меняем */
.case-media .plyr--video .plyr__controls .plyr__control:hover {
background: color-mix(in srgb, var(--surface) 84%, var(--bg) 16%);
color: var(--accent);
}
.case-media .plyr--video .plyr__controls .plyr__control svg {
fill: currentColor;
}
/* Кнопка Play по центру: normal как у кнопок панели, hover — только иконка в акцент */
.case-media .plyr--video .plyr__control--overlaid {
background: color-mix(in srgb, var(--surface) 84%, var(--bg) 16%);
color: var(--text-muted);
border: none;
}
.case-media .plyr--video .plyr__control--overlaid:hover {
background: color-mix(in srgb, var(--surface) 84%, var(--bg) 16%);
color: var(--accent);
}
.case-media .plyr--video .plyr__controls .plyr__progress__container {
height: auto;
display: flex;
align-items: center;
min-width: 0;
flex: 1 1 auto;
}
.case-media .plyr--video .plyr__controls .plyr__progress {
flex: 1 1 auto;
min-width: 0;
}
.case-media .plyr--video .plyr__controls .plyr__progress input[type="range"] {
width: 100%;
min-width: 0;
}
.case-media .case-video-shell {
border-radius: var(--radius-md);
overflow: hidden;
box-sizing: border-box;
border: 1px solid var(--line);
box-shadow: none;
transition:
border-color 0.2s ease,
box-shadow 0.2s ease;
}
.case-media .case-video-shell:hover,
.case-media .case-video-shell:focus-within {
border-color: var(--accent);
box-shadow: 0 8px 24px color-mix(in srgb, var(--accent) 18%, transparent);
}
.case-media .case-plyr video,
.case-media .plyr video {
width: 100% !important;
height: auto !important;
max-height: none;
object-fit: contain;
object-position: center;
border-radius: 0 !important;
}
/* Fullscreen (API и fallback Plyr): кадр целиком, без cover по ширине */
.plyr--fullscreen-active,
.plyr--fullscreen-fallback,
.plyr:fullscreen,
.plyr:-webkit-full-screen {
background: #000;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.plyr--fullscreen-active .plyr__video-wrapper,
.plyr--fullscreen-fallback .plyr__video-wrapper,
.plyr:fullscreen .plyr__video-wrapper,
.plyr:-webkit-full-screen .plyr__video-wrapper {
display: flex;
align-items: center;
justify-content: center;
flex: 1 1 auto;
width: 100%;
height: 100%;
max-height: none;
}
.case-plyr.case-plyr--fullscreen video,
.case-plyr--fullscreen-fallback video,
.case-plyr.plyr--fullscreen-fallback video,
.plyr--fullscreen-active video,
.plyr--fullscreen-active .plyr__video-wrapper video,
.plyr--fullscreen-fallback video,
.plyr--fullscreen-fallback .plyr__video-wrapper video,
.plyr:fullscreen video,
.plyr:-webkit-full-screen video,
video:fullscreen,
video:-webkit-full-screen {
width: auto !important;
height: auto !important;
max-width: 100% !important;
max-height: 100% !important;
object-fit: contain !important;
object-position: center;
margin: auto;
}
.case-media .plyr__video-wrapper,
.case-media .plyr__poster,
.case-media .plyr__video-embed {
border-radius: 0 !important;
border: 0 !important;
box-shadow: none !important;
}
.case-media .plyr__control {
color: var(--text-muted);
}
.case-media .plyr__control:hover,
.case-media .plyr__control:focus-visible {
color: var(--accent-text);
background: var(--bg-elevated);
border-color: color-mix(in hsl, var(--accent) 38%, var(--line));
}
.case-media .plyr__control--overlaid {
background: color-mix(in srgb, var(--surface) 88%, var(--bg) 12%);
border: 1px solid color-mix(in srgb, var(--line) 92%, transparent);
color: var(--text-muted);
}
.case-media .plyr__control--overlaid:hover {
background: var(--bg-elevated);
color: var(--accent-text);
border-color: color-mix(in hsl, var(--accent) 38%, var(--line));
}
.case-media figcaption {
margin-top: 0.3rem;
font-size: 0.86rem;
line-height: 1.35;
color: var(--text-muted);
}
.case-media:has(.case-video-shell) {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.35rem;
}
.case-media:has(.case-video-shell) > .case-video-shell {
width: 100%;
}
.case-media:has(.case-video-shell) > figcaption {
width: 100%;
margin-top: 0;
text-align: center;
}
.case-media--natural img {
width: auto;
max-width: 100%;
margin-inline: auto;
}
.case-media--natural {
display: flex;
flex-direction: column;
align-items: center;
}
.case-media--content img {
width: 100%;
max-width: 100%;
}
.case-media--wide {
width: min(calc(100vw - (max(var(--space), env(safe-area-inset-left)) + max(var(--space), env(safe-area-inset-right)))), calc(100% + 8rem));
margin-left: 50%;
transform: translateX(-50%);
}
.case-media--wide img {
width: 100%;
max-width: 100%;
margin-inline: auto;
}
/* Длинный скрин: ширина по колонке (content) или «широкая» (wide), см. data-case-tall-width */
.case-media[data-case-tall-media][data-case-tall-width="wide"]:not(.case-media--wide) {
width: min(calc(100vw - (max(var(--space), env(safe-area-inset-left)) + max(var(--space), env(safe-area-inset-right)))), calc(100% + 8rem));
margin-left: 50%;
transform: translateX(-50%);
}
.case-media[data-case-tall-media][data-case-tall-width="wide"] .case-media-tall__clip > img,
.case-media.case-media--wide[data-case-tall-media] .case-media-tall__clip > img {
width: 100%;
max-width: 100%;
margin-inline: auto;
}
.case-media[data-case-tall-media][data-case-tall-width="wide"] .case-media-tall,
.case-media.case-media--wide[data-case-tall-media] .case-media-tall {
width: 100%;
}
/* Длинный скрин: обрезка по высоте, туман и кнопка внутри рамки превью */
.case-media-tall {
position: relative;
box-sizing: border-box;
border: 0;
background: none;
}
.case-media-tall__clip {
position: relative;
max-height: var(--case-tall-max, min(70vh, 32rem));
overflow: hidden;
transition: max-height 0.38s ease;
}
.case-media-tall--expanded .case-media-tall__clip {
max-height: none;
overflow: visible;
}
.case-media-tall--reduced-motion .case-media-tall__clip {
transition: none;
}
.case-media-tall__clip > img {
width: 100%;
max-width: 100%;
height: auto;
display: block;
}
.case-media-tall__fog {
position: absolute;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
height: min(58%, 15rem);
min-height: 5.5rem;
pointer-events: none;
visibility: visible;
opacity: 1;
background: linear-gradient(
to top,
color-mix(in srgb, var(--bg) 99.5%, transparent) 0%,
color-mix(in srgb, var(--bg) 96%, transparent) 12%,
color-mix(in srgb, var(--bg) 78%, transparent) 38%,
color-mix(in srgb, var(--bg) 38%, transparent) 68%,
transparent 100%
);
transition: opacity 0.22s ease, visibility 0.22s ease;
}
.case-media-tall--expanded .case-media-tall__fog {
opacity: 0;
visibility: hidden;
}
.case-media-tall__actions {
position: absolute;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
padding: 0.65rem 0.5rem 0.75rem;
border: 0;
background: none;
pointer-events: none;
}
.case-media-tall__actions .case-media-tall__btn {
pointer-events: auto;
}
.case-media-tall__btn.btn.btn--ghost {
gap: 0.45rem;
min-width: unset;
padding: 0.45rem 0.65rem;
color: var(--accent-text);
border-color: transparent !important;
background: transparent !important;
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
box-shadow: none !important;
}
.case-media-tall__btn.btn.btn--ghost:hover,
.case-media-tall__btn.btn.btn--ghost:focus-visible {
color: var(--accent-hover);
border-color: transparent !important;
background: color-mix(in srgb, var(--accent) 10%, transparent) !important;
backdrop-filter: none !important;
-webkit-backdrop-filter: none !important;
}
.case-media-tall__btn-chev {
display: block;
width: 1rem;
height: 1rem;
flex-shrink: 0;
background: currentColor;
mask-image: url("../assets/shared/icons/shevron-down.svg");
-webkit-mask-image: url("../assets/shared/icons/shevron-down.svg");
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
}
.case-media-tall--expanded .case-media-tall__btn .case-media-tall__btn-chev {
mask-image: url("../assets/shared/icons/shevron-up.svg");
-webkit-mask-image: url("../assets/shared/icons/shevron-up.svg");
}
@media (prefers-reduced-motion: reduce) {
.case-media-tall__clip {
transition: none;
}
.case-media-tall__fog {
transition: none;
}
}
/* Галерея изображений сеткой: число колонок на широком экране — CSS-переменная --case-gallery-cols на figure */
.case-media-gallery {
--case-gallery-cols: 3;
}
/* Wide-галерея: 4 колонки и выход за колонку контента (как у .case-media--wide) */
.case-media-gallery--wide {
--case-gallery-cols: 4;
width: min(calc(100vw - (max(var(--space), env(safe-area-inset-left)) + max(var(--space), env(safe-area-inset-right)))), calc(100% + 8rem));
margin-left: 50%;
transform: translateX(-50%);
}
.case-media-gallery > figcaption {
width: 100%;
text-align: center;
}
.case-media-gallery__grid {
display: grid;
gap: 0.65rem;
grid-template-columns: repeat(var(--case-gallery-cols), minmax(0, 1fr));
}
@media (max-width: 48rem) {
.case-media-gallery__grid {
grid-template-columns: repeat(min(2, var(--case-gallery-cols)), minmax(0, 1fr));
}
}
@media (max-width: 28rem) {
.case-media-gallery__grid {
grid-template-columns: 1fr;
}
}
.case-media-gallery__item {
min-width: 0;
border-radius: var(--radius-md);
overflow: hidden;
border: 1px solid var(--line);
background: color-mix(in srgb, var(--surface) 60%, var(--bg) 40%);
transition:
border-color 0.2s ease,
box-shadow 0.2s ease;
}
.case-media-gallery__item:has(> img[data-image-viewer]:not([data-src])):not(.has-img-loading) {
padding: 0;
border: none;
background: none;
overflow: visible;
}
/* Заглушка: клип по тайлу (viewer снимает overflow только после load) */
.case-media-gallery__item.has-img-loading {
overflow: hidden;
border: 1px solid var(--line);
}
.case-media-gallery__item img {
width: 100%;
height: auto;
display: block;
}
.case-media-gallery--wide {
width: min(calc(100vw - (max(var(--space), env(safe-area-inset-left)) + max(var(--space), env(safe-area-inset-right)))), calc(100% + 8rem));
margin-left: 50%;
transform: translateX(-50%);
}
.case-callout {
width: min(calc(100vw - (max(var(--space), env(safe-area-inset-left)) + max(var(--space), env(safe-area-inset-right)))), calc(100% + 8rem));
margin: 1.8rem 0 2.4rem;
margin-left: 50%;
padding: 0.95rem 1.1rem;
display: grid;
grid-template-columns: auto 1fr;
align-items: start;
gap: 0.72rem;
border-radius: var(--radius-md);
transform: translateX(-50%);
background: color-mix(in srgb, var(--surface) 84%, var(--bg) 16%);
}
.case-callout__emoji {
display: inline-grid;
place-items: center;
min-width: 1.65rem;
min-height: 1.65rem;
font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", emoji, sans-serif;
font-size: clamp(1.05rem, 1.75vw, 1.3rem);
line-height: 1;
font-style: normal;
font-variant-emoji: emoji;
color: unset;
-webkit-text-fill-color: unset;
transform-origin: center;
}
.case-callout__emoji--pulse {
animation: case-callout-emoji-pulse 0.6s ease-in-out infinite;
}
.case-callout__content {
min-width: 0;
font-size: clamp(1.05rem, 1.45vw, 1.125rem);
line-height: 1.6;
color: var(--text);
}
.case-callout__content > :first-child {
margin-top: 0;
}
.case-callout__content > :last-child {
margin-bottom: 0;
}
.case-callout:has(.case-callout__content > p:only-child),
.case-callout:has(.case-callout__content > :only-child) {
align-items: center;
}
@keyframes case-callout-emoji-pulse {
0%,
100% {
transform: scale(1);
filter: saturate(1);
}
50% {
transform: scale(1.12);
filter: saturate(1.15);
}
}
/* Кликабельные кадры (viewer): рамка на кадре, figcaption снаружи и по центру под картинкой */
.case-media:has(> img[data-image-viewer]:not([data-src])),
.case-media:has(.case-media-tall__clip > img[data-image-viewer]:not([data-src])) {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.35rem;
}
/* Перебивает margin у `.case-article img` в локальных <style> страниц кейсов */
.case-article .case-media > img[data-image-viewer],
.case-article .case-media-gallery__item > img[data-image-viewer],
.case-article .case-media-tall__clip > img[data-image-viewer] {
margin: 0;
}
.case-media:has(> img[data-image-viewer]:not([data-src])) > figcaption,
.case-media:has(.case-media-tall__clip > img[data-image-viewer]:not([data-src])) > figcaption {
width: 100%;
margin-top: 0;
text-align: center;
}
.case-media:not(.case-media--natural) > img[data-image-viewer]:not([data-src]),
.case-media-gallery__item > img[data-image-viewer]:not([data-src]) {
box-sizing: border-box;
border-radius: var(--radius-md);
border: 1px solid var(--line);
box-shadow: none;
transition:
border-color 0.2s ease,
box-shadow 0.2s ease;
}
.case-media-tall:has(.case-media-tall__clip > img[data-image-viewer]:not([data-src])) {
border-radius: var(--radius-md);
overflow: hidden;
border: 1px solid var(--line);
box-shadow: none;
transition:
border-color 0.2s ease,
box-shadow 0.2s ease;
}
.case-media-tall:has(.case-media-tall__clip > img[data-image-viewer]:not([data-src])) .case-media-tall__clip {
border: none;
box-shadow: none;
}
.case-media:not(.case-media--natural):has(> img[data-image-viewer]:not([data-src]):hover) > img[data-image-viewer]:not([data-src]),
.case-media:not(.case-media--natural):has(> img[data-image-viewer]:not([data-src]):focus-visible) > img[data-image-viewer]:not([data-src]),
.case-media-gallery__item:has(> img[data-image-viewer]:not([data-src]):hover) > img[data-image-viewer]:not([data-src]),
.case-media-gallery__item:has(> img[data-image-viewer]:not([data-src]):focus-within) > img[data-image-viewer]:not([data-src]),
.case-media:has(.case-media-tall__clip > img[data-image-viewer]:not([data-src]):hover) .case-media-tall,
.case-media:has(.case-media-tall__clip > img[data-image-viewer]:not([data-src]):focus-visible) .case-media-tall {
border-color: var(--accent);
box-shadow: 0 8px 24px color-mix(in srgb, var(--accent) 18%, transparent);
}
img[data-image-viewer]:not([data-src]) {
cursor: zoom-in;
}
img[data-image-viewer]:not([data-src]):focus-visible {
outline: none;
}
.case-media--natural img[data-image-viewer] {
cursor: default;
}
.case-image-viewer {
position: fixed;
inset: 0;
z-index: 1400;
background: color-mix(in srgb, var(--bg) 72%, transparent);
backdrop-filter: blur(22px) saturate(130%);
-webkit-backdrop-filter: blur(22px) saturate(130%);
opacity: 0;
transition: opacity 0.18s ease;
}
.case-image-viewer.is-open {
opacity: 1;
}
.case-image-viewer[hidden] {
display: none;
}
html.imgv-lock,
html.imgv-lock body {
overflow: hidden;
}
html[data-theme="light"] {
--imgv-slider-thumb-bg: color-mix(in srgb, white 92%, var(--surface));
--imgv-slider-thumb-border: color-mix(in srgb, var(--line) 85%, white);
}
html[data-theme="dark"] {
--imgv-slider-thumb-bg: color-mix(in srgb, var(--surface) 92%, black 8%);
--imgv-slider-thumb-border: color-mix(in srgb, var(--line) 82%, black 18%);
}
.case-image-viewer__toolbar {
position: absolute;
left: 50%;
bottom: max(0.85rem, env(safe-area-inset-bottom));
transform: translateX(-50%);
z-index: 3;
display: flex;
align-items: center;
gap: 0.55rem;
padding: 0.6rem;
border-radius: 999px;
width: max-content;
max-width: calc(100vw - max(1rem, env(safe-area-inset-left)) - max(1rem, env(safe-area-inset-right)));
opacity: 0;
transform: translate(-50%, 18px);
transition:
transform 0.2s ease,
opacity 0.16s ease;
}
.case-image-viewer.is-open .case-image-viewer__toolbar {
opacity: 1;
transform: translate(-50%, 0);
}
.case-image-viewer__zoom {
min-width: 2.5rem;
text-align: center;
font-size: 0.82rem;
color: var(--text-muted);
font-weight: 400;
}
/* Группа слайдер + текст масштаба с уменьшенным внутренним зазором */
.case-image-viewer__scale-group {
display: inline-flex;
align-items: center;
gap: 0.25rem;
}
.case-image-viewer__slider {
flex: 0 0 5.2rem;
width: 5.2rem;
min-width: 5.2rem;
accent-color: var(--accent);
appearance: none;
-webkit-appearance: none;
background: transparent;
height: 1rem;
padding: 0;
}
.case-image-viewer__slider::-webkit-slider-runnable-track {
height: 0.86rem;
border-radius: 999px;
background: color-mix(in srgb, var(--text-muted) 36%, var(--surface));
border: 1px solid color-mix(in srgb, var(--line) 92%, transparent);
}
.case-image-viewer__slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 0.62rem;
height: 0.62rem;
margin-top: calc((0.86rem - 0.62rem) / 2 - 1px);
border-radius: 999px;
border: 1px solid var(--imgv-slider-thumb-border, color-mix(in srgb, var(--line) 85%, white));
background: var(--imgv-slider-thumb-bg, color-mix(in srgb, white 92%, var(--surface)));
}
.case-image-viewer__slider::-moz-range-track {
height: 0.86rem;
border-radius: 999px;
background: color-mix(in srgb, var(--text-muted) 36%, var(--surface));
border: 1px solid color-mix(in srgb, var(--line) 92%, transparent);
}
.case-image-viewer__slider::-moz-range-progress {
height: 0.86rem;
border-radius: 999px;
background: color-mix(in srgb, var(--text-muted) 36%, var(--surface));
border: 1px solid color-mix(in srgb, var(--line) 92%, transparent);
}
.case-image-viewer__slider::-moz-range-thumb {
width: 0.62rem;
height: 0.62rem;
border-radius: 999px;
transform: translateY(-2px);
border: 1px solid var(--imgv-slider-thumb-border, color-mix(in srgb, var(--line) 85%, white));
background: var(--imgv-slider-thumb-bg, color-mix(in srgb, white 92%, var(--surface)));
}
.case-image-viewer__slider:focus-visible {
outline: 2px solid color-mix(in srgb, var(--accent) 54%, var(--line));
outline-offset: 3px;
}
.case-image-viewer__btn.btn {
min-width: 2.2rem;
min-height: 2.2rem;
padding: 0.42rem;
border-radius: 999px;
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--text-muted);
}
.case-image-viewer__btn.btn:hover,
.case-image-viewer__btn.btn:focus-visible {
color: var(--accent-text);
background: var(--bg-elevated);
border-color: color-mix(in hsl, var(--accent) 38%, var(--line));
}
.case-image-viewer__btn-icon {
width: 1rem;
height: 1rem;
display: block;
background: currentColor;
-webkit-mask-image: var(--imgv-icon);
mask-image: var(--imgv-icon);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-position: center;
mask-position: center;
-webkit-mask-size: contain;
mask-size: contain;
}
.case-image-viewer__stage {
position: relative;
z-index: 1;
width: 100%;
height: 100%;
overflow: auto;
padding: max(1rem, env(safe-area-inset-top)) max(1rem, env(safe-area-inset-right)) calc(max(1rem, env(safe-area-inset-bottom)) + var(--imgv-toolbar-space, 0px)) max(1rem, env(safe-area-inset-left));
cursor: grab;
-ms-overflow-style: none;
scrollbar-width: none;
}
.case-image-viewer__stage:focus,
.case-image-viewer__stage:focus-visible {
outline: none;
}
.case-image-viewer__stage::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
}
.case-image-viewer__stage.is-centered {
display: flex;
align-items: center;
justify-content: center;
}
.case-image-viewer__stage.is-center-y {
display: flex;
align-items: center;
}
.case-image-viewer__img {
display: block;
width: auto;
max-width: none;
height: auto;
margin: 0 auto;
cursor: grab;
user-select: none;
-webkit-user-drag: none;
opacity: 0;
transition: opacity 0.16s ease;
}
/* TUI braille-спиннер (переиспользуемый, чистый CSS) */
.tui-spinner {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.1em;
height: 1.1em;
font-family: ui-monospace, "Cascadia Code", "Consolas", "Courier New", monospace;
font-size: 1.5rem;
line-height: 1;
letter-spacing: 0.1em;
color: var(--accent);
}
.tui-spinner > span {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
animation: tui-spinner-step 0.9s steps(1, end) infinite;
}
.tui-spinner > span:nth-child(1) { animation-delay: 0s; }
.tui-spinner > span:nth-child(2) { animation-delay: 0.09s; }
.tui-spinner > span:nth-child(3) { animation-delay: 0.18s; }
.tui-spinner > span:nth-child(4) { animation-delay: 0.27s; }
.tui-spinner > span:nth-child(5) { animation-delay: 0.36s; }
.tui-spinner > span:nth-child(6) { animation-delay: 0.45s; }
.tui-spinner > span:nth-child(7) { animation-delay: 0.54s; }
.tui-spinner > span:nth-child(8) { animation-delay: 0.63s; }
.tui-spinner > span:nth-child(9) { animation-delay: 0.72s; }
.tui-spinner > span:nth-child(10) { animation-delay: 0.81s; }
@keyframes tui-spinner-step {
0%, 9.999% { opacity: 1; }
10%, 100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
.tui-spinner > span { animation: none; opacity: 0; }
.tui-spinner > span:nth-child(1) { opacity: 1; }
}
/* Универсальный эффект «продавливания» иконки при нажатии кнопки */
.icon-press {
transition: transform 0.12s ease;
}
[class*="btn"]:active:not(:disabled) .icon-press,
.btn:active:not(:disabled) .icon-press,
.case-image-viewer__btn--nav:active:not(:disabled) .icon-press,
.case-media-slider__nav.is-pressed:not(:disabled) .icon-press {
transform: scale(0.82);
}
.case-image-viewer__loader {
position: absolute;
left: 50%;
top: 50%;
z-index: 2;
transform: translate(-50%, -50%);
display: inline-flex;
align-items: center;
text-shadow: 0 1px 6px hsla(0, 0%, 0%, 0.35);
pointer-events: none;
opacity: 0;
transition: opacity 0.14s ease;
}
.case-image-viewer.is-loading .case-image-viewer__loader {
opacity: 1;
}
.case-image-viewer__loader.is-error .tui-spinner {
display: none;
}
.case-image-viewer__loader-msg {
font-family: var(--font, inherit);
font-size: 0.82rem;
color: var(--text-muted);
margin-left: 0.5rem;
}
.case-image-viewer.is-loading .case-image-viewer__img {
opacity: 0;
}
.case-image-viewer.is-open .case-image-viewer__img {
opacity: 1;
}
.case-image-viewer__stage.is-panning,
.case-image-viewer__stage.is-panning .case-image-viewer__img {
cursor: grabbing;
}
/* Кнопки пред/след в тулбаре: группа с отрицательным зазором и скруглением только снаружи */
.case-image-viewer__nav-group {
display: inline-flex;
border-radius: 999px;
overflow: hidden;
}
.case-image-viewer__btn--nav {
--imgv-nav-size: 2rem;
width: var(--imgv-nav-size);
height: var(--imgv-nav-size);
padding: 0;
border-radius: 0;
display: inline-flex;
align-items: center;
justify-content: center;
/* Позиционируем, чтобы z-index работал: наведённая кнопка должна
рисоваться поверх соседа и показывать свой бордер целиком (включая шов). */
position: relative;
}
/* Соседняя кнопка сдвигается на 1px, перекрывая разделительный бордер */
.case-image-viewer__btn--nav + .case-image-viewer__btn--nav {
margin-left: -1px;
}
.case-image-viewer__btn--nav[hidden] {
display: none;
}
/* Скругления только на крайних кнопках группы (все 4 угла заданы явно) */
.case-image-viewer__btn--nav:first-child {
border-radius: 999px 0 0 999px;
}
.case-image-viewer__btn--nav:last-child {
border-radius: 0 999px 999px 0;
}
/* У одиночной кнопки в группе — скругление со всех сторон */
.case-image-viewer__btn--nav:only-child {
border-radius: 999px;
}
/* Наведённая/в фокусе кнопка поднимается над соседом: её бордер (включая
шовный 1px, перекрытый соседом из-за margin-left:-1px) рисуется целиком. */
.case-image-viewer__btn--nav:hover,
.case-image-viewer__btn--nav:focus-visible {
z-index: 1;
}
/* Точки-пагинация в тулбаре просмотрщика */
.case-image-viewer__dots {
display: flex;
align-items: center;
gap: 0.4rem;
padding: 0 0.15rem;
}
.case-image-viewer__dots[hidden] {
display: none;
}
.case-image-viewer__dot {
width: 0.375rem;
height: 0.375rem;
padding: 0;
border: none;
border-radius: 50%;
background: color-mix(in srgb, var(--text-muted) 40%, transparent);
cursor: pointer;
transition: background 0.22s ease, width 0.28s cubic-bezier(0.22, 0.61, 0.36, 1), border-radius 0.28s ease;
}
.case-image-viewer__dot:hover,
.case-image-viewer__dot:focus-visible {
background: color-mix(in srgb, var(--text-muted) 65%, transparent);
}
.case-image-viewer__dot.is-active {
background: var(--accent);
width: calc(0.375rem * 2.6);
border-radius: 999px;
}
@media (max-width: 640px) {
.case-link-card {
grid-template-columns: 1fr;
}
.case-link-card__media {
width: 100%;
max-width: 160px;
}
.case-link-card--favicon {
grid-template-columns: 1fr;
}
.case-link-card--favicon .case-link-card__media {
width: 24px;
max-width: none;
margin-inline: auto;
}
.case-media--wide {
width: 100%;
}
.case-media-gallery--wide {
width: 100%;
margin-left: 0;
transform: none;
}
.case-callout {
width: 100%;
margin-left: 0;
transform: none;
}
}
.hero__tags {
margin: 0 0 1.5rem;
padding: 0;
list-style: none;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
max-width: 42rem;
}
.hero__tag {
display: inline-flex;
align-items: center;
min-height: 2rem;
padding: 0.35rem 0.7rem;
border-radius: 999px;
border: 1px solid var(--line);
background: color-mix(in srgb, var(--surface) 78%, transparent);
color: var(--text-muted);
font-size: 0.88rem;
font-weight: 600;
line-height: 1.2;
white-space: normal;
}
.hero__actions {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
margin-top: 2rem;
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.65rem 1.25rem;
border-radius: var(--radius-btn);
font-weight: 600;
font-size: 0.95rem;
text-decoration: none;
border: 1px solid transparent;
cursor: pointer;
font-family: inherit;
transition:
background 0.2s ease,
color 0.15s ease,
border-color 0.15s ease,
box-shadow 0.2s ease,
backdrop-filter 0.2s ease;
}
.btn:has(.btn__icon) {
gap: 0.5rem;
}
.btn__icon {
display: block;
width: 1.125rem;
height: 1.125rem;
flex-shrink: 0;
background: currentColor;
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
}
.btn--primary .btn__icon {
mask-image: url("../assets/shared/icons/write_me.svg");
-webkit-mask-image: url("../assets/shared/icons/write_me.svg");
}
.btn--secondary .btn__icon {
mask-image: url("../assets/shared/icons/portfolio.svg");
-webkit-mask-image: url("../assets/shared/icons/portfolio.svg");
}
.btn--resume .btn__icon {
mask-image: url("../assets/shared/icons/cv.svg");
-webkit-mask-image: url("../assets/shared/icons/cv.svg");
}
/* Primary: радиальный акцент (--accent-btn-radial-*) + стекло; по умолчанию «приподнята» */
.btn--primary {
position: relative;
isolation: isolate;
overflow: hidden;
border: 1px solid var(--btn-primary-border);
background: var(--btn-primary-bg);
backdrop-filter: var(--btn-primary-backdrop);
-webkit-backdrop-filter: var(--btn-primary-backdrop);
box-shadow: var(--btn-primary-shadow-raised);
color: var(--on-accent);
}
.btn--primary.btn--flat {
box-shadow: var(--btn-primary-shadow-flat);
backdrop-filter: blur(14px) saturate(128%);
-webkit-backdrop-filter: blur(14px) saturate(128%);
}
.btn--primary::after {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
z-index: 0;
background: var(--btn-primary-sheen);
}
html[data-theme="light"] .btn--primary::after {
opacity: 0.42;
}
/* flat: слабее диагональный блик, меньше «объёма» от глянца */
.btn--primary.btn--flat::after {
opacity: 0.22;
}
html[data-theme="light"] .btn--primary.btn--flat::after {
opacity: 0.28;
}
.btn--primary::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
background: radial-gradient(
circle 3rem at var(--btn-shine-x, 50%) var(--btn-shine-y, 50%),
color-mix(in hsl, hsl(var(--theme-h) calc(var(--theme-s) * 1%) calc(var(--theme-l) * 1%)), white 52%) 0%,
transparent 55%
);
opacity: 0;
transition: opacity 0.2s ease;
pointer-events: none;
z-index: 2;
mix-blend-mode: soft-light;
}
.btn--primary:hover::before {
opacity: 0.58;
}
.btn--primary > * {
position: relative;
z-index: 3;
}
.btn--primary:hover {
background: var(--btn-primary-hover-bg);
backdrop-filter: var(--btn-primary-backdrop-hover);
-webkit-backdrop-filter: var(--btn-primary-backdrop-hover);
box-shadow: var(--btn-primary-shadow-hover);
color: var(--on-accent);
}
.btn--primary.btn--flat:hover,
.btn--primary.btn--flat:focus-visible {
box-shadow: var(--btn-primary-shadow-flat);
backdrop-filter: blur(15px) saturate(132%);
-webkit-backdrop-filter: blur(15px) saturate(132%);
}
a.btn--primary:visited {
color: var(--on-accent);
background: var(--btn-primary-bg);
}
.btn--primary:focus-visible {
background: var(--btn-primary-hover-bg);
backdrop-filter: var(--btn-primary-backdrop-hover);
-webkit-backdrop-filter: var(--btn-primary-backdrop-hover);
box-shadow: var(--btn-primary-shadow-hover);
color: var(--on-accent);
outline: 2px solid color-mix(in hsl, var(--accent) 65%, var(--text));
outline-offset: 2px;
}
.btn--primary.btn--flat:focus-visible {
box-shadow: var(--btn-primary-shadow-flat);
}
@media (prefers-reduced-motion: reduce) {
.btn--primary::before,
.fab--primary::before {
display: none;
}
.case-callout__emoji--pulse {
animation: none;
}
}
/* Secondary: нейтральное стекло (--v12-glass-neutral-*); по умолчанию плоская */
.btn--secondary,
.btn--ghost {
border: 1px solid var(--v12-glass-neutral-border);
color: var(--text);
background: var(--v12-glass-neutral-bg);
backdrop-filter: var(--v12-glass-neutral-filter);
-webkit-backdrop-filter: var(--v12-glass-neutral-filter);
box-shadow: none;
}
.btn--secondary.btn--raised,
.btn--ghost.btn--raised {
box-shadow: var(--v12-glass-neutral-shadow);
}
.btn--secondary:hover,
.btn--secondary:focus-visible,
.btn--ghost:hover,
.btn--ghost:focus-visible {
border-color: color-mix(in srgb, var(--accent) 45%, var(--v12-glass-neutral-border));
color: var(--text);
backdrop-filter: var(--v12-glass-neutral-filter-elevated);
-webkit-backdrop-filter: var(--v12-glass-neutral-filter-elevated);
}
a.btn--secondary:visited,
a.btn--ghost:visited {
color: var(--text);
}
.hero__visual {
display: flex;
justify-content: center;
perspective: 1300px;
perspective-origin: 50% 50%;
}
@media (min-width: 860px) {
.hero__visual {
justify-content: flex-end;
}
}
/*
* Оболочка: overflow + скругление — без preserve-3d на том же узле.
* Иначе браузер «сплющивает» 3D и параллакс между слоями почти не виден.
*/
.hero__portrait-shell {
--portrait-bg-pos: 50% 36%;
--portrait-cutout-pos: 50% 36%;
width: min(100%, 380px, 38vw);
aspect-ratio: 1;
position: relative;
border-radius: var(--radius-card);
overflow: hidden;
border: 1px solid var(--line);
background: var(--surface);
box-shadow: var(--shadow-strong);
}
@media (max-width: 859.98px) {
.hero__portrait-shell {
width: min(100%, 380px, 88vw);
}
}
.hero__portrait {
width: 100%;
height: 100%;
}
.hero__portrait-inner {
position: relative;
width: 100%;
height: 100%;
}
.hero__portrait-layers {
position: relative;
width: 100%;
height: 100%;
}
.hero__portrait-layer {
position: absolute;
inset: 0;
}
.hero__photo-bg {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: var(--portrait-bg-pos);
}
.hero__photo-cutout {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: var(--portrait-cutout-pos);
}
.hero__photo-motion {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: var(--portrait-cutout-pos);
opacity: 0;
transition: opacity 0.2s ease;
pointer-events: none;
}
.hero__portrait-shell.hero__portrait-shell--motion-visible .hero__photo-motion {
opacity: 1;
}
.hero__portrait-shell::after {
content: "";
position: absolute;
left: 8%;
right: 8%;
bottom: -1.05rem;
height: 1.15rem;
border-radius: 999px;
pointer-events: none;
background: hsla(0, 0%, 0%, 0.24);
filter: blur(9px);
z-index: -1;
}
html[data-theme="light"] .hero__portrait-shell::after {
background: hsla(var(--theme-h), 25%, 24%, 0.28);
filter: blur(12px);
}
html[data-theme="light"] .hero__portrait-shell {
box-shadow:
0 16px 26px -10px hsla(var(--theme-h), 26%, 22%, 0.24),
0 7px 12px -9px hsla(var(--theme-h), 22%, 24%, 0.16);
}
.section {
padding: calc(2 * clamp(2.5rem, 5vw, 4rem)) calc(2 * max(var(--space), env(safe-area-inset-right, 0px))) calc(2 * clamp(2.5rem, 5vw, 4rem)) calc(2 * max(var(--space), env(safe-area-inset-left, 0px)));
}
.section--tight {
padding-top: calc(2 * clamp(1.75rem, 3vw, 2.5rem));
padding-bottom: calc(2 * clamp(1.75rem, 3vw, 2.5rem));
}
.section--surface {
background: transparent;
}
.section__inner {
max-width: var(--max);
margin: 0 auto;
}
.section__title {
margin: 0 0 1.25rem;
font-family: var(--font);
font-size: clamp(0.95rem, 1.35vw, 1.1rem);
font-weight: 600;
letter-spacing: 0;
text-transform: none;
color: var(--text-muted);
}
/* Главная: заголовки секций в стиле hero__eyebrow */
body.home .section__title {
margin: 0 0 0.5rem;
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.14em;
text-transform: uppercase;
}
.section__prose {
margin: 0;
max-width: 42rem;
color: var(--text-muted);
}
/* Scroll-reveal: плавное появление секций при скролле */
[data-reveal] {
opacity: 0;
transform: translateY(80px);
transition: opacity 0.4s ease-out, transform 0.6s ease-out;
}
[data-reveal].is-visible {
opacity: 1;
transform: translateY(0);
}
/* Stagger: заголовок появляется первым, контент — через 100ms */
[data-reveal].is-visible .section__title {
transition-delay: 0.1s;
}
[data-reveal].is-visible .section__inner > *:not(.section__title) {
transition-delay: 0.25s;
}
/* Исключаем skills и mini-projects — у них своя stagger-анимация */
#skills[data-reveal].is-visible .section__title,
#activity[data-reveal].is-visible .section__title {
transition-delay: 0s;
}
#skills[data-reveal].is-visible .section__inner > *:not(.section__title),
#activity[data-reveal].is-visible .section__inner > *:not(.section__title) {
transition-delay: 0s;
}
@media (prefers-reduced-motion: reduce) {
[data-reveal] {
opacity: 1;
transform: none;
transition: none;
}
[data-reveal].is-visible .section__title,
[data-reveal].is-visible .section__inner > *:not(.section__title) {
transition-delay: 0s;
}
}
.experience-grid {
list-style: none;
margin: 0;
padding: 0;
position: relative;
min-height: 1px;
overflow: hidden;
transition: height 360ms cubic-bezier(0.2, 0.65, 0.25, 1);
}
.experience-grid__item {
margin: 0;
position: absolute;
left: 0;
top: 0;
transition: transform 320ms cubic-bezier(0.2, 0.65, 0.25, 1);
}
.experience-grid__item::before {
content: "";
position: absolute;
inset: 0;
border-radius: var(--radius-card);
padding: 1px;
background: radial-gradient(
380px circle at var(--mouse-x, 50%) var(--mouse-y, 50%),
color-mix(in srgb, var(--accent) 92%, transparent),
transparent 50%
);
-webkit-mask:
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
opacity: 0;
pointer-events: none;
z-index: 3;
transition: opacity 220ms ease;
}
.experience-grid:hover .experience-grid__item::before {
opacity: 0.38;
}
.experience-grid__item:hover::before,
.experience-grid__item:focus-within::before {
opacity: 1;
}
.experience__actions {
margin-top: 1.5rem;
display: flex;
justify-content: center;
}
.exp-card {
position: relative;
overflow: hidden;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius-card);
padding: 1.15rem 1.25rem;
display: flex;
flex-direction: column;
gap: 0.55rem;
align-items: flex-start;
}
.exp-card::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
opacity: 0;
pointer-events: none;
z-index: 0;
transition: opacity 220ms ease;
background: radial-gradient(
420px circle at var(--mouse-x, 50%) var(--mouse-y, 50%),
color-mix(in srgb, var(--accent) 22%, transparent),
transparent 42%
);
}
.exp-card::after {
transition: opacity 220ms ease;
}
.experience-grid:hover .exp-card::before {
opacity: 0.32;
}
.exp-card:hover::before,
.exp-card:focus-visible::before {
opacity: 1;
}
.exp-card--link {
text-decoration: none;
color: inherit;
transition: border-color 0.22s ease, box-shadow 0.22s ease;
}
.exp-card--link:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
}
.exp-card::after {
content: attr(data-exp-order);
position: absolute;
bottom: -0.78rem;
right: -0.58rem;
top: auto;
font-family: var(--font-accent);
font-size: clamp(5rem, 19vw, 7.8rem);
font-weight: 900;
line-height: 0.78;
letter-spacing: -0.055em;
color: color-mix(in srgb, var(--text) 4.5%, transparent);
pointer-events: none;
user-select: none;
z-index: 0;
}
.exp-card > * {
position: relative;
z-index: 1;
}
.exp-card__time-row {
display: flex;
flex-wrap: wrap;
gap: 0.1rem 0.35rem;
align-items: baseline;
font-size: 0.82rem;
color: var(--text-muted);
width: 100%;
}
.exp-card__period {
font-weight: 600;
color: var(--text);
}
.exp-card__sep {
font-weight: 400;
opacity: 0.55;
user-select: none;
}
.exp-card__duration {
font-weight: 500;
}
.exp-card__company {
margin: 0;
font-family: var(--font-accent);
font-size: clamp(1.14rem, 2.6vw, 1.38rem);
font-weight: 700;
line-height: 1.2;
letter-spacing: -0.02em;
color: var(--accent-text);
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 0.35rem 0.45rem;
}
.exp-card__ext,
.mp-card__ext {
display: inline-flex;
width: 1.05em;
height: 1.05em;
flex-shrink: 0;
align-self: center;
background-color: currentColor;
opacity: 0;
transform: translateY(5px);
transition: opacity 0.22s ease, transform 0.22s ease;
-webkit-mask-image: url("../assets/shared/icons/link_url.svg");
mask-image: url("../assets/shared/icons/link_url.svg");
-webkit-mask-size: contain;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-position: center;
mask-position: center;
}
@media (prefers-reduced-motion: reduce) {
.exp-card__ext,
.mp-card__ext {
transition: none;
}
}
.exp-card--link:hover .exp-card__ext,
.exp-card--link:focus-visible .exp-card__ext,
.mp-card--link:hover .mp-card__ext,
.mp-card--link:focus-visible .mp-card__ext {
opacity: 1;
transform: translateY(0);
}
.exp-card__desc {
margin: 0;
font-size: 0.92rem;
line-height: 1.45;
color: var(--text-muted);
}
.mini-projects-grid {
list-style: none;
margin: 0;
padding: 0;
position: relative;
min-height: 1px;
overflow: clip;
overflow-clip-margin: 44px;
transition: height 360ms cubic-bezier(0.2, 0.65, 0.25, 1);
}
.mini-projects-grid__item {
margin: 0;
position: absolute;
left: 0;
top: 0;
transition: transform 320ms cubic-bezier(0.2, 0.65, 0.25, 1);
}
.mini-projects__actions {
margin-top: 1.5rem;
display: flex;
justify-content: center;
}
.mp-card {
box-sizing: border-box;
position: relative;
display: flex;
isolation: isolate;
overflow: hidden;
width: 100%;
min-height: 100%;
height: 100%;
border: 1px solid var(--line);
border-radius: var(--radius-card);
background: var(--surface);
color: inherit;
text-decoration: none;
transition: border-color 0.22s ease, transform 0.28s ease, box-shadow 0.28s ease;
}
.mp-card:hover,
.mp-card:focus-visible {
border-color: color-mix(in srgb, var(--accent) 58%, var(--line));
}
.mp-card--link {
cursor: pointer;
}
.mp-card--link:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
}
.mp-card--link:hover,
.mp-card--link:focus-visible {
transform: translateY(-5px);
z-index: 2;
box-shadow: 0 8px 18px -10px color-mix(in srgb, var(--accent) 28%, transparent),
0 2px 6px -3px color-mix(in srgb, var(--accent) 14%, transparent);
}
.mp-card__body {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
gap: 0.5rem;
min-width: 0;
overflow: hidden;
}
.mp-card__title {
margin: 0;
font-family: var(--font-accent);
font-size: clamp(1.02rem, 2.2vw, 1.22rem);
font-weight: 700;
line-height: 1.2;
letter-spacing: -0.02em;
color: var(--accent-text);
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 0.35rem 0.45rem;
min-width: 0;
}
.mp-card__desc {
margin: 0;
font-size: 0.88rem;
line-height: 1.45;
color: var(--text-muted);
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.mp-card__tags {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 0.35rem 0.45rem;
}
.mp-card__tag {
display: inline-flex;
align-items: center;
padding: 0.35rem 0.7rem;
border: 0;
border-radius: var(--radius-btn);
background: color-mix(in srgb, var(--surface) 62%, var(--bg-elevated) 38%);
color: var(--text-muted);
font-size: 0.78rem;
font-weight: 500;
letter-spacing: 0.01em;
text-transform: none;
white-space: nowrap;
}
.mp-card__media {
position: relative;
z-index: 1;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
background: transparent;
box-sizing: border-box;
}
.mp-card__image {
display: block;
width: 100%;
max-width: 100%;
height: auto;
object-fit: cover;
object-position: center;
border: 1px solid var(--line);
border-radius: calc(var(--radius-card) - 4px);
box-sizing: border-box;
}
.mp-card--stack {
flex-direction: column;
align-items: stretch;
gap: 0;
padding: 0;
}
.mp-card--stack .mp-card__body {
padding: 1.2rem 1.35rem 1.45rem;
}
.mp-card--stack .mp-card__media {
width: 100%;
flex-shrink: 0;
padding: 1.2rem 1.35rem 0;
}
.mp-card--stack .mp-card__image {
aspect-ratio: 16 / 9;
}
.mp-card--stack-bottom {
flex-direction: column-reverse;
align-items: stretch;
gap: 0;
padding: 0;
}
.mp-card--stack-bottom .mp-card__body {
padding: 1.2rem 1.35rem 1.45rem;
}
.mp-card--stack-bottom .mp-card__media {
width: 100%;
flex-shrink: 0;
padding: 0 1.35rem 1.2rem;
}
.mp-card--stack-bottom .mp-card__image {
aspect-ratio: 16 / 9;
}
.mp-card--stack-bottom.mp-card--hor-image .mp-card__image {
object-fit: contain;
aspect-ratio: 16 / 9;
background: color-mix(in srgb, var(--text-muted) 10%, var(--surface));
}
/* внутри варианта: Название → микротекст → тэг */
.mp-card--stack-bottom .mp-card__desc {
order: 1;
}
.mp-card--stack-bottom .mp-card__tags {
order: 2;
}
/* текст как в карточках опыта работы */
.mp-card--stack-bottom .mp-card__title {
font-size: clamp(1.14rem, 2.6vw, 1.38rem);
}
.mp-card--stack-bottom .mp-card__desc {
font-size: 0.92rem;
}
/* теги портфолио: пастельный цвет по hue тега (задаёт JS), темо-зависимый */
.mp-card--stack-bottom .mp-card__tag {
background: hsl(var(--tag-hue, 0) 58% 86%);
color: hsl(var(--tag-hue, 0) 42% 32%);
}
html[data-theme="dark"] .mp-card--stack-bottom .mp-card__tag {
background: hsl(var(--tag-hue, 0) 45% 30%);
color: hsl(var(--tag-hue, 0) 58% 84%);
}
.mp-card--horizontal {
flex-direction: row;
align-items: stretch;
gap: 0;
padding: 0;
}
.mp-card--horizontal .mp-card__body {
flex: 1 1 auto;
padding: 1.15rem 1.35rem 1.3rem 1.35rem;
justify-content: center;
}
.mp-card--horizontal .mp-card__media {
flex: 0 0 22%;
max-width: 6rem;
align-self: stretch;
min-height: 0;
padding: 1.15rem 0 1.15rem 1.15rem;
}
.mp-card--horizontal .mp-card__image {
max-height: 100%;
aspect-ratio: 16 / 9;
}
.mp-card--horizontal.mp-card--hor-image .mp-card__image {
object-fit: contain;
aspect-ratio: 1;
background: color-mix(in srgb, var(--text-muted) 10%, var(--surface));
}
.mp-card--compact {
flex-direction: column;
padding: 1.25rem 1.45rem 1.35rem;
gap: 0.55rem;
}
/* активность: теги внизу карточки */
.mp-card--compact .mp-card__desc {
order: 1;
}
.mp-card--compact .mp-card__tags {
order: 2;
}
.mp-card--decor {
min-height: 7.5rem;
padding: 0;
align-items: stretch;
justify-content: stretch;
pointer-events: none;
}
.mp-card__decor-pattern {
position: absolute;
inset: 0;
z-index: 0;
background: color-mix(in srgb, var(--surface) 94%, var(--accent));
opacity: 1;
}
@media (max-width: 519px) {
.mp-card--horizontal {
flex-direction: column;
}
.mp-card--horizontal .mp-card__media {
flex-basis: auto;
max-width: none;
width: 100%;
align-self: stretch;
padding: 1.15rem 1.25rem 0;
}
.mp-card--horizontal.mp-card--hor-image .mp-card__media {
width: auto;
max-width: 6rem;
align-self: center;
padding: 1.15rem 1.25rem 0;
}
.mp-card--horizontal .mp-card__body {
padding: 1.15rem 1.25rem 1.35rem 1.25rem;
}
}
@media (prefers-reduced-motion: reduce) {
.mini-projects-grid__item {
transition: none;
}
.mini-projects-grid {
transition: none;
}
}
.projects__heading {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
margin-bottom: 1rem;
}
.projects__title.section__title {
margin-bottom: 0;
}
.projects__controls {
display: flex;
align-items: center;
gap: 0.5rem;
}
.projects__nav-btn {
width: 2.25rem;
height: 2.25rem;
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid var(--line);
border-radius: var(--radius-sm);
background: color-mix(in srgb, var(--surface) 86%, transparent);
color: var(--text-muted);
cursor: pointer;
transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
}
.projects__nav-btn:hover:not(:disabled),
.projects__nav-btn:focus-visible:not(:disabled) {
color: var(--accent-text);
border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
background: var(--accent-soft);
}
.projects__nav-btn:disabled {
opacity: 0.45;
cursor: default;
}
.projects__nav-ico {
width: 1rem;
height: 1rem;
display: block;
background: currentColor;
mask-size: contain;
-webkit-mask-size: contain;
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-position: center;
}
.projects__nav-ico--left {
mask-image: url("../assets/shared/icons/shevron-left.svg");
-webkit-mask-image: url("../assets/shared/icons/shevron-left.svg");
}
.projects__nav-ico--right {
mask-image: url("../assets/shared/icons/shevron-right.svg");
-webkit-mask-image: url("../assets/shared/icons/shevron-right.svg");
}
.projects-carousel {
--projects-gap: 1rem;
--projects-visible: 1;
--projects-section-pad: calc(2 * max(var(--space), env(safe-area-inset-right, 0px), env(safe-area-inset-left, 0px)));
--projects-viewport-width: 100vw;
--projects-content-width: calc(var(--projects-viewport-width) - 2 * var(--projects-section-pad));
--projects-edge-space: max(calc(var(--projects-section-pad) - var(--projects-gap)), 0px);
--projects-card-width: calc(
(
var(--projects-content-width) - (var(--projects-visible) - 1) * var(--projects-gap)
) / var(--projects-visible)
);
--projects-edge-hit-zone: 64px;
position: relative;
width: var(--projects-viewport-width);
max-width: var(--projects-viewport-width);
margin-left: calc(50% - 0.5 * var(--projects-viewport-width));
}
@media (min-width: 760px) {
.projects-carousel {
--projects-visible: 2;
--projects-gap: 1.15rem;
}
}
@media (min-width: 1180px) {
.projects-carousel {
--projects-visible: 3;
--projects-gap: 1.25rem;
}
}
.projects-carousel__viewport {
overflow-x: auto;
overflow-y: visible;
scrollbar-width: none;
-ms-overflow-style: none;
cursor: grab;
touch-action: pan-y;
padding-bottom: 1rem;
padding-left: 0;
padding-right: 0;
}
.projects-carousel__viewport::-webkit-scrollbar {
display: none;
}
.projects-carousel__viewport.is-dragging {
cursor: grabbing;
user-select: none;
}
.projects-carousel__edge-hit {
position: absolute;
top: 0;
bottom: 0;
width: var(--projects-edge-hit-zone);
border: 0;
padding: 0;
margin: 0;
background: transparent;
z-index: 4;
cursor: pointer;
}
.projects-carousel__edge-hit--left {
left: 0;
}
.projects-carousel__edge-hit--right {
right: 0;
}
.projects-carousel__track {
display: flex;
gap: var(--projects-gap);
align-items: stretch;
padding: 0.15rem 0 2.35rem;
}
.projects-carousel__item {
flex: 0 0 var(--projects-card-width);
min-width: 0;
}
.projects-carousel__spacer {
flex: 0 0 var(--projects-edge-space);
pointer-events: none;
}
.portfolio-card {
display: flex;
flex-direction: column;
gap: 0;
align-items: stretch;
height: auto;
padding: 0;
border-radius: var(--radius-card);
border: 1px solid var(--line);
background: color-mix(in srgb, var(--surface) 94%, transparent);
color: inherit;
text-decoration: none;
overflow: hidden;
transition: border-color 0.2s ease;
}
.portfolio-card:hover,
.portfolio-card:focus-visible {
border-color: color-mix(in srgb, var(--accent) 55%, var(--line));
}
.portfolio-card:focus-visible {
outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
outline-offset: 3px;
}
.portfolio-card__body {
position: relative;
display: flex;
flex-direction: column;
gap: 0.85rem;
min-height: 0;
padding: 1.3rem;
background: color-mix(in srgb, var(--surface) 90%, transparent);
min-width: 0;
flex: none;
height: auto;
overflow: hidden;
}
.portfolio-card__body::after {
display: none;
content: none;
}
.portfolio-card__title {
margin: 0;
font-family: var(--font-accent);
font-size: clamp(1.22rem, 2.2vw, 1.55rem);
line-height: 1.2;
letter-spacing: -0.015em;
color: var(--text);
transition: color 0.2s ease;
}
html[data-font="geologica"] .portfolio-card__title {
font-weight: 700;
}
html[data-font="mono"] .portfolio-card__title {
font-weight: 700;
}
.portfolio-card__tags {
display: flex;
flex-wrap: wrap;
gap: 0.45rem;
margin: auto 0 0;
padding: 0;
list-style: none;
align-self: flex-start;
}
.portfolio-card__tag {
display: inline-flex;
align-items: center;
min-height: 1.95rem;
padding: 0.25rem 0.82rem;
border-radius: var(--radius-btn);
border: 0;
background: color-mix(in srgb, var(--surface) 62%, var(--bg-elevated) 38%);
color: var(--text-muted);
font-size: 0.78rem;
font-weight: 500;
letter-spacing: 0.01em;
text-transform: none;
white-space: nowrap;
}
.portfolio-card__summary {
margin: 0;
color: var(--text-muted);
font-size: 0.93rem;
line-height: 1.45;
display: -webkit-box;
-webkit-line-clamp: 6;
-webkit-box-orient: vertical;
overflow: hidden;
}
.portfolio-card__cover {
position: relative;
display: flex;
align-items: center;
justify-content: stretch;
aspect-ratio: 16 / 9;
height: auto;
min-height: 0;
min-width: 0;
width: 100%;
max-width: 100%;
flex: none;
border-left: 0;
padding: 1.3rem;
padding-top: 0;
background: transparent;
overflow: hidden;
border-radius: 0;
align-self: stretch;
}
.portfolio-card__image {
position: relative;
width: 100%;
height: 100%;
max-width: 100%;
display: block;
object-fit: cover;
object-position: center;
filter: none;
border: 1px solid color-mix(in srgb, var(--line) 84%, var(--text) 16%);
border-radius: calc(var(--radius-card) - 4px);
margin-left: 0;
}
.portfolio-card:hover .portfolio-card__title,
.portfolio-card:focus-visible .portfolio-card__title {
color: var(--accent-text);
}
@media (max-width: 639.98px) {
.projects__heading {
align-items: flex-start;
gap: 0.55rem;
}
.projects__controls {
margin-left: auto;
}
.portfolio-card {
height: auto;
}
.portfolio-card__body {
padding: 1.05rem 1.05rem 0.95rem;
background: transparent;
height: auto;
}
.portfolio-card__cover {
border-left: 0;
border-top: 0;
width: 100%;
min-height: 0;
padding: 1.05rem 1.05rem 0.95rem;
padding-top: 0;
border-radius: 0;
}
.portfolio-card__image {
width: 100%;
height: 100%;
object-position: center;
}
}
.skills-intro {
margin-bottom: clamp(1.5rem, 3vw, 2rem);
}
.skills-intro p:last-child {
margin-bottom: 0;
}
/* Вступление «Навыки»: сообщения-баблы */
.skills-intro--chat.section__prose {
max-width: min(52rem, 100%);
}
.skills-intro--chat {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.45rem;
}
.skills-intro--chat .skills-msg {
--skills-bubble-fill: color-mix(in srgb, var(--surface) 86%, var(--accent) 14%);
--skills-bubble-edge: color-mix(in srgb, var(--line), var(--text) 8%);
align-self: flex-start;
width: max-content;
max-width: min(52rem, 100%);
min-width: 0;
margin: 0;
padding: 0;
position: relative;
overflow: hidden;
box-sizing: border-box;
background: var(--skills-bubble-fill);
border: 1px solid var(--skills-bubble-edge);
border-radius: var(--radius-card) var(--radius-card) var(--radius-card) 0;
box-shadow: none;
}
.skills-intro--chat .skills-msg__body {
position: relative;
z-index: 1;
padding-top: max(0.52rem, calc(0.12rem + var(--radius-card) * 0.34));
padding-right: max(0.75rem, calc(0.18rem + var(--radius-card) * 0.46));
padding-bottom: max(0.42rem, calc(0.1rem + var(--radius-card) * 0.3));
padding-left: max(0.75rem, calc(0.18rem + var(--radius-card) * 0.46));
}
.skills-intro--chat .skills-msg__author {
margin: 0 0 0.38rem;
font-size: 0.75rem;
line-height: 1.25;
font-weight: 700;
letter-spacing: 0.01em;
color: var(--accent-text);
}
.skills-intro--chat .skills-msg__text {
margin: 0 0 0.38rem;
font-size: inherit;
line-height: 1.52;
font-style: italic;
color: color-mix(in srgb, var(--text) 88%, var(--text-muted));
overflow-wrap: break-word;
}
.skills-intro--chat .skills-msg__time {
display: block;
margin: 0;
padding: 0;
text-align: right;
font-size: 0.7rem;
font-variant-numeric: tabular-nums;
letter-spacing: 0.02em;
color: var(--text-muted);
opacity: 0.9;
}
.skills-intro--chat[data-skills-anim] .skills-msg:not(.is-visible) {
opacity: 0;
visibility: hidden;
pointer-events: none;
transform: translate3d(calc(-1 * min(1.75rem, 7vw)), 0, 0);
}
.skills-intro--chat[data-skills-anim] .skills-msg.is-visible {
opacity: 1;
transform: translate3d(0, 0, 0);
visibility: visible;
pointer-events: auto;
transition:
opacity 0.42s cubic-bezier(0.2, 0.65, 0.25, 1),
transform 0.52s cubic-bezier(0.18, 0.72, 0.24, 1),
visibility 0s linear 0s;
}
@media (prefers-reduced-motion: reduce) {
.skills-intro--chat[data-skills-anim] .skills-msg:not(.is-visible) {
opacity: 1;
transform: none;
visibility: visible;
pointer-events: auto;
transition: none;
}
.skills-intro--chat[data-skills-anim] .skills-msg.is-visible {
transition: none;
}
}
.skills-categories {
display: flex;
flex-direction: column;
gap: 0;
width: 100%;
max-width: 100%;
margin-left: 0;
box-sizing: border-box;
}
.skills-category {
position: relative;
border-radius: 0;
padding: clamp(0.75rem, 1.6vw, 1.18rem) 0;
}
.skills-category__title {
margin: 0;
font-family: var(--font-accent);
font-size: clamp(1rem, 1.55vw, 1.18rem);
font-weight: 700;
letter-spacing: 0.03em;
text-transform: uppercase;
color: color-mix(in srgb, var(--text) 82%, var(--text-muted));
}
.skills-category__toggle {
display: inline-flex;
position: relative;
align-items: center;
justify-content: space-between;
gap: 0.7rem;
width: 100%;
margin: 0;
padding: 0;
border: 0;
background: transparent;
color: inherit;
font: inherit;
letter-spacing: inherit;
text-transform: inherit;
text-align: left;
cursor: pointer;
transition: color 0.18s ease;
}
.skills-category__toggle::before {
content: "";
position: absolute;
inset: -0.45rem -0.1rem;
}
.skills-category__toggle:focus-visible {
outline: 2px solid color-mix(in srgb, var(--accent) 52%, transparent);
outline-offset: 4px;
border-radius: var(--radius-sm);
}
.skills-category__title-text {
min-width: 0;
}
.skills-category__chevron {
width: 1.05rem;
height: 1.05rem;
flex-shrink: 0;
background: currentColor;
mask-image: url("../assets/shared/icons/shevron-down.svg");
-webkit-mask-image: url("../assets/shared/icons/shevron-down.svg");
mask-size: contain;
-webkit-mask-size: contain;
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-position: center;
transition: transform 0.22s ease;
}
.skills-category__toggle:hover {
color: var(--accent-text);
}
.skills-category__toggle:hover .skills-category__chevron {
transform: scale(1.08);
}
.skills-category:hover .skills-category__toggle {
color: var(--accent-text);
}
.skills-category:hover .skills-category__chevron {
transform: scale(1.08);
}
.skills-category__toggle[aria-expanded="true"] .skills-category__chevron {
transform: rotate(180deg);
}
.skills-category:hover .skills-category__toggle[aria-expanded="true"] .skills-category__chevron,
.skills-category__toggle:hover[aria-expanded="true"] .skills-category__chevron {
transform: rotate(180deg) scale(1.08);
}
.skills-category__panel[hidden] {
display: none !important;
}
html[data-font="geologica"] .skills-category__title {
font-weight: 800;
}
.skills-category__grid {
display: grid;
gap: 1.5rem;
grid-template-columns: 1fr;
padding-top: 0.45rem;
padding-bottom: 0.55rem;
}
@media (min-width: 720px) {
.skills-category__grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
/*
Мозаика на 6 дорожках (визуально до трёх «столбиков» ширины: ½ / ⅓ / ⅔):
каждые 6 карточек — цикл: ряд 4+2, ряд 2+4, ряд 3+3.
Ровно 3 карточки: две первые как в цикле, третья — на всю ширину.
*/
@media (min-width: 1024px) {
.skills-category__grid {
grid-template-columns: repeat(6, minmax(0, 1fr));
grid-auto-flow: dense;
gap: 1.5rem;
}
.skills-category__grid .skill-task-card:nth-child(6n + 1) {
grid-column: span 4;
}
.skills-category__grid .skill-task-card:nth-child(6n + 2) {
grid-column: span 2;
}
.skills-category__grid .skill-task-card:nth-child(6n + 3) {
grid-column: span 2;
}
.skills-category__grid .skill-task-card:nth-child(6n + 4) {
grid-column: span 4;
}
.skills-category__grid .skill-task-card:nth-child(6n + 5) {
grid-column: span 3;
}
.skills-category__grid .skill-task-card:nth-child(6n + 6) {
grid-column: span 3;
}
.skills-category__grid .skill-task-card:nth-child(3):last-child {
grid-column: 1 / -1;
}
}
@media (min-width: 1100px) {
.skills-category__layout {
display: block;
}
.skills-category__title {
position: static;
margin-bottom: 1rem;
z-index: auto;
line-height: 1.22;
max-width: none;
font-size: clamp(1.08rem, 1.85vw, 1.48rem);
letter-spacing: 0.025em;
}
}
html[data-skill-connectors-js] .skill-task-card__task::after,
html[data-skill-connectors-js] .skill-task-card__solution::before,
html[data-skill-connectors-js] .skill-task-card__solution::after {
display: none !important;
}
html[data-skill-connectors-js] .skill-task-card__task,
html[data-skill-connectors-js] .skill-task-card__solutions,
html[data-skill-connectors-js] .skill-task-card__solution {
position: relative;
z-index: 1;
}
.skill-task-card__connector-svg {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: -1;
shape-rendering: geometricPrecision;
}
.skill-task-card {
isolation: isolate;
/* Коннекторы: идея examples_ideas/css-tree-menu — вертикаль (::before) и уголок (::after) раздельно, кастом через переменные */
--skill-solutions-margin-left: 0.5rem;
--skill-solutions-padding-left: 2.45rem;
--skill-solutions-stack-gap: 0.42rem;
--skill-connector-arm: calc(var(--skill-solutions-margin-left) + var(--skill-solutions-padding-left));
--skill-connector-stitch: 0rem;
--skill-connector-first-pull: 0.4rem;
--skill-connector-task-to-solutions-gap: 0.38rem;
--skill-connector-shift-right: 0.95rem;
/* Сегменты коннектора: как обводка карточек — нейтрально, без акцента */
--skill-connector-color-bridge: color-mix(in srgb, var(--line), var(--text) 6%);
--skill-connector-color-spine: color-mix(in srgb, var(--line), var(--text) 6%);
--skill-connector-color-elbow-h: color-mix(in srgb, var(--line), var(--text) 6%);
--skill-connector-color-elbow-v: color-mix(in srgb, var(--line), var(--text) 6%);
position: relative;
display: flex;
flex-direction: column;
min-height: 100%;
padding: 0;
background: transparent;
border: 0;
border-radius: var(--radius-md);
overflow: visible;
}
.skill-task-card__task {
position: relative;
margin: 0;
padding: 0.82rem;
font-size: clamp(1rem, 1.25vw, 1.12rem);
font-weight: 600;
line-height: 1.35;
color: var(--text);
flex: 0 0 auto;
background: var(--surface);
border: 1px solid color-mix(in srgb, var(--line), var(--text) 6%);
border-radius: calc(var(--radius-sm) + 2px);
transition: border-color 0.22s ease;
}
/* Мост «задача → решения» (высота = зазору между блоками) */
.skill-task-card__task::after {
content: "";
position: absolute;
left: var(--skill-connector-shift-right);
bottom: 0;
width: 0;
height: var(--skill-connector-task-to-solutions-gap);
border-left: 1px solid var(--skill-connector-color-bridge);
pointer-events: none;
}
.skill-task-card__solutions {
position: relative;
flex: 1 1 auto;
margin: var(--skill-connector-task-to-solutions-gap) 0 0.5rem;
padding: 0 0 0 var(--skill-solutions-padding-left);
border: 0;
border-radius: 0;
background: transparent;
display: flex;
flex-direction: column;
align-items: flex-start;
gap: var(--skill-solutions-stack-gap);
transform: none;
transition: none;
}
.skill-task-card__solution {
--skill-solution-connector-radius: calc(var(--radius-sm) + 2px);
--skill-connector-elbow-top: calc(50% - var(--skill-connector-stitch));
--skill-connector-elbow-height: calc(50% + var(--skill-connector-stitch));
position: relative;
margin: 0;
padding: 0.56rem 0.68rem;
font-size: 0.82rem;
line-height: 1.45;
color: var(--text-muted);
background: var(--surface);
border: 1px solid color-mix(in srgb, var(--skill-solution-separator), var(--text) 6%);
border-radius: calc(var(--radius-sm) + 2px);
display: inline-block;
vertical-align: top;
max-width: 100%;
transition: color 0.22s ease, border-color 0.22s ease;
}
/* Вертикаль (как li::before в css-tree-menu) */
.skill-task-card__solution::before {
content: "";
position: absolute;
left: calc(-1 * var(--skill-connector-arm) + var(--skill-connector-shift-right));
top: 0;
width: 0;
border-left: 1px solid var(--skill-connector-color-spine);
pointer-events: none;
}
.skill-task-card__solution:not(:last-child)::before {
height: calc(100% + var(--skill-solutions-stack-gap) + var(--skill-connector-stitch));
bottom: auto;
}
.skill-task-card__solution:last-child::before {
height: var(--skill-connector-elbow-height);
bottom: auto;
}
.skill-task-card__solution:first-child::before {
top: calc(-1 * var(--skill-connector-first-pull));
}
.skill-task-card__solution:first-child:not(:last-child)::before {
height: calc(100% + var(--skill-solutions-stack-gap) + var(--skill-connector-stitch) + var(--skill-connector-first-pull));
}
.skill-task-card__solution:first-child:last-child::before {
height: calc(50% + var(--skill-connector-first-pull) + var(--skill-connector-stitch));
}
/* Уголок L (как отдельная горизонталь + скругление в css-tree-menu) */
.skill-task-card__solution::after {
content: "";
position: absolute;
left: calc(-1 * var(--skill-connector-arm) + var(--skill-connector-shift-right));
top: var(--skill-connector-elbow-top);
width: calc(var(--skill-connector-arm) - var(--skill-connector-shift-right));
height: var(--skill-connector-elbow-height);
border-bottom: 1px solid var(--skill-connector-color-elbow-h);
border-left: 1px solid var(--skill-connector-color-elbow-v);
border-bottom-left-radius: var(--skill-solution-connector-radius);
pointer-events: none;
}
.skill-task-card__solution:hover,
.skill-task-card__solution:focus-visible {
color: var(--text);
border-color: var(--accent);
}
/* Ховер по решению: акцент на карточке задачи и наведённом решении */
.skill-task-card:has(.skill-task-card__solution:is(:hover, :focus-visible)) .skill-task-card__task {
border-color: var(--accent);
}
/* Коннектор без JS: только псевдоэлементы наведённого решения; мост из задачи — при любом ховере по решению */
.skill-task-card__solution:hover::before,
.skill-task-card__solution:hover::after {
border-color: var(--accent);
}
.skill-task-card:has(.skill-task-card__solution:hover) .skill-task-card__task::after {
border-color: var(--accent);
}
html[data-radius="strong"] .skill-task-card__task {
border-radius: 1.15rem;
}
html[data-radius="strong"] .skill-task-card__solution {
--skill-solution-connector-radius: 1rem;
border-radius: 1rem;
}
.skill-grid {
display: grid;
gap: 1.5rem;
grid-template-columns: 1fr;
}
@media (min-width: 720px) {
.skill-grid {
grid-template-columns: repeat(2, 1fr);
}
}
.skill-block {
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--radius-md);
padding: 1.25rem 1.35rem;
}
.skill-block__title {
margin: 0 0 0.75rem;
font-size: 1rem;
font-weight: 600;
}
.skill-block__list {
margin: 0;
padding-left: 1.1rem;
color: var(--text-muted);
font-size: 0.92rem;
}
.skill-block__list li + li {
margin-top: 0.4rem;
}
.contact-grid {
list-style: none;
margin: 0;
padding: 0;
display: grid;
gap: 0.75rem;
grid-template-columns: 1fr;
}
@media (min-width: 560px) {
.contact-grid {
grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
}
}
.contact-grid > li {
margin: 0;
min-width: 0;
}
.contact-card {
box-sizing: border-box;
position: relative;
display: flex;
align-items: flex-start;
gap: 0.75rem;
width: 100%;
min-height: 100%;
padding: 1rem 2.35rem 1rem 1.1rem;
border: 1px solid var(--line);
border-radius: var(--radius-card);
background: var(--surface);
color: inherit;
text-decoration: none;
overflow: hidden;
isolation: isolate;
transition: border-color 0.22s ease, transform 0.28s ease, box-shadow 0.28s ease;
}
/* Бренд канала = цвет из соответствующей иконки (см. SVG в assets/shared/icons/) */
.contact-card--brand-tg {
--contact-brand: #0088cc;
}
.contact-card--brand-vk {
--contact-brand: #0077ff;
}
.contact-card--brand-whatsapp {
--contact-brand: #25D366;
}
.contact-card--brand-ya {
--contact-brand: #f8604a;
}
/* Почта — акцент темы (пикер), не цвет из SVG */
.contact-card--brand-email {
--contact-brand: var(--accent);
}
.contact-card::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
z-index: 0;
background: radial-gradient(
ellipse 130% 120% at 0% 100%,
color-mix(in srgb, var(--contact-brand) 26%, transparent) 0%,
transparent 58%
);
opacity: 0.42;
}
.contact-card:hover,
.contact-card:focus-visible {
border-color: color-mix(in srgb, var(--contact-brand) 58%, var(--line));
transform: translateY(-5px);
z-index: 2;
box-shadow: 0 8px 18px -10px color-mix(in srgb, var(--contact-brand) 28%, transparent),
0 2px 6px -3px color-mix(in srgb, var(--contact-brand) 14%, transparent);
}
@media (prefers-reduced-motion: reduce) {
.contact-card__name {
transition: none;
}
.contact-card__corner {
transition: none;
}
}
.contact-card__corner {
position: absolute;
top: 0.55rem;
right: 0.55rem;
z-index: 2;
width: var(--icon-contact-meta);
height: var(--icon-contact-meta);
pointer-events: none;
background-color: color-mix(in srgb, var(--text-muted) 88%, transparent);
transition: background-color 0.22s ease;
mask-image: url("../assets/shared/icons/arrow_upright.svg");
-webkit-mask-image: url("../assets/shared/icons/arrow_upright.svg");
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
}
/* Среднее скругление — уголок чуть ниже и левее базовой позиции */
html[data-radius="medium"] .contact-card__corner {
top: calc(0.75rem + 0.1rem);
right: calc(0.75rem + 0.1rem);
}
/* При сильном скруглении карточки — уголок по вертикали по центру строки с иконкой канала, чуть левее от правого края */
html[data-radius="strong"] .contact-card__corner {
top: calc(1rem + 1.25rem);
right: 1.8rem;
transform: translateY(-50%);
}
.contact-card:hover .contact-card__corner,
.contact-card:focus-visible .contact-card__corner {
background-color: color-mix(in srgb, var(--contact-brand) 82%, transparent);
}
.contact-card__corner--copy {
mask-image: url("../assets/shared/icons/copy.svg");
-webkit-mask-image: url("../assets/shared/icons/copy.svg");
}
.contact-card__icon,
.contact-card__body {
position: relative;
z-index: 1;
}
.contact-card--action {
margin: 0;
font: inherit;
text-align: left;
cursor: pointer;
}
.contact-card__icon {
flex: 0 0 auto;
display: grid;
place-items: center;
width: 2.5rem;
height: 2.5rem;
border-radius: var(--radius-md);
background: color-mix(in srgb, var(--contact-brand) 10%, transparent);
}
.contact-card__icon img {
width: var(--icon-contact);
height: var(--icon-contact);
display: block;
}
.contact-card__icon--accent {
background: color-mix(in srgb, var(--contact-brand) 10%, transparent);
}
.contact-card__icon--accent::before {
content: "";
width: var(--icon-contact);
height: var(--icon-contact);
display: block;
background-color: var(--contact-brand);
mask-image: url("../assets/shared/icons/email.svg");
-webkit-mask-image: url("../assets/shared/icons/email.svg");
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
}
.contact-card__body {
flex: 1 1 auto;
min-width: 0;
display: flex;
flex-direction: column;
gap: 0.2rem;
}
.contact-card__name {
font-family: var(--font-accent);
font-size: 1rem;
font-weight: 600;
line-height: 1.25;
color: var(--text);
transition: color 0.22s ease;
}
.contact-card:hover .contact-card__name,
.contact-card:focus-visible .contact-card__name {
color: var(--contact-brand);
}
a.contact-card--link,
a.contact-card--link:visited {
color: var(--text);
text-decoration: none;
}
a.contact-card--link:hover,
a.contact-card--link:focus-visible {
color: var(--text);
}
.contact-card__hint {
font-size: 0.86rem;
line-height: 1.35;
color: var(--text-muted);
}
.contact-card--link:focus-visible,
.contact-card--action:focus-visible {
outline: 2px solid color-mix(in srgb, var(--contact-brand) 72%, var(--line));
outline-offset: 2px;
}
.section--footerish {
padding-bottom: clamp(2.5rem, 5vw, 3.5rem);
}
#contact.section--footerish {
padding-bottom: calc(2 * clamp(2.5rem, 5vw, 3.5rem));
}
.footer {
padding: 1.25rem max(var(--space), env(safe-area-inset-right, 0px)) calc(1.25rem + env(safe-area-inset-bottom, 0px)) max(var(--space), env(safe-area-inset-left, 0px));
color: var(--text-muted);
font-size: 0.85rem;
}
.footer__inner {
max-width: var(--max);
margin: 0 auto;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.35rem 0.5rem;
}
.footer__chunk--date,
.footer__chunk--meta {
white-space: nowrap;
}
.footer__chunk--main {
min-width: 0;
}
.footer__sep {
opacity: 0.5;
}
.footer__attr {
opacity: 0.75;
}
.footer__attr a {
color: var(--text-muted);
font-weight: 500;
}
.footer__attr a:hover {
color: var(--accent-text);
}
.cookie-notice {
position: fixed;
left: max(var(--space), env(safe-area-inset-left, 0px));
right: auto;
bottom: max(0.85rem, env(safe-area-inset-bottom, 0px));
/* Не заходить под FAB справа: инсеты + ширина кнопки (~3rem) + заметный зазор */
max-width: min(
32rem,
calc(
100vw - max(var(--space), env(safe-area-inset-left, 0px)) - max(var(--space), env(safe-area-inset-right, 0px)) - 3rem - 2rem
)
);
padding: 0.72rem 0.85rem;
border: 1px solid var(--line);
border-radius: var(--radius-md);
background: color-mix(in srgb, var(--bg-elevated) 94%, var(--bg));
box-shadow: 0 12px 28px hsla(0, 0%, 0%, 0.18);
z-index: 2147483647;
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
gap: 0.65rem;
}
.cookie-notice[hidden] {
display: none !important;
}
.cookie-notice__text {
margin: 0;
color: var(--text-muted);
font-size: 0.86rem;
line-height: 1.45;
}
.cookie-notice__text a {
color: var(--text);
}
.cookie-notice__text a:hover {
color: var(--accent-text);
}
.cookie-notice .btn {
font-size: 0.85rem;
font-weight: 600;
line-height: 1;
padding: 0.55rem 0.8rem;
white-space: nowrap;
gap: 0.45rem;
}
.cookie-notice__accept-icon {
display: flex;
align-items: center;
flex-shrink: 0;
line-height: 0;
}
.cookie-notice__accept-icon img {
display: block;
width: 1.125rem;
height: 1.125rem;
}
/* --- Адаптив: телефон / планшет / монитор --- */
html {
overflow-x: hidden;
}
@media (max-width: 639.98px) {
html {
font-size: 0.9375rem;
}
.theme-picker__panel {
width: min(calc(320px + 2.2rem), calc(100vw - 1.25rem));
max-width: calc(100vw - 1.25rem);
max-height: min(85vh, 540px);
}
.hero {
padding-top: calc(2 * clamp(1rem, 4vw, 1.75rem));
}
.section {
padding: calc(2 * clamp(2rem, 6vw, 2.75rem)) calc(2 * max(var(--space), env(safe-area-inset-right, 0px))) calc(2 * clamp(2rem, 6vw, 2.75rem)) calc(2 * max(var(--space), env(safe-area-inset-left, 0px)));
}
.hero__title {
font-size: clamp(2.45rem, 10vw, 3.35rem);
}
.hero-rotator {
min-width: 7ch;
}
.hero__tags {
margin-bottom: 1.1rem;
gap: 0.4rem;
}
.hero__tag {
font-size: 0.82rem;
padding: 0.32rem 0.6rem;
}
.hero__actions {
flex-direction: column;
align-items: stretch;
gap: 0.65rem;
}
.hero__actions .btn {
width: 100%;
justify-content: center;
min-height: 48px;
padding: 0.75rem 1.25rem;
}
.cookie-notice {
left: max(0.75rem, env(safe-area-inset-left, 0px));
right: auto;
max-width: min(
32rem,
calc(
100vw - max(0.75rem, env(safe-area-inset-left, 0px)) - max(0.75rem, env(safe-area-inset-right, 0px)) - 3rem - 2rem
)
);
grid-template-columns: 1fr;
gap: 0.55rem;
}
.radius-seg__btn {
min-height: 52px;
padding: 0.45rem 0.2rem;
}
.radius-seg__viz {
width: 40px;
height: 40px;
}
.radius-seg__arc {
width: 24px;
height: 24px;
}
.fab-stack {
right: max(0.75rem, env(safe-area-inset-right, 0px));
bottom: max(0.75rem, env(safe-area-inset-bottom, 0px));
gap: 0.5rem;
}
.content-edit-fab-stack {
left: max(0.75rem, env(safe-area-inset-left, 0px));
bottom: max(0.75rem, env(safe-area-inset-bottom, 0px));
gap: 0.5rem;
}
}
@media (pointer: coarse) {
.btn {
min-height: 44px;
touch-action: manipulation;
}
.colorpicker__hue {
height: 28px;
}
.colorpicker__hue::-webkit-slider-runnable-track {
height: 16px;
border-radius: 8px;
}
.colorpicker__hue::-webkit-slider-thumb {
width: 24px;
height: 24px;
margin-top: -5px;
}
.colorpicker__hue::-moz-range-track {
height: 16px;
border-radius: 8px;
}
.colorpicker__hue::-moz-range-thumb {
width: 24px;
height: 24px;
}
.colorpicker__knob {
width: 24px;
height: 24px;
margin: -12px 0 0 -12px;
}
}
@media (min-width: 640px) and (max-width: 1023.98px) {
html {
font-size: 0.96875rem;
}
.header__inner {
row-gap: 0.65rem;
}
.hero__grid {
gap: clamp(1.75rem, 4vw, 2.75rem);
}
.hero {
padding-top: calc(2 * clamp(2rem, 5vw, 3.75rem));
padding-bottom: calc(2 * clamp(1.75rem, 4vw, 3rem));
}
.section {
padding: calc(2 * clamp(2rem, 4vw, 3.25rem)) calc(2 * max(var(--space), env(safe-area-inset-right, 0px))) calc(2 * clamp(2rem, 4vw, 3.25rem)) calc(2 * max(var(--space), env(safe-area-inset-left, 0px)));
}
.card {
padding: 1.25rem 1.25rem;
}
.skill-block {
padding: 1.15rem 1.2rem;
}
}
@media (min-width: 1024px) {
.header__inner {
padding-block: 0.8rem;
}
.header__cluster {
gap: 0.85rem 1.35rem;
}
.nav {
gap: 0.65rem 1.2rem;
font-size: 0.925rem;
}
.hero {
padding-top: calc(2 * clamp(2.75rem, 5vw, 4.75rem));
}
.section {
padding: calc(2 * clamp(2.75rem, 4.5vw, 4.25rem)) calc(2 * max(var(--space), env(safe-area-inset-right, 0px))) calc(2 * clamp(2.75rem, 4.5vw, 4.25rem)) calc(2 * max(var(--space), env(safe-area-inset-left, 0px)));
}
}
/* v1: liquid glass — отдельные параметры для светлой и тёмной темы */
/* Токены glass: .glass-neutral + парящая шапка (.header--scrolled .header__inner) + overflow-меню */
html[data-theme="dark"] {
--v12-glass-neutral-bg: linear-gradient(
145deg,
color-mix(in srgb, var(--bg-elevated) 80%, transparent),
color-mix(in srgb, var(--surface) 52%, transparent)
);
--v12-glass-neutral-border: color-mix(in srgb, var(--line) 75%, hsla(0, 0%, 100%, 0.08));
--v12-glass-neutral-shadow:
0 14px 32px hsla(0, 0%, 0%, 0.4),
inset 0 1px 0 hsla(0, 0%, 100%, 0.09);
--v12-glass-neutral-filter: blur(16px) saturate(118%);
--v12-glass-neutral-filter-elevated: blur(18px) saturate(125%);
}
html[data-theme="light"] {
--v12-glass-neutral-bg: linear-gradient(
145deg,
color-mix(in srgb, var(--surface) 62%, hsla(0, 0%, 100%, 0.45)),
color-mix(in srgb, var(--bg-elevated) 38%, transparent)
);
--v12-glass-neutral-border: color-mix(in srgb, var(--line) 58%, hsla(0, 0%, 0%, 0.07));
--v12-glass-neutral-shadow:
0 14px 28px hsla(var(--theme-h), 22%, 38%, 0.11),
inset 0 1px 0 hsla(0, 0%, 100%, 0.9),
inset 0 -1px 0 hsla(0, 0%, 0%, 0.04);
--v12-glass-neutral-filter: blur(12px) saturate(124%);
--v12-glass-neutral-filter-elevated: blur(14px) saturate(130%);
}
html[data-theme="dark"] .header--scrolled .header__inner,
html[data-theme="light"] .header--scrolled .header__inner {
background: var(--v12-glass-neutral-bg);
border-color: var(--v12-glass-neutral-border);
box-shadow: var(--v12-glass-neutral-shadow);
backdrop-filter: var(--v12-glass-neutral-filter-elevated);
-webkit-backdrop-filter: var(--v12-glass-neutral-filter-elevated);
}
/* ========== Тёмная тема: плашки, FAB, overflow ========== */
html[data-theme="dark"] .glass-neutral,
html[data-theme="light"] .glass-neutral {
background: var(--v12-glass-neutral-bg);
border-color: var(--v12-glass-neutral-border);
box-shadow: var(--v12-glass-neutral-shadow);
backdrop-filter: var(--v12-glass-neutral-filter);
-webkit-backdrop-filter: var(--v12-glass-neutral-filter);
}
html[data-theme="dark"] .theme-picker__panel.glass-neutral,
html[data-theme="dark"] .cookie-notice.glass-neutral,
html[data-theme="light"] .theme-picker__panel.glass-neutral,
html[data-theme="light"] .cookie-notice.glass-neutral {
backdrop-filter: var(--v12-glass-neutral-filter-elevated);
-webkit-backdrop-filter: var(--v12-glass-neutral-filter-elevated);
}
html[data-theme="dark"] .fab.glass-neutral:not(.fab--primary):hover,
html[data-theme="dark"] .fab.glass-neutral:not(.fab--primary):focus-visible,
html[data-theme="light"] .fab.glass-neutral:not(.fab--primary):hover,
html[data-theme="light"] .fab.glass-neutral:not(.fab--primary):focus-visible {
backdrop-filter: var(--v12-glass-neutral-filter-elevated);
-webkit-backdrop-filter: var(--v12-glass-neutral-filter-elevated);
}
html[data-theme="dark"] .nav-more__dock,
html[data-theme="light"] .nav-more__dock,
html[data-theme="dark"] #nav-more-menu-floating,
html[data-theme="light"] #nav-more-menu-floating {
background: var(--v12-glass-neutral-bg);
border-color: var(--v12-glass-neutral-border);
box-shadow: var(--v12-glass-neutral-shadow);
backdrop-filter: var(--v12-glass-neutral-filter-elevated);
-webkit-backdrop-filter: var(--v12-glass-neutral-filter-elevated);
}
html[data-theme="dark"] .nav-more__dock::before,
html[data-theme="light"] .nav-more__dock::before,
html[data-theme="dark"] #nav-more-menu-floating::before,
html[data-theme="light"] #nav-more-menu-floating::before {
content: none;
}
html[data-theme="dark"] #nav-more-menu-floating a {
position: relative;
z-index: 1;
color: color-mix(in srgb, var(--text) 72%, var(--text-muted));
}
html[data-theme="dark"] #nav-more-menu-floating a:hover {
color: var(--text);
}
html[data-theme="dark"] .cookie-notice .cookie-notice__text {
color: color-mix(in srgb, var(--text) 58%, var(--text-muted));
}
html[data-theme="light"] #nav-more-menu-floating a {
position: relative;
z-index: 1;
color: color-mix(in srgb, var(--text) 22%, var(--text-muted));
}
html[data-theme="light"] #nav-more-menu-floating a:hover {
color: var(--text);
}
html[data-theme="light"] .cookie-notice .cookie-notice__text {
color: color-mix(in srgb, var(--text) 20%, var(--text-muted));
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
html[data-theme="dark"] .fab--primary,
html[data-theme="dark"] .btn--primary,
html[data-theme="light"] .fab--primary,
html[data-theme="light"] .btn--primary {
background: radial-gradient(
150% 160% at 0% 0%,
var(--accent-btn-radial-core) 0%,
var(--accent-btn-radial-mid) 52%,
var(--accent-btn-radial-edge) 100%
);
border-color: transparent;
box-shadow: var(--shadow-strong);
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
html[data-theme="dark"] .btn--primary.btn--flat,
html[data-theme="light"] .btn--primary.btn--flat {
box-shadow: none;
}
html[data-theme="dark"] .fab--primary::after,
html[data-theme="dark"] .btn--primary::after,
html[data-theme="light"] .fab--primary::after,
html[data-theme="light"] .btn--primary::after {
display: none;
}
html[data-theme="dark"] a.fab--primary:visited,
html[data-theme="dark"] a.btn--primary:visited,
html[data-theme="light"] a.fab--primary:visited,
html[data-theme="light"] a.btn--primary:visited {
background: radial-gradient(
150% 160% at 0% 0%,
var(--accent-btn-radial-core) 0%,
var(--accent-btn-radial-mid) 52%,
var(--accent-btn-radial-edge) 100%
);
}
html[data-theme="dark"] .fab--primary:hover,
html[data-theme="dark"] .fab--primary:focus-visible,
html[data-theme="dark"] .btn--primary:hover,
html[data-theme="dark"] .btn--primary:focus-visible,
html[data-theme="light"] .fab--primary:hover,
html[data-theme="light"] .fab--primary:focus-visible,
html[data-theme="light"] .btn--primary:hover,
html[data-theme="light"] .btn--primary:focus-visible {
background: radial-gradient(
150% 160% at 0% 0%,
color-mix(in hsl, var(--accent-btn-radial-core), white 5%) 0%,
color-mix(in hsl, var(--accent-btn-radial-mid), white 8%) 52%,
color-mix(in hsl, var(--accent-btn-radial-edge), white 4%) 100%
);
}
html[data-theme="dark"] .glass-neutral,
html[data-theme="light"] .glass-neutral {
background: var(--v12-glass-neutral-bg);
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
html[data-theme="dark"] .header--scrolled .header__inner,
html[data-theme="light"] .header--scrolled .header__inner {
background: var(--bg-elevated);
box-shadow: 0 16px 38px hsla(0, 0%, 0%, 0.2);
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
html[data-theme="dark"] .nav-more__dock,
html[data-theme="light"] .nav-more__dock,
html[data-theme="dark"] #nav-more-menu-floating,
html[data-theme="light"] #nav-more-menu-floating {
background: var(--bg-elevated);
border-color: var(--line);
box-shadow: var(--shadow-strong);
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
}
#contact.section.section--footerish {
padding-bottom: calc(2 * clamp(2.5rem, 5vw, 3.5rem)) !important;
}
/* --- Режим правок контента (localhost) --- */
.content-edit-fab-stack {
position: fixed;
left: max(var(--space), env(safe-area-inset-left, 0px));
bottom: max(1rem, env(safe-area-inset-bottom, 0px));
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.6rem;
z-index: 1500;
transition: bottom 0.2s ease;
}
body.content-edit-mode-active .content-edit-fab-stack {
bottom: calc(var(--content-edit-dock-height, 14rem) + 1.25rem + env(safe-area-inset-bottom, 0px));
}
.content-edit-fab {
position: relative;
overflow: visible;
}
.content-edit-fab[hidden] {
display: none !important;
}
.content-edit-fab__badge {
position: absolute;
top: 0;
right: 0;
z-index: 1;
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 1.125rem;
height: 1.125rem;
padding: 0 0.28rem;
border-radius: 999px;
font-size: 0.625rem;
font-weight: 700;
line-height: 1;
font-variant-numeric: tabular-nums;
letter-spacing: -0.02em;
color: var(--on-accent);
background: var(--accent);
border: 2px solid var(--bg);
box-sizing: border-box;
transform: translate(42%, -42%);
pointer-events: none;
}
.content-edit-fab__badge[hidden] {
display: none !important;
}
.content-edit-fab.is-active,
.fab.content-edit-fab[data-content-edit-mode-toggle].is-active {
border-color: var(--accent);
color: var(--accent-text);
}
body.content-edit-mode-active main {
cursor: crosshair;
}
body.content-edit-mode-active main a,
body.content-edit-mode-active main button,
body.content-edit-mode-active main video {
cursor: default;
}
.content-edit-outline-hover {
outline: 1.5px dashed color-mix(in srgb, var(--accent) 48%, transparent);
outline-offset: 3px;
}
.content-edit-outline-ref-hover {
outline: 1.5px dashed color-mix(in srgb, var(--accent) 78%, transparent);
outline-offset: 3px;
}
body.content-edit-shift-active.content-edit-mode-active main {
cursor: crosshair;
}
body.content-edit-shift-active.content-edit-mode-active .content-edit-dock,
body.content-edit-shift-active.content-edit-mode-active .content-edit-fab-stack {
cursor: default;
}
.content-edit-outline {
outline: 2px solid color-mix(in srgb, var(--accent) 72%, transparent);
outline-offset: 3px;
}
.content-edit-dock {
--content-edit-lines: 5;
position: fixed;
left: max(var(--space), env(safe-area-inset-left, 0px));
bottom: max(1rem, env(safe-area-inset-bottom, 0px));
z-index: 1490;
display: grid;
grid-template-columns: minmax(11rem, 34%) 1fr;
width: min(56rem, calc(100vw - 2 * max(var(--space), env(safe-area-inset-left, 0px))));
height: calc(2.15rem + 1.45em * var(--content-edit-lines) + 3.85rem);
max-height: calc(2.15rem + 1.45em * var(--content-edit-lines) + 3.85rem);
border: 1px solid var(--v12-glass-neutral-border);
border-radius: var(--radius-md);
overflow: hidden;
}
.content-edit-dock[hidden] {
display: none !important;
}
.content-edit-dock__list {
display: flex;
flex-direction: column;
min-height: 0;
border-right: 1px solid var(--line);
}
.content-edit-dock__heading {
margin: 0;
padding: 0.55rem 0.75rem 0.4rem;
font-size: 0.88rem;
font-weight: 600;
line-height: 1.25;
color: var(--text);
border-bottom: 1px solid var(--line);
flex-shrink: 0;
}
.content-edit-dock__items {
margin: 0;
padding: 0.35rem;
list-style: none;
overflow-y: auto;
flex: 1;
min-height: 0;
}
.content-edit-dock__row {
display: flex;
align-items: stretch;
gap: 0.25rem;
}
.content-edit-dock__row + .content-edit-dock__row {
margin-top: 0.2rem;
}
.content-edit-dock__item {
display: block;
flex: 1;
min-width: 0;
text-align: left;
padding: 0.5rem 0.55rem;
border: 0;
border-radius: var(--radius-sm);
background: transparent;
color: var(--text);
font: inherit;
font-size: 0.86rem;
line-height: 1.35;
cursor: pointer;
}
.content-edit-dock__delete {
flex-shrink: 0;
align-self: center;
display: grid;
place-items: center;
width: 1.85rem;
height: 1.85rem;
padding: 0;
border: 0;
border-radius: var(--radius-sm);
background: transparent;
color: var(--text-muted);
cursor: pointer;
}
.content-edit-dock__delete-icon {
display: block;
width: 1rem;
height: 1rem;
background: currentColor;
mask-image: url("../assets/shared/icons/delete.svg");
-webkit-mask-image: url("../assets/shared/icons/delete.svg");
mask-size: contain;
mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
pointer-events: none;
}
.content-edit-dock__delete:hover,
.content-edit-dock__delete:focus-visible {
color: var(--text);
background: color-mix(in srgb, var(--accent) 10%, transparent);
outline: none;
}
.content-edit-dock__item.is-selected,
.content-edit-dock__item:hover,
.content-edit-dock__item:focus-visible {
background: color-mix(in srgb, var(--accent) 12%, transparent);
outline: none;
}
.content-edit-dock__item.is-selected {
color: var(--accent-text);
}
.content-edit-dock__empty {
margin: 0;
padding: 0.75rem;
font-size: 0.86rem;
color: var(--text-muted);
}
.content-edit-dock__editor {
display: flex;
flex-direction: column;
min-height: 0;
overflow: hidden;
}
.content-edit-dock__editor-body {
display: flex;
flex-direction: column;
justify-content: flex-end;
flex: 1;
min-height: 0;
padding: 0.65rem 0.85rem;
}
.content-edit-dock__input {
display: block;
width: 100%;
height: calc(1.45em * var(--content-edit-lines) + 0.9rem);
min-height: calc(1.45em * var(--content-edit-lines) + 0.9rem);
max-height: calc(1.45em * var(--content-edit-lines) + 0.9rem);
padding: 0.45rem 0.55rem;
border: 1px solid var(--line);
border-radius: var(--radius-sm);
font: inherit;
line-height: 1.45;
color: var(--text);
background: var(--bg);
resize: none;
overflow-y: auto;
box-sizing: border-box;
flex-shrink: 0;
}
.content-edit-dock__input:disabled {
opacity: 0.55;
cursor: not-allowed;
}
.content-edit-dock__input:focus-visible {
outline: 2px solid color-mix(in srgb, var(--accent) 55%, transparent);
outline-offset: 1px;
}
.content-edit-dock__hint {
margin: 0.35rem 0 0;
font-size: 0.78rem;
line-height: 1.3;
color: var(--text-muted);
flex-shrink: 0;
}
@media (max-width: 640px) {
.content-edit-dock {
grid-template-columns: 1fr;
grid-template-rows: auto auto;
height: auto;
max-height: min(70vh, 28rem);
}
.content-edit-dock__list {
border-right: 0;
border-bottom: 1px solid var(--line);
}
}
/* Marquee — бегущая строка */
.marquee {
overflow: hidden;
}
.marquee__track {
display: flex;
width: max-content;
animation: marquee 30s linear infinite;
}
.marquee__content {
display: flex;
gap: 1rem;
padding-right: 1rem;
}
.marquee__content .hero__tag {
white-space: nowrap;
flex-shrink: 0;
}
/* Альтернативный вариант marquee: статичная flex-сетка чипсов */
.marquee--grid {
/* padding inherited from .section */
}
.marquee-grid {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
justify-content: flex-start;
}
.marquee-grid__cell {
margin: 0;
flex: 0 0 auto;
}
.marquee-grid__cell .hero__tag {
white-space: nowrap;
}
/* Marquee появляется мягче, чем обычные секции (без большого сдвига) */
.marquee[data-reveal] {
opacity: 0;
transform: translateY(16px);
transition: opacity 0.5s ease, transform 0.5s ease;
}
.marquee[data-reveal].is-visible {
opacity: 1;
transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
.marquee[data-reveal] {
opacity: 1;
transform: none;
transition: none;
}
}
@keyframes marquee {
0% { transform: translateX(0); }
100% { transform: translateX(-33.333%); }
}
/* Separator */
.sep {
border: none;
margin: 0;
padding: 0;
}
.sep--line {
border-top: 1px solid var(--line);
height: 0;
}
.sep--air {
height: 1.5rem;
}
.sep--air-lg {
height: 2.5rem;
}
/* Слайдер изображений в лонгриде кейса: одна картинка + стрелки + точки */
.case-media-slider {
--slider-gap: 0;
--slider-radius: var(--radius-card);
--slider-ctrl-size: 2.5rem;
--slider-ctrl-inset: 0.75rem;
--slider-dot-size: 0.375rem;
--slider-dot-gap: 0.375rem;
position: relative;
margin: 0.85rem 0 1.2rem;
border-radius: var(--slider-radius);
}
.case-media-slider__viewport {
position: relative;
overflow: hidden;
width: 100%;
border: 1px solid var(--line);
border-radius: var(--slider-radius);
box-sizing: border-box;
background: color-mix(in srgb, var(--surface) 55%, transparent);
touch-action: pan-y;
cursor: grab;
transition:
border-color 0.2s ease,
box-shadow 0.2s ease;
}
.case-media-slider:hover .case-media-slider__viewport {
border-color: var(--accent);
box-shadow: 0 8px 24px color-mix(in srgb, var(--accent) 18%, transparent);
}
.case-media-slider__viewport:active {
cursor: grabbing;
}
.case-media-slider__track {
display: flex;
width: 100%;
transition: transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
will-change: transform;
}
.case-media-slider__slide {
flex: 0 0 100%;
min-width: 0;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.case-media-slider__slide img {
display: block;
width: 100%;
height: auto;
max-height: 80vh;
object-fit: contain;
}
/* Подпись под активным слайдом (как у case-media) */
.case-media-slider__slide figcaption,
.case-media-slider figcaption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 0.6rem 0.9rem;
font-size: 0.82rem;
color: var(--text-muted);
text-align: center;
background: color-mix(in srgb, var(--surface) 78%, transparent);
backdrop-filter: blur(6px);
}
/* Стрелки */
/* Группа кнопок пред/след — слитая «пилюля» в нижнем правом углу */
.case-media-slider__nav-group {
position: absolute;
right: var(--slider-ctrl-inset);
bottom: var(--slider-ctrl-inset);
z-index: 3;
display: inline-flex;
border-radius: 999px;
overflow: hidden;
opacity: 0;
transition: opacity 0.18s ease;
}
.case-media-slider:hover .case-media-slider__nav-group,
.case-media-slider__nav-group:focus-within {
opacity: 1;
}
.case-media-slider__nav {
width: var(--slider-ctrl-size);
height: var(--slider-ctrl-size);
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid var(--line);
border-radius: 0;
background: color-mix(in srgb, var(--surface) 86%, transparent);
color: var(--text-muted);
cursor: pointer;
transition: color 0.18s ease, border-color 0.18s ease, background 0.18s ease;
}
/* Соседняя кнопка перекрывает разделительный бордер */
.case-media-slider__nav + .case-media-slider__nav {
margin-left: -1px;
}
/* Скругления только на крайних кнопках группы */
.case-media-slider__nav:first-child {
border-radius: 999px 0 0 999px;
}
.case-media-slider__nav:last-child {
border-radius: 0 999px 999px 0;
}
.case-media-slider__nav:hover:not(:disabled),
.case-media-slider__nav:focus-visible:not(:disabled) {
color: var(--accent-text);
border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
position: relative;
z-index: 1;
}
.case-media-slider__nav:disabled {
opacity: 0.4;
cursor: default;
pointer-events: none;
}
.case-media-slider__nav-ico {
width: 1rem;
height: 1rem;
display: block;
background: currentColor;
mask-size: contain;
-webkit-mask-size: contain;
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
mask-position: center;
-webkit-mask-position: center;
transition: transform 0.12s ease;
}
/* Нажатие: иконка слегка «продавливается» внутрь (общий .icon-press) */
.case-media-slider__nav-ico--left {
mask-image: url("../assets/shared/icons/shevron-left.svg");
-webkit-mask-image: url("../assets/shared/icons/shevron-left.svg");
}
.case-media-slider__nav-ico--right {
mask-image: url("../assets/shared/icons/shevron-right.svg");
-webkit-mask-image: url("../assets/shared/icons/shevron-right.svg");
}
/* Точки-пагинация */
.case-media-slider__dots {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: var(--slider-dot-gap);
margin-top: 0.9rem;
padding: 0.2rem 0;
}
.case-media-slider__dot {
width: var(--slider-dot-size);
height: var(--slider-dot-size);
padding: 0;
border: none;
border-radius: 50%;
background: color-mix(in srgb, var(--text-muted) 40%, transparent);
cursor: pointer;
transition: background 0.22s ease, width 0.28s cubic-bezier(0.22, 0.61, 0.36, 1), border-radius 0.28s ease;
}
.case-media-slider__dot:hover,
.case-media-slider__dot:focus-visible {
background: color-mix(in srgb, var(--text-muted) 65%, transparent);
}
.case-media-slider__dot.is-active {
background: var(--accent);
width: calc(var(--slider-dot-size) * 2.6);
border-radius: 999px;
}
/* Неактивные слайды: скрыты от скринридеров (aria-hidden в JS), но остаются видимыми,
чтобы при сдвиге трека не было «дырки» от мгновенно исчезнувшего кадра. */
.case-media-slider__slide:not(.is-active) {
pointer-events: none;
}
/* Настраиваемая ширина — как у статичных .case-media (--wide / --content / --natural).
Кнопки пред/след внутри viewport, поэтому не участвуют в расчёте ширины.
Высота — автоматически по контенту. */
/* Базовый / --content: встроен в колонку контента, не шире её */
.case-media-slider,
.case-media-slider.case-media--content {
display: block;
width: 100%;
max-width: 100%;
margin-inline: auto;
}
/* --wide: как одиночные wide-картинки страницы — выходит за колонку, центр по вьюпорту */
.case-media-slider.case-media--wide {
width: min(calc(100vw - (max(var(--space), env(safe-area-inset-left)) + max(var(--space), env(safe-area-inset-right)))), calc(100% + 8rem));
max-width: none;
margin-left: 50%;
transform: translateX(-50%);
}
/* --natural / auto: ширина по картинке (--slider-natural-w или авто из JS), не больше ширины экрана */
.case-media-slider.case-media--natural {
display: block;
width: min(var(--slider-natural-w, 100%), 100vw);
max-width: 100vw;
margin-left: 50%;
transform: translateX(-50%);
}
.case-media-slider .case-media-slider__viewport,
.case-media-slider.case-media--content .case-media-slider__viewport,
.case-media-slider.case-media--wide .case-media-slider__viewport,
.case-media-slider.case-media--natural .case-media-slider__viewport {
width: auto;
max-width: 100%;
margin-inline: auto;
}
.case-media-slider .case-media-slider__slide img,
.case-media-slider.case-media--content .case-media-slider__slide img,
.case-media-slider.case-media--wide .case-media-slider__slide img,
.case-media-slider.case-media--natural .case-media-slider__slide img {
width: auto;
max-width: 100%;
max-height: none;
height: auto;
margin-inline: auto;
}
@media (prefers-reduced-motion: reduce) {
.case-media-slider__track {
transition: none;
}
}
/* Режимы анимации переключения кадров.
slide — сдвиг трека (по умолчанию); fade — кроссфейд активного слайда;
none — мгновенная смена без переходов. */
.case-media-slider--anim-fade .case-media-slider__track {
display: block;
transform: none !important;
}
.case-media-slider--anim-fade .case-media-slider__slide {
position: absolute;
inset: 0;
opacity: 0;
transition: opacity 0.45s ease;
pointer-events: none;
}
.case-media-slider--anim-fade .case-media-slider__slide.is-active {
position: relative;
opacity: 1;
pointer-events: auto;
}
.case-media-slider--anim-none .case-media-slider__track {
transition: none !important;
}
.case-media-slider--anim-none .case-media-slider__slide {
transition: none !important;
}
/* Переключатель режима анимации (для демо-примера) */
.case-media-slider__anim-switch {
display: flex;
justify-content: center;
gap: 0.4rem;
margin: 0.4rem auto 0.8rem;
padding: 0;
}
.case-media-slider__anim-switch button {
font: inherit;
font-size: 0.8rem;
padding: 0.25rem 0.7rem;
border: 1px solid var(--line);
border-radius: 999px;
background: transparent;
color: var(--text-muted);
cursor: pointer;
transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
.case-media-slider__anim-switch button:hover {
color: var(--accent);
border-color: var(--accent);
}
.case-media-slider__anim-switch button[aria-pressed="true"] {
background: var(--accent);
border-color: var(--accent);
color: #fff;
}