/* ══════════════════════════════════════════════════════════════════
   Project card gallery — a swipeable, snap-scrolling carousel.

   Layout: .project-gallery is the flex item inside the card and stacks
   the image frame (.blog-list-thumb sizing: 16/9 on mobile, 300x169 at
   >=sm, 356x200 at >=md) with the dots strip underneath it.

   Mechanics: the track is a native horizontal scroller with CSS
   scroll-snap, so touch swipes and trackpad gestures work without
   JavaScript.  projects.js layers mouse dragging, arrows, dots and
   keyboard control on top of the same scroll position.
   ══════════════════════════════════════════════════════════════════ */

.project-gallery {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
    width: 100%;
}

/* Match the widths .blog-list-thumb used to hold on its own, so the card
   row keeps its proportions now that a wrapper sits in between. */
@media (min-width: 640px) {
    .project-gallery {
        width: 300px;
        min-width: 300px;
        flex-shrink: 0;
        /* The card row stretches its items by default, which would leave
           the wrapper as tall as the whole card — a hover area far bigger
           than the image itself. */
        align-self: flex-start;
    }
}

@media (min-width: 768px) {
    .project-gallery {
        width: 356px;
        min-width: 356px;
    }
}

.project-gallery__frame {
    position: relative;
    isolation: isolate;
    background: #0b1220;
}

/* ── Scroll track ─────────────────────────────────────────────────── */
.project-gallery__viewport {
    display: flex;
    width: 100%;
    height: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    /* Keep horizontal rubber-banding from scrolling the page behind it */
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    -ms-overflow-style: none;
    cursor: grab;
    outline: none;
}

.project-gallery__viewport::-webkit-scrollbar {
    display: none;
}

.project-gallery__viewport:focus-visible {
    box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.55);
}

/* While a mouse drag is in progress the snap points would fight the
   scrollLeft updates, so they are switched off for the duration. */
.project-gallery__viewport.is-dragging {
    cursor: grabbing;
    scroll-snap-type: none;
    scroll-behavior: auto;
    -webkit-user-select: none;
    user-select: none;
}

.project-gallery__slide {
    position: relative;
    flex: 0 0 100%;
    width: 100%;
    height: 100%;
    margin: 0;
    scroll-snap-align: center;
    scroll-snap-stop: always;
}

.project-gallery__img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    -webkit-user-drag: none;
    -webkit-user-select: none;
    user-select: none;
}

/* A real button makes opening a project screenshot reliable for mouse,
   touch and keyboard users without changing the gallery's visual layout. */
.project-image-preview-trigger {
    display: block;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 0;
    border-radius: inherit;
    background: transparent;
    line-height: 0;
}

.project-image-preview-trigger:focus-visible {
    outline: 2px solid var(--accent-200);
    outline-offset: -3px;
}

/* ── Caption ──────────────────────────────────────────────────────── */
.project-gallery__caption {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    padding: 1.4rem 0.7rem 0.55rem;
    font-size: 0.72rem;
    line-height: 1.3;
    color: var(--text);
    text-align: center;
    background: linear-gradient(to top, rgba(3, 7, 18, 0.88), rgba(3, 7, 18, 0));
    pointer-events: none;
    z-index: 2;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

/* ── Arrows ───────────────────────────────────────────────────────────
   Same white glass as the site's back-to-top button, over a thin gray-900
   base.  The base is what keeps the button readable on light screenshots
   — the white gradient alone disappears on a white image — while staying
   light enough to still read as glass rather than a dark blob. */
.project-gallery__arrow {
    position: absolute;
    top: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.85rem;
    height: 1.85rem;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 9999px;
    color: #ffffff;
    background-color: rgba(17, 24, 39, 0.55);
    background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.03) 100%);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.1);
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transform: translateY(-50%);
    transition: opacity 0.2s ease, background-color 0.2s ease, background-image 0.2s ease,
        border-color 0.2s ease;
    z-index: 3;
}

.project-gallery__arrow svg {
    width: 0.95rem;
    height: 0.95rem;
    /* Keeps the chevron itself crisp now that the pane is light */
    filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.45));
}

.project-gallery__arrow--prev {
    left: 0.45rem;
}

.project-gallery__arrow--next {
    right: 0.45rem;
}

/* Hover is bound to the image frame only — the wrapper also covers the
   dots strip below it (and stretches to the full card height), which
   made the arrows appear well before the cursor reached the image.
   Keyboard users get them via :focus-visible; a plain mouse click no
   longer latches them on. */
@media (hover: hover) and (pointer: fine) {
    .project-gallery__frame:hover .project-gallery__arrow,
    .project-gallery__viewport:focus-visible ~ .project-gallery__arrow {
        opacity: 1;
        pointer-events: auto;
    }

    /* Mirrors #back-to-top:hover — one step brighter, nothing else */
    .project-gallery__arrow:hover {
        background-color: rgba(17, 24, 39, 0.6);
        background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.05) 100%);
        border-color: rgba(255, 255, 255, 0.18);
        box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.15);
    }
}

.project-gallery__arrow:active {
    background-color: rgba(17, 24, 39, 0.66);
}

.project-gallery__arrow:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.7);
    outline-offset: 2px;
    opacity: 1;
    pointer-events: auto;
}

/* At the first / last slide the corresponding arrow is taken out */
.project-gallery__arrow[disabled] {
    opacity: 0 !important;
    pointer-events: none !important;
}

/* ── Dots ─────────────────────────────────────────────────────────────
   Sit below the image on the card surface, so no dark backdrop pane is
   needed and nothing covers the screenshot. */
.project-gallery__dots {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.1rem;
    min-height: 1.05rem;
}

.project-gallery__dot {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    /* Deliberately larger than the visible pill: gives touch users a
       real hit target without making the indicator heavy. */
    width: 1.05rem;
    height: 1.05rem;
    padding: 0;
    border: 0;
    border-radius: 9999px;
    background: transparent;
    cursor: pointer;
    transition: width 0.24s var(--ease-standard);
}

.project-gallery__dot-fill {
    display: block;
    width: 0.34rem;
    height: 0.34rem;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.26);
    transition: width 0.24s var(--ease-standard), background 0.24s ease;
}

.project-gallery__dot:hover .project-gallery__dot-fill {
    background: rgba(255, 255, 255, 0.5);
}

.project-gallery__dot:focus-visible {
    outline: 2px solid rgba(255, 255, 255, 0.6);
    outline-offset: 1px;
}

/* Active slide: the dot stretches into a white pill */
.project-gallery__dot.is-active {
    width: 1.5rem;
}

.project-gallery__dot.is-active .project-gallery__dot-fill {
    width: 0.95rem;
    background: rgba(255, 255, 255, 0.85);
}

/* Seven or more slides: shrink everything a notch so the strip still
   fits under the 300px-wide frame on small screens. */
.project-gallery__dots--compact .project-gallery__dot {
    width: 0.8rem;
    height: 0.9rem;
}

.project-gallery__dots--compact .project-gallery__dot-fill {
    width: 0.28rem;
    height: 0.28rem;
}

.project-gallery__dots--compact .project-gallery__dot.is-active {
    width: 1.15rem;
}

.project-gallery__dots--compact .project-gallery__dot.is-active .project-gallery__dot-fill {
    width: 0.7rem;
}

/* ── Larger cards get slightly larger controls ────────────────────── */
@media (min-width: 768px) {
    .project-gallery__arrow {
        width: 2rem;
        height: 2rem;
    }

    .project-gallery__arrow svg {
        width: 1.05rem;
        height: 1.05rem;
    }

    .project-gallery__caption {
        font-size: 0.76rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .project-gallery__viewport {
        scroll-behavior: auto;
    }

    .project-gallery__arrow,
    .project-gallery__dot,
    .project-gallery__dot-fill {
        transition: none;
    }
}
