/* ==========================================================================
   Yugan Solutions — showcase styles for the two portfolio pages.

   Loaded only by /projects/ and /clients/, after tailwind.min.css and
   base.css, so every rule here wins over a utility of equal specificity.

   Everything the two pages need visually lives in this file rather than in
   Tailwind utilities, for one practical reason: the compiled stylesheet is
   generated by scanning the templates, so a page built out of long utility
   chains cannot be adjusted without a full rebuild. Hand-written component
   classes keep the markup readable and the design tweakable.

   Naming:  .pf-*  portfolio (projects page)
            .cl-*  clients page
            .sw-*  shared between the two
   ========================================================================== */


/* ==========================================================================
   1. Shared primitives
   ========================================================================== */

/* ── Eyebrow rule ──
   A short gradient hairline that runs out from a section tag. Cheap, but it
   is what stops a centred heading block from floating in the middle of a
   dark page with nothing anchoring it. */
.sw-rule {
    display: block;
    height: 1px;
    width: 100%;
    max-width: 220px;
    margin: 1.75rem auto 0;
    background: linear-gradient(90deg, transparent, rgba(168, 85, 247, 0.65), rgba(245, 158, 11, 0.45), transparent);
}

/* ── Hero stat strip ──
   Three or four figures in one row, divided by hairlines rather than boxed
   into cards: at hero size, boxes compete with the headline. */
.sw-stats {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1px;
    overflow: hidden;
    border: 1px solid rgba(124, 58, 237, 0.24);
    border-radius: 1rem;
    background: rgba(124, 58, 237, 0.16);
    box-shadow: 0 20px 50px rgba(3, 2, 14, 0.4);
}

.sw-stats--4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 640px) {
    .sw-stats--4 {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

.sw-stat {
    position: relative;
    padding: 1.15rem 0.75rem 1.25rem;
    text-align: center;
    background: linear-gradient(160deg, rgba(35, 30, 61, 0.82), rgba(13, 11, 26, 0.86));
    transition: background 0.4s ease;
}

.sw-stat:hover {
    background: linear-gradient(160deg, rgba(56, 39, 105, 0.86), rgba(13, 11, 26, 0.86));
}

.sw-stat__value {
    font-family: 'Plus Jakarta Sans', system-ui, sans-serif;
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1.1;
    background: linear-gradient(135deg, #C084FC, #A855F7 45%, #F59E0B);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

@media (min-width: 640px) {
    .sw-stat__value {
        font-size: 2rem;
    }
}

.sw-stat__label {
    margin-top: 0.3rem;
    font-size: 0.75rem;
    line-height: 1.35;
    color: #C2C9D4;
}

@media (min-width: 640px) {
    .sw-stat__label {
        font-size: 0.8125rem;
    }
}

/* ── Section heading block ── */
.sw-head {
    margin-inline: auto;
    max-width: 44rem;
    text-align: center;
}

.sw-head__title {
    margin-top: 1.5rem;
    font-size: clamp(1.75rem, 1.2rem + 2.2vw, 2.75rem);
    font-weight: 700;
    line-height: 1.12;
    color: #FFFFFF;
}

.sw-head__sub {
    margin-top: 1rem;
    font-size: 1rem;
    line-height: 1.75;
    color: #C2C9D4;
}

/* ── Empty / no-results panel ── */
.sw-empty {
    border-radius: 1rem;
    border: 1px dashed rgba(168, 85, 247, 0.3);
    background: rgba(124, 58, 237, 0.06);
    padding: 4rem 1.5rem;
    text-align: center;
}

.sw-empty__icon {
    display: inline-flex;
    height: 4rem;
    width: 4rem;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    border: 1px solid rgba(168, 85, 247, 0.28);
    background: rgba(124, 58, 237, 0.14);
    color: #A855F7;
    font-size: 1.5rem;
}

.sw-empty__title {
    margin-top: 1.25rem;
    font-size: 1.125rem;
    font-weight: 700;
    color: #FFFFFF;
}

.sw-empty__text {
    margin: 0.5rem auto 0;
    max-width: 26rem;
    font-size: 0.875rem;
    line-height: 1.7;
    color: #C2C9D4;
}


/* ==========================================================================
   2. Projects — sticky filter toolbar
   ========================================================================== */

/* Sits directly under the fixed header (h-16 / lg:h-20) so the filters stay
   reachable however far down the grid the reader is. The wrapper carries the
   sticky offset; the bar itself carries the frosted panel, which keeps the
   blur from being clipped by the sticky containing block. */
.pf-toolbar {
    position: sticky;
    top: calc(4rem + 0.5rem);
    z-index: 30;
    padding-block: 0.5rem;
}

@media (min-width: 1024px) {
    .pf-toolbar {
        top: calc(5rem + 0.625rem);
    }
}

.pf-toolbar__inner {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    border: 1px solid rgba(124, 58, 237, 0.28);
    border-radius: 1rem;
    background: rgba(11, 9, 23, 0.86);
    box-shadow: 0 18px 44px rgba(3, 2, 14, 0.5);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    padding: 0.75rem;
}

@media (min-width: 1024px) {
    .pf-toolbar__inner {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        gap: 1.25rem;
        padding: 0.75rem 1.25rem;
    }
}

/* Horizontal scroller on narrow screens. The mask fades the pills out at
   both edges instead of letting them collide with the panel border, which
   is also the cue that there is more to scroll to. */
.pf-filters {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    overflow-x: auto;
    scrollbar-width: none;
    -ms-overflow-style: none;
    padding: 2px;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 16px, #000 calc(100% - 16px), transparent);
    mask-image: linear-gradient(90deg, transparent, #000 16px, #000 calc(100% - 16px), transparent);
}

.pf-filters::-webkit-scrollbar {
    display: none;
}

@media (min-width: 1024px) {
    .pf-filters {
        flex-wrap: wrap;
        overflow: visible;
        -webkit-mask-image: none;
        mask-image: none;
    }
}

.pf-pill {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 0.5rem;
    white-space: nowrap;
    border-radius: 999px;
    border: 1px solid rgba(124, 58, 237, 0.3);
    background: rgba(124, 58, 237, 0.08);
    padding: 0.5rem 0.95rem;
    font-size: 0.8125rem;
    font-weight: 600;
    color: #C2C9D4;
    transition: color 0.28s ease, background 0.28s ease, border-color 0.28s ease,
                transform 0.28s ease, box-shadow 0.28s ease;
}

.pf-pill:hover {
    color: #FFFFFF;
    border-color: rgba(168, 85, 247, 0.6);
    background: rgba(168, 85, 247, 0.16);
    transform: translateY(-1px);
}

.pf-pill:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.4);
}

.pf-pill__count {
    font-family: 'Space Mono', monospace;
    font-size: 11px;
    line-height: 1;
    padding: 3px 7px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    color: #C084FC;
}

.pf-pill.is-active {
    color: #FFFFFF;
    border-color: transparent;
    background: linear-gradient(135deg, #7C3AED, #A855F7);
    box-shadow: 0 10px 28px rgba(124, 58, 237, 0.45);
}

.pf-pill.is-active .pf-pill__count {
    background: rgba(7, 5, 15, 0.32);
    color: #FFFFFF;
}

.pf-toolbar__meta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.55rem;
    flex: 0 0 auto;
    font-family: 'Space Mono', monospace;
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: #A9B1BF;
}

.pf-toolbar__dot {
    display: inline-flex;
    height: 6px;
    width: 6px;
    border-radius: 999px;
    background: #34D399;
    box-shadow: 0 0 0 3px rgba(52, 211, 153, 0.16);
}


/* ==========================================================================
   3. Projects — spotlight case study
   ========================================================================== */

.pf-spot {
    position: relative;
    display: grid;
    overflow: hidden;
    border-radius: 1.25rem;
    border: 1px solid rgba(168, 85, 247, 0.26);
    background: linear-gradient(155deg, rgba(38, 32, 68, 0.9), rgba(13, 11, 26, 0.94));
    box-shadow: 0 34px 90px rgba(3, 2, 14, 0.55);
    transition: border-color 0.4s ease, box-shadow 0.5s ease, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}

@media (min-width: 1024px) {
    .pf-spot {
        grid-template-columns: 1.08fr 0.92fr;
    }

    .pf-spot:hover {
        transform: translateY(-6px);
        border-color: rgba(168, 85, 247, 0.5);
        box-shadow: 0 44px 110px rgba(88, 28, 196, 0.34);
    }
}

.pf-spot:focus-within {
    border-color: rgba(168, 85, 247, 0.6);
}

.pf-spot__media {
    position: relative;
    overflow: hidden;
    aspect-ratio: 16 / 10;
    background: linear-gradient(150deg, rgba(76, 29, 149, 0.6), rgba(13, 11, 26, 0.95));
}

@media (min-width: 1024px) {
    .pf-spot__media {
        aspect-ratio: auto;
        min-height: 26rem;
    }
}

.pf-spot__img {
    height: 100%;
    width: 100%;
    object-fit: cover;
    object-position: top center;
    transition: transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

.pf-spot:hover .pf-spot__img {
    transform: scale(1.045);
}

/* Vertical seam on desktop, bottom fade on mobile — in both cases the image
   has to hand off to the copy without a hard edge. */
.pf-spot__veil {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(to top, rgba(13, 11, 26, 0.92), rgba(13, 11, 26, 0.1) 55%, transparent);
}

@media (min-width: 1024px) {
    .pf-spot__veil {
        background: linear-gradient(to right, transparent 55%, rgba(13, 11, 26, 0.85));
    }
}

.pf-spot__body {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 1.75rem 1.5rem 2rem;
}

@media (min-width: 640px) {
    .pf-spot__body {
        padding: 2.25rem 2rem 2.5rem;
    }
}

@media (min-width: 1024px) {
    .pf-spot__body {
        padding: 3rem 2.75rem;
    }
}

.pf-spot__title {
    margin-top: 1.1rem;
    font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);
    font-weight: 700;
    line-height: 1.15;
    color: #FFFFFF;
}

.pf-spot__desc {
    margin-top: 0.9rem;
    font-size: 0.9375rem;
    line-height: 1.8;
    color: #C2C9D4;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Corner marker — the small mono ordinal that tells you this block is the
   lead item rather than just a bigger card. */
.pf-spot__mark {
    position: absolute;
    top: 1.25rem;
    right: 1.5rem;
    font-family: 'Space Mono', monospace;
    font-size: 11px;
    letter-spacing: 0.22em;
    color: rgba(192, 132, 252, 0.55);
}


/* ==========================================================================
   4. Projects — card grid
   ========================================================================== */

.pf-grid {
    display: grid;
    gap: 1.25rem;
    grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 640px) {
    .pf-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 1.5rem;
    }
}

@media (min-width: 1024px) {
    .pf-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

/* One or two results should not sit as a lonely card in a three-up grid. */
.pf-grid--few {
    margin-inline: auto;
    max-width: 58rem;
}

@media (min-width: 1024px) {
    .pf-grid--few {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

.pf-card {
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    isolation: isolate;
    border-radius: 1rem;
    border: 1px solid rgba(124, 58, 237, 0.22);
    background: linear-gradient(160deg, rgba(35, 30, 61, 0.72), rgba(13, 11, 26, 0.88));
    box-shadow: 0 18px 44px rgba(3, 2, 14, 0.42);
    transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1),
                border-color 0.35s ease, box-shadow 0.45s ease;
}

.pf-card:hover {
    transform: translateY(-8px);
    border-color: rgba(168, 85, 247, 0.5);
    box-shadow: 0 34px 74px rgba(88, 28, 196, 0.34);
}

.pf-card:focus-visible {
    outline: none;
    border-color: rgba(168, 85, 247, 0.7);
    box-shadow: 0 0 0 3px rgba(168, 85, 247, 0.45), 0 34px 74px rgba(88, 28, 196, 0.3);
}

/* Gradient hairline ring, revealed on hover. Drawn as a masked border so it
   follows the radius exactly instead of approximating it with a shadow. */
.pf-card::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 4;
    border-radius: inherit;
    padding: 1px;
    background: linear-gradient(135deg, rgba(168, 85, 247, 0.85), rgba(245, 158, 11, 0.4) 58%, transparent);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    opacity: 0;
    transition: opacity 0.4s ease;
    pointer-events: none;
}

.pf-card:hover::after,
.pf-card:focus-visible::after {
    opacity: 1;
}

/* Pointer-following glow. site-effects.js already writes --pointer-x/y on
   anything carrying [data-tilt], so this costs no extra JavaScript. It sits at
   z-index 0 — above the card's own background, below the media and the body —
   which is why it reads as light inside the glass rather than a wash over the
   screenshot. */
.pf-card::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    opacity: 0;
    pointer-events: none;
    background: radial-gradient(340px circle at var(--pointer-x, 50%) var(--pointer-y, 50%),
                rgba(168, 85, 247, 0.18), transparent 46%);
    transition: opacity 0.35s ease;
}

.pf-card:hover::before {
    opacity: 1;
}

.pf-card__media {
    position: relative;
    z-index: 1;
    overflow: hidden;
    aspect-ratio: 16 / 10;
    background: linear-gradient(150deg, rgba(76, 29, 149, 0.55), rgba(13, 11, 26, 0.92));
}

.pf-card__img {
    height: 100%;
    width: 100%;
    object-fit: cover;
    object-position: top center;
    transition: transform 0.85s cubic-bezier(0.22, 1, 0.36, 1), filter 0.6s ease;
    filter: saturate(0.92);
}

.pf-card:hover .pf-card__img {
    transform: scale(1.07);
    filter: saturate(1.05);
}

.pf-card__fallback {
    display: flex;
    height: 100%;
    width: 100%;
    align-items: center;
    justify-content: center;
    color: rgba(168, 85, 247, 0.42);
    font-size: 3rem;
}

.pf-card__scrim {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(to top, rgba(13, 11, 26, 0.96) 2%, rgba(13, 11, 26, 0.24) 48%, transparent 78%);
}

/* One-shot light sweep on hover. Purely decorative, and it sits behind the
   ring but above the image so it reads as light on glass. */
.pf-card__sheen {
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
    opacity: 0;
    background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, 0.1) 48%, transparent 58%);
    transform: translateX(-65%);
}

.pf-card:hover .pf-card__sheen {
    opacity: 1;
    animation: pfSheen 1.05s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes pfSheen {
    from { transform: translateX(-65%); }
    to   { transform: translateX(65%); }
}

.pf-badges {
    position: absolute;
    inset: 0.85rem 0.85rem auto;
    z-index: 2;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.5rem;
}

.pf-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: 999px;
    padding: 5px 11px;
    font-family: 'Space Mono', monospace;
    font-size: 11px;
    line-height: 1.2;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}

/* Category names are free text out of the database and can be long. Capping
   the width stops one from meeting the Featured badge coming the other way on
   a narrow phone. */
.pf-chip--cat {
    max-width: 62%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    border: 1px solid rgba(168, 85, 247, 0.42);
    background: rgba(13, 11, 26, 0.68);
    color: #DDD3FF;
}

.pf-chip--featured {
    border: 1px solid rgba(245, 158, 11, 0.45);
    background: rgba(245, 158, 11, 0.16);
    color: #FBBF24;
}

.pf-card__body {
    position: relative;
    z-index: 2;
    display: flex;
    flex: 1;
    flex-direction: column;
    padding: 1.35rem 1.4rem 1.45rem;
}

.pf-card__client {
    font-family: 'Space Mono', monospace;
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #C084FC;
    margin-bottom: 0.4rem;
}

.pf-card__title {
    font-size: 1.125rem;
    font-weight: 700;
    line-height: 1.3;
    color: #FFFFFF;
    transition: color 0.3s ease;
}

.pf-card:hover .pf-card__title {
    color: #EADCFF;
}

.pf-card__desc {
    margin-top: 0.6rem;
    font-size: 0.875rem;
    line-height: 1.7;
    color: #C2C9D4;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.pf-tech {
    margin-top: 1rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.pf-tech > span {
    border-radius: 999px;
    border: 1px solid rgba(124, 58, 237, 0.32);
    background: rgba(124, 58, 237, 0.14);
    padding: 3px 10px;
    font-family: 'Space Mono', monospace;
    font-size: 11px;
    line-height: 1.4;
    color: #CBD2DE;
}

.pf-tech > span.pf-tech__more {
    border-style: dashed;
    color: #A9B1BF;
}

.pf-card__foot {
    margin-top: auto;
    padding-top: 1.15rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    border-top: 1px solid rgba(124, 58, 237, 0.2);
    margin-inline: -0.15rem;
    padding-inline: 0.15rem;
}

.pf-cta {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-family: 'Space Mono', monospace;
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #C084FC;
    transition: color 0.3s ease;
}

.pf-card:hover .pf-cta {
    color: #F3E8FF;
}

.pf-arrow {
    display: inline-flex;
    height: 2.15rem;
    width: 2.15rem;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    border: 1px solid rgba(168, 85, 247, 0.35);
    background: rgba(124, 58, 237, 0.16);
    color: #C4B5FD;
    font-size: 0.7rem;
    transition: background 0.35s ease, color 0.35s ease, border-color 0.35s ease, transform 0.35s ease;
}

.pf-card:hover .pf-arrow {
    border-color: transparent;
    background: linear-gradient(135deg, #7C3AED, #A855F7);
    color: #FFFFFF;
    transform: translate(3px, -3px);
}


/* ==========================================================================
   5. Clients — name ribbon

   A slow marquee of client names rather than of their logos. The logos are
   overwhelmingly dark marks on transparent backgrounds, which need a light
   plate to read at all (see the wall below) — and a moving row of white
   plates directly above a grid of white plates is the same picture twice.
   Set as mono capitals the ribbon reads as a different object entirely, and
   carries the motion the wall deliberately does not have.
   ========================================================================== */

.cl-ribbon {
    position: relative;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}

.cl-ribbon__track {
    display: flex;
    width: max-content;
    align-items: center;
    animation: clMarquee 46s linear infinite;
    will-change: transform;
}

.cl-ribbon:hover .cl-ribbon__track {
    animation-play-state: paused;
}

@keyframes clMarquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

.cl-ribbon__item {
    display: flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 1.75rem;
    padding-right: 1.75rem;
}

.cl-ribbon__name {
    font-family: 'Space Mono', monospace;
    font-size: 13px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    white-space: nowrap;
    color: #9A93B4;
}

.cl-ribbon__sep {
    font-size: 7px;
    color: rgba(245, 158, 11, 0.75);
}

@media (prefers-reduced-motion: reduce) {
    .cl-ribbon__track {
        animation: none;
    }
}


/* ==========================================================================
   6. Clients — logo wall
   ========================================================================== */

.cl-wall {
    display: grid;
    gap: 1rem;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 640px) {
    .cl-wall {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 1.25rem;
    }
}

@media (min-width: 1024px) {
    .cl-wall {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

.cl-tile {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1.1rem;
    overflow: hidden;
    isolation: isolate;
    min-height: 13.5rem;
    border-radius: 1rem;
    border: 1px solid rgba(124, 58, 237, 0.22);
    background: linear-gradient(160deg, rgba(35, 30, 61, 0.62), rgba(13, 11, 26, 0.85));
    padding: 2.4rem 1.15rem 1.6rem;
    text-align: center;
    transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1),
                border-color 0.35s ease, box-shadow 0.45s ease;
}

.cl-tile:hover {
    transform: translateY(-7px);
    border-color: rgba(168, 85, 247, 0.55);
    box-shadow: 0 28px 62px rgba(88, 28, 196, 0.32);
}

.cl-tile:focus-within {
    border-color: rgba(168, 85, 247, 0.6);
}

/* Soft bloom that fades up from the bottom of the tile on hover. Kept behind
   the logo with z-index so it lifts the tile without washing the mark out. */
.cl-tile::before {
    content: '';
    position: absolute;
    inset: auto -20% -60% -20%;
    z-index: -1;
    height: 12rem;
    border-radius: 999px;
    background: radial-gradient(ellipse at center, rgba(168, 85, 247, 0.35), transparent 68%);
    opacity: 0;
    transition: opacity 0.45s ease;
    pointer-events: none;
}

.cl-tile:hover::before {
    opacity: 1;
}

/* ── The light plate ──
   Client logos arrive as whatever the client had: dark wordmarks on
   transparent PNGs, white-background JPEGs, one reversed white mark. Dropped
   straight onto a near-black tile, most of them are unreadable and the two
   with baked-in white backgrounds read as floating white rectangles.

   One near-white plate behind every mark fixes both at once: dark logos get
   the light ground they were drawn for, and the white-background files stop
   looking like a mistake because every tile now has the same plate. It is
   also what makes the wall look deliberate rather than like a folder of
   mixed-up downloads. */
.cl-tile__plate {
    position: relative;
    display: flex;
    height: 5.25rem;
    width: 100%;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    border-radius: 0.875rem;
    padding: 0.85rem 1rem;
    background: linear-gradient(180deg, #FFFFFF, #EFEAFB);
    box-shadow: inset 0 0 0 1px rgba(124, 58, 237, 0.18), 0 10px 24px rgba(3, 2, 14, 0.45);
    transition: transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.45s ease;
}

.cl-tile:hover .cl-tile__plate {
    transform: translateY(-4px) scale(1.03);
    box-shadow: inset 0 0 0 1px rgba(168, 85, 247, 0.5), 0 20px 40px rgba(88, 28, 196, 0.45);
}

/* One-shot light sweep across the plate on hover. This is the reveal now that
   the marks are in colour at rest — nothing to desaturate and restore, so the
   plate itself does the reacting. */
.cl-tile__shine {
    position: absolute;
    inset: -40% -10%;
    pointer-events: none;
    opacity: 0;
    background: linear-gradient(112deg, transparent 40%, rgba(168, 85, 247, 0.28) 49%,
                rgba(255, 255, 255, 0.7) 52%, rgba(245, 158, 11, 0.22) 55%, transparent 64%);
    transform: translateX(-70%);
}

.cl-tile:hover .cl-tile__shine {
    opacity: 1;
    animation: clShine 0.85s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes clShine {
    from { transform: translateX(-70%); }
    to   { transform: translateX(70%); }
}

.cl-tile__logo {
    position: relative;
    z-index: 1;
    max-height: 100%;
    max-width: 100%;
    height: auto;
    width: auto;
    object-fit: contain;
    /* Full colour at rest — these are the clients' marks, and a wall of grey
       ghosts sells none of them. The hairline shadow is for the ones drawn in
       a pale tint: it gives their strokes an edge against the plate, and is
       invisible on the dark ones. */
    filter: drop-shadow(0 0 1px rgba(20, 14, 45, 0.5));
    transition: transform 0.55s cubic-bezier(0.34, 1.56, 0.64, 1), filter 0.45s ease;
}

.cl-tile:hover .cl-tile__logo {
    /* Slight overshoot from the spring easing above, so the mark settles
       rather than just growing. */
    transform: scale(1.07);
    filter: drop-shadow(0 3px 8px rgba(88, 28, 196, 0.28));
}

/* A mark drawn in white for a dark background is invisible on the plate at any
   opacity — this is legibility, not styling, so it stays whatever the rest of
   the wall does. logo-plate.js measures each file and tags those, and the tone
   is flipped so the shape survives. */
.cl-tile__logo.is-light-mark {
    filter: invert(1);
}

.cl-tile:hover .cl-tile__logo.is-light-mark {
    filter: invert(1) drop-shadow(0 3px 8px rgba(88, 28, 196, 0.28));
}

/* The name picks up a gradient underline that draws in from the left, so the
   whole tile responds rather than just the plate. */
.cl-tile__name {
    position: relative;
    display: inline-block;
    padding-bottom: 0.3rem;
}

.cl-tile__name::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    height: 2px;
    width: 0;
    border-radius: 2px;
    background: linear-gradient(90deg, #A855F7, #F59E0B);
    transition: width 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}

.cl-tile:hover .cl-tile__name::after {
    width: 100%;
}

/* Stand-in when a client row has no logo file. Lives inside the same plate,
   so a missing image never breaks the rhythm of the wall. */
.cl-tile__mark {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    color: #7C3AED;
    font-size: 1.5rem;
    opacity: 0.55;
}

.cl-tile__name {
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.4;
    color: #FFFFFF;
}

.cl-tile__link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-family: 'Space Mono', monospace;
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #C084FC;
    transition: color 0.3s ease;
}

.cl-tile__link:hover {
    color: #F3E8FF;
}

.cl-tile__index {
    position: absolute;
    top: 0.75rem;
    left: 0.9rem;
    font-family: 'Space Mono', monospace;
    font-size: 11px;
    letter-spacing: 0.14em;
    color: rgba(192, 132, 252, 0.4);
    transition: color 0.35s ease;
}

.cl-tile:hover .cl-tile__index {
    color: rgba(245, 158, 11, 0.75);
}


/* ==========================================================================
   7. Clients — promise band
   ========================================================================== */

.cl-promises {
    display: grid;
    gap: 1rem;
    grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 640px) {
    .cl-promises {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 1.25rem;
    }
}

@media (min-width: 1024px) {
    .cl-promises {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

.cl-promise {
    position: relative;
    overflow: hidden;
    border-radius: 1rem;
    border: 1px solid rgba(124, 58, 237, 0.22);
    background: linear-gradient(160deg, rgba(35, 30, 61, 0.6), rgba(13, 11, 26, 0.84));
    padding: 1.6rem 1.4rem 1.7rem;
    transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1), border-color 0.35s ease, box-shadow 0.4s ease;
}

.cl-promise:hover {
    transform: translateY(-6px);
    border-color: rgba(168, 85, 247, 0.5);
    box-shadow: 0 26px 58px rgba(88, 28, 196, 0.28);
}

/* Gradient tick that grows along the top edge on hover — the cheapest
   possible way to make a row of four cards feel individually responsive. */
.cl-promise::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    height: 2px;
    width: 0;
    background: linear-gradient(90deg, #7C3AED, #A855F7, #F59E0B);
    transition: width 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}

.cl-promise:hover::before {
    width: 100%;
}

.cl-promise__icon {
    display: inline-flex;
    height: 2.75rem;
    width: 2.75rem;
    align-items: center;
    justify-content: center;
    border-radius: 0.875rem;
    border: 1px solid rgba(168, 85, 247, 0.32);
    background: rgba(124, 58, 237, 0.18);
    color: #C4B5FD;
    font-size: 1rem;
    transition: color 0.35s ease, background 0.35s ease;
}

.cl-promise:hover .cl-promise__icon {
    color: #FBBF24;
    background: rgba(124, 58, 237, 0.3);
}

.cl-promise__title {
    margin-top: 1.1rem;
    font-size: 1rem;
    font-weight: 700;
    color: #FFFFFF;
}

.cl-promise__text {
    margin-top: 0.5rem;
    font-size: 0.875rem;
    line-height: 1.7;
    color: #C2C9D4;
}


/* ==========================================================================
   8. Clients — testimonials
   ========================================================================== */

.cl-quotes {
    display: grid;
    gap: 1.25rem;
    grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 768px) {
    .cl-quotes {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (min-width: 1024px) {
    .cl-quotes {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

.cl-quote {
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: 1rem;
    border: 1px solid rgba(124, 58, 237, 0.22);
    background: linear-gradient(160deg, rgba(35, 30, 61, 0.7), rgba(13, 11, 26, 0.9));
    padding: 1.65rem 1.5rem 1.5rem;
    transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1), border-color 0.35s ease, box-shadow 0.42s ease;
}

.cl-quote:hover {
    transform: translateY(-6px);
    border-color: rgba(168, 85, 247, 0.5);
    box-shadow: 0 28px 62px rgba(88, 28, 196, 0.3);
}

/* Oversized quote glyph bled off the corner — reads as texture, not as a
   piece of punctuation competing with the testimonial itself. */
.cl-quote__glyph {
    position: absolute;
    top: -1.75rem;
    right: 0.5rem;
    font-family: 'Roboto', Georgia, serif;
    font-size: 7rem;
    line-height: 1;
    color: rgba(168, 85, 247, 0.12);
    pointer-events: none;
    user-select: none;
}

.cl-quote__stars {
    display: flex;
    gap: 0.25rem;
    font-size: 0.75rem;
    color: #F59E0B;
}

.cl-quote__stars .is-off {
    color: #6B7488;
}

.cl-quote__text {
    position: relative;
    margin-top: 1.1rem;
    font-size: 0.9375rem;
    line-height: 1.8;
    color: #D1D5DB;
}

.cl-quote__foot {
    margin-top: 1.5rem;
    padding-top: 1.15rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    border-top: 1px solid rgba(124, 58, 237, 0.22);
}

.cl-quote__avatar {
    display: flex;
    height: 2.75rem;
    width: 2.75rem;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: linear-gradient(135deg, #7C3AED, #A855F7);
    font-size: 0.9375rem;
    font-weight: 700;
    color: #FFFFFF;
}

.cl-quote__name {
    font-size: 0.875rem;
    font-weight: 600;
    color: #FFFFFF;
}

.cl-quote__role {
    margin-top: 0.1rem;
    font-size: 0.8125rem;
    color: #C2C9D4;
}


/* ==========================================================================
   9. Motion and touch fallbacks
   ========================================================================== */

/* Hover lift is a pointer affordance. On touch it fires on tap and leaves the
   card stuck in its hovered state until the next tap somewhere else. */
@media (hover: none), (pointer: coarse) {
    .pf-card:hover,
    .pf-spot:hover,
    .cl-tile:hover,
    .cl-promise:hover,
    .cl-quote:hover {
        transform: none;
        box-shadow: 0 18px 44px rgba(3, 2, 14, 0.42);
    }

    .pf-card:hover .pf-card__img,
    .pf-spot:hover .pf-spot__img,
    .cl-tile:hover .cl-tile__logo,
    .cl-tile:hover .cl-tile__plate {
        transform: none;
    }

    .pf-card:hover .pf-card__sheen,
    .cl-tile:hover .cl-tile__shine {
        animation: none;
        opacity: 0;
    }

    .cl-tile:hover .cl-tile__name::after {
        width: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .pf-card,
    .pf-spot,
    .cl-tile,
    .cl-promise,
    .cl-quote,
    .pf-card__img,
    .pf-spot__img,
    .cl-tile__logo,
    .cl-tile__plate,
    .cl-tile__name::after {
        transition: none;
    }

    .pf-card:hover,
    .pf-spot:hover,
    .cl-tile:hover,
    .cl-promise:hover,
    .cl-quote:hover,
    .cl-tile:hover .cl-tile__plate,
    .cl-tile:hover .cl-tile__logo {
        transform: none;
    }

    .pf-card:hover .pf-card__sheen,
    .cl-tile:hover .cl-tile__shine {
        animation: none;
        opacity: 0;
    }
}
