fix(projects): add mobile edge spacing, 1-card layout, and smooth touch drag physics

This commit is contained in:
2026-09-06 13:37:45 +03:30
parent a1cab65d1e
commit c7ef6dff3e
2 changed files with 303 additions and 62 deletions

View File

@@ -75,6 +75,8 @@
overscroll-behavior-inline: contain;
touch-action: pan-y;
user-select: none;
container-type: inline-size;
container-name: carousel;
}
.carouselViewport::-webkit-scrollbar {
@@ -89,23 +91,28 @@
.dragging {
cursor: grabbing;
scroll-snap-type: none !important;
scroll-behavior: auto !important;
user-select: none;
}
.carouselTrack {
display: flex;
align-items: stretch;
width: max-content;
gap: 24px;
gap: 20px;
padding: 4px 0 8px;
}
.card {
display: flex;
flex: 0 0 var(--size-project-width);
flex: 0 0 clamp(300px, 24vw, 340px);
flex-shrink: 0;
flex-direction: column;
width: var(--size-project-width);
min-height: 480px;
width: clamp(300px, 24vw, 340px);
min-height: 460px;
overflow: hidden;
box-sizing: border-box;
border: 1px solid var(--border-default);
border-radius: var(--radius-lg);
background: var(--bg-surface);
@@ -116,13 +123,14 @@
.mediaContainer {
position: relative;
width: 100%;
height: var(--size-project-media-height);
aspect-ratio: 16 / 10;
overflow: hidden;
background: var(--color-blue-900);
}
.projectImage {
object-fit: cover;
object-position: center;
pointer-events: none;
transition: transform 0.3s ease;
}
@@ -131,7 +139,7 @@
display: flex;
flex: 1;
flex-direction: column;
padding: 24px;
padding: 18px 16px;
}
.cardTitleRow {
@@ -143,9 +151,9 @@
.cardTitle {
color: var(--text-primary);
font-size: var(--font-size-h3);
font-size: 18px;
font-weight: 700;
line-height: var(--line-height-h3);
line-height: 1.25;
}
.titleLinkIcon {
@@ -158,9 +166,9 @@
}
.cardDate {
margin-bottom: 14px;
margin-bottom: 10px;
color: var(--text-muted);
font-size: var(--font-size-label-small);
font-size: 11px;
font-weight: 700;
line-height: var(--line-height-label-small);
letter-spacing: var(--letter-spacing-eyebrow);
@@ -169,21 +177,24 @@
.cardDesc {
display: -webkit-box;
margin-bottom: 20px;
margin-bottom: 16px;
overflow: hidden;
color: var(--text-primary);
font-size: var(--font-size-body-small);
font-size: 13.5px;
font-weight: 400;
line-height: var(--line-height-body-small);
line-height: 1.55;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
-webkit-line-clamp: 3;
white-space: normal;
word-break: normal;
overflow-wrap: break-word;
}
.tagList {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 24px;
gap: 6px;
margin-bottom: 18px;
}
.tagBadge {
@@ -233,7 +244,9 @@
}
.scrollbar {
--thumb-width: 216px;
width: 480px;
max-width: 100%;
height: 20px;
margin: 0;
appearance: none;
@@ -248,7 +261,7 @@
}
.scrollbar::-webkit-slider-thumb {
width: 216px;
width: var(--thumb-width, 216px);
height: 6px;
margin-top: 0;
appearance: none;
@@ -265,7 +278,7 @@
}
.scrollbar::-moz-range-thumb {
width: 216px;
width: var(--thumb-width, 216px);
height: 6px;
border: 0;
border-radius: var(--radius-pill);
@@ -294,65 +307,192 @@
background: var(--color-blue-300);
}
@media (max-width: 1024px) {
/* ================================================================
LAPTOP 1101px – 1440px
Comfortable ~290px-330px cards (~3 to 4 visible)
================================================================ */
@media (max-width: 1440px) and (min-width: 1101px) {
.carouselTrack {
gap: 20px;
}
.card {
flex: 0 0 clamp(290px, 23vw, 330px);
width: clamp(290px, 23vw, 330px);
}
.scrollbar {
width: min(480px, 50vw);
--thumb-width: 120px;
}
}
/* ================================================================
TABLET 651px – 1100px
Comfortable ~310px-350px cards (~2 cards visible)
================================================================ */
@media (max-width: 1100px) and (min-width: 651px) {
.projectsSection {
padding-top: var(--space-8);
padding-bottom: var(--space-9);
}
.carouselTrack {
gap: var(--space-4);
}
.card {
flex-basis: min(340px, calc(100vw - (2 * var(--layout-page-gutter))));
width: min(340px, calc(100vw - (2 * var(--layout-page-gutter))));
}
}
@media (max-width: 640px) {
.headerRow {
align-items: stretch;
flex-direction: column;
gap: var(--space-3);
margin-bottom: var(--space-6);
}
.arrowButtons {
align-self: flex-end;
gap: var(--space-2);
}
.navButton {
width: 40px;
height: 40px;
align-items: flex-start;
justify-content: space-between;
margin-bottom: 32px;
}
.carouselViewport {
margin-inline: calc(-1 * var(--layout-page-gutter));
width: calc(100% + (2 * var(--layout-page-gutter)));
padding-inline: var(--layout-page-gutter);
scroll-padding-inline: var(--layout-page-gutter);
scroll-snap-type: x mandatory;
scroll-padding-inline: 0;
}
.carouselTrack {
gap: 20px;
}
.card {
flex-basis: min(320px, calc(100vw - 40px));
width: min(320px, calc(100vw - 40px));
min-height: 460px;
flex: 0 0 clamp(310px, 42vw, 350px);
width: clamp(310px, 42vw, 350px);
min-height: 450px;
box-sizing: border-box;
scroll-snap-align: start;
}
.mediaContainer {
height: 200px;
aspect-ratio: 16 / 10;
}
.cardBody {
padding: var(--space-5);
padding: 18px 16px;
}
.cardTitle {
font-size: 18px;
}
.cardDesc {
font-size: 13.5px;
line-height: 1.55;
margin-bottom: 14px;
-webkit-line-clamp: 3;
white-space: normal;
word-break: normal;
overflow-wrap: break-word;
}
.tagList {
gap: 6px;
margin-bottom: 16px;
}
.tagBadge {
padding: 3px 9px;
font-size: 11px;
}
.scrollbarWrapper {
display: flex;
justify-content: center;
margin-top: 32px;
}
.scrollbar {
width: min(360px, 60vw);
--thumb-width: 90px;
}
}
/* ================================================================
MOBILE ≤ 650px
Comfortable ~310px-330px card (~1 card visible with clean margins)
================================================================ */
@media (max-width: 650px) {
.projectsSection {
padding-top: 48px;
padding-bottom: 64px;
}
.headerRow {
margin-bottom: 24px;
}
.arrowButtons {
display: none;
}
.carouselViewport {
width: 100%;
margin-inline: 0;
padding-inline: 0;
scroll-padding-inline: 0;
scroll-snap-type: x mandatory;
-webkit-overflow-scrolling: touch;
}
.carouselTrack {
gap: 16px;
width: max-content;
}
.card {
flex: 0 0 calc(100vw - (2 * var(--layout-page-gutter)));
flex: 0 0 100cqw;
width: calc(100vw - (2 * var(--layout-page-gutter)));
width: 100cqw;
min-width: calc(100vw - (2 * var(--layout-page-gutter)));
min-width: 100cqw;
max-width: 100%;
min-height: 420px;
box-sizing: border-box;
scroll-snap-align: start;
scroll-snap-stop: always;
}
.mediaContainer {
aspect-ratio: 16 / 10;
}
.cardBody {
padding: 18px 16px;
}
.cardTitle {
font-size: 18px;
}
.cardDesc {
font-size: 13px;
line-height: 1.5;
margin-bottom: 14px;
white-space: normal;
word-break: normal;
overflow-wrap: break-word;
-webkit-line-clamp: 3;
}
.tagList {
gap: 6px;
margin-bottom: 16px;
}
.tagBadge {
padding: 3px 9px;
font-size: 11px;
}
.scrollbarWrapper {
display: flex;
justify-content: center;
margin-top: 24px;
}
.scrollbar {
width: min(200px, 60vw);
height: 16px;
--thumb-width: 60px;
}
}
@media (hover: hover) and (pointer: fine) {