/* ========================================
   CG Experts — Interactive 360° Configurator
   Self-contained styles. Loaded after styles.min.css
   so any token already defined there can be reused.
   ======================================== */

/* The whole configurator (mac-frame viewer + caption + price) reads as
   ONE big featured product card sitting above the 3 service cards.
   Outer chrome lives on .cfg-stage; the mac-frame strips its own border
   and radius so it flushes flat to the card's edges. */
.cfg-stage {
    max-width: 1100px;
    margin: 56px auto 0;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 20px;
    overflow: hidden;
    box-shadow: 0 14px 40px rgba(0, 0, 0, 0.06), 0 2px 6px rgba(0, 0, 0, 0.04);
}
.cfg-stage .mac-frame {
    border-radius: 0;
    border: 0;
    box-shadow: none;
}

/* Footer row: caption left, price right — the bit that ties the demo to
   the price tag visually. Same chrome as a service card's content area. */
.cfg-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 28px;
    padding: 22px 28px;
    border-top: 1px solid var(--border-color);
}
.cfg-footer .cfg-caption {
    margin: 0;
    flex: 1;
    text-align: left;
    max-width: none;
    font-size: 13px;
    color: var(--text-secondary);
}
.cfg-footer .cfg-caption strong {
    color: var(--text-primary);
    font-weight: 600;
}
.cfg-footer .cfg-price {
    margin: 0;
    flex-shrink: 0;
    align-self: center;
}
@media (max-width: 700px) {
    .cfg-footer {
        flex-direction: column;
        align-items: stretch;
        gap: 14px;
        padding: 18px 18px 20px;
    }
    .cfg-footer .cfg-caption {
        text-align: center;
        font-size: 12.5px;
    }
    .cfg-footer .cfg-price {
        align-self: center;
    }
}

/* ---------- Intro copy above the viewer ---------- */
.cfg-intro {
    text-align: center;
    max-width: 640px;
    margin: 0 auto 28px;
}

/* When the intro lives BELOW the configurator (swatches above it),
   flip the margin to give breathing room from the swatches instead. */
.cfg-intro--below {
    margin: 32px auto 0;
}

/* Tight single-line caption that sits below the configurator —
   no competing heading, no big block. Reads as commentary on what
   the user just played with, not a sub-section header. */
.cfg-caption {
    max-width: 560px;
    margin: 24px auto 0;
    text-align: center;
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-muted);
}
.cfg-caption strong {
    color: var(--text-primary);
    font-weight: 600;
}

/* Pricing tag for the configurator — centered standalone, same look as
   the .service-price chips inside the 3 cards so config + cards visually
   read as one product family. */
.cfg-price {
    display: block;
    width: fit-content;
    margin: 14px auto 0;
}

/* Casual aside that ties the configurator into the 3 service cards
   below. Reads as a friendly throwaway line so the cards feel like
   "and here's the rest of what we ship" rather than a separate menu. */
.services-aside {
    margin: 56px auto 28px;
    text-align: center;
    font-size: 14px;
    font-weight: 500;
    color: var(--text-muted);
    letter-spacing: 0.01em;
}

.cfg-intro__eyebrow {
    display: inline-block;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--accent-blue-mid);
    margin-bottom: 12px;
}

.cfg-intro__title {
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: -0.01em;
    color: var(--text-primary);
    margin-bottom: 14px;
}

.cfg-intro__copy {
    font-size: 16px;
    line-height: 1.65;
    color: var(--text-secondary);
    margin-top: 14px;
}

/* ---------- Viewer (canvas + overlays) ---------- */
.cfg-viewer {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 16px;
    overflow: hidden;
    box-shadow: var(--shadow-md);
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    touch-action: pan-y;
}
.cfg-viewer.is-grabbing {
    cursor: grabbing;
}

.cfg-canvas {
    display: block;
    width: 100%;
    height: 100%;
}

/* Loading state */
.cfg-loading {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
    pointer-events: none;
    transition: opacity 0.4s var(--transition-base);
}
.cfg-viewer.is-ready .cfg-loading {
    opacity: 0;
}

/* Drag hint — visible until first interaction or 4s timeout */
.cfg-hint {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.5s ease;
    color: var(--text-secondary);
}
.cfg-viewer.is-ready:not(.is-engaged) .cfg-hint {
    opacity: 0.7;
}
.cfg-hint__icon {
    width: 44px;
    height: 44px;
    opacity: 0.55;
}
.cfg-hint__label {
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

/* Preload progress bar */
.cfg-progress {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: rgba(0, 0, 0, 0.06);
    overflow: hidden;
    transition: opacity 0.3s ease;
}
.cfg-viewer.is-loaded .cfg-progress {
    opacity: 0;
}
.cfg-progress__bar {
    height: 100%;
    width: 0%;
    background: var(--accent-main);
    transition: width 0.15s linear;
}

/* ---------- Paint swatches — round dots, bottom-center inside viewport ---------- */
.cfg-swatches {
    position: absolute;
    bottom: 16px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 5;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 12px;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border-radius: 999px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
}

.cfg-swatch {
    appearance: none;
    border: none;
    background: transparent;
    padding: 0;
    border-radius: 50%;
    cursor: pointer;
    line-height: 0;
    transition: transform var(--transition-fast);
}
.cfg-swatch:hover {
    transform: scale(1.08);
}
.cfg-swatch:focus-visible {
    outline: 2px solid var(--accent-main);
    outline-offset: 2px;
    border-radius: 50%;
}

.cfg-swatch__dot {
    display: block;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--swatch-color, #888);
    /* Subtle inner ring so light/white swatches stay visible on the dark pill. */
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.18);
    transition: box-shadow var(--transition-fast);
}
.cfg-swatch.is-active .cfg-swatch__dot {
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25),
                0 0 0 2px rgba(0, 0, 0, 0.55),
                0 0 0 4px #fff;
}

/* ---------- Preset angle thumbnails (top-center inside viewport) ---------- */
.cfg-angles {
    position: absolute;
    top: 16px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 8px;
    z-index: 5;
    padding: 8px;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border-radius: 12px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    transition: opacity var(--transition-base);
}
.cfg-angles[hidden] {
    display: none;
}

.cfg-angles__btn {
    appearance: none;
    border: 2px solid rgba(255, 255, 255, 0.18);
    background: #f0f0f0;          /* light bg shows while the thumb decodes */
    border-radius: 6px;
    padding: 0;
    overflow: hidden;
    cursor: pointer;
    transition: border-color var(--transition-fast), transform var(--transition-fast);
    /* Smaller now that they share the bottom row with the swatches above. */
    width: 76px;
    height: 43px;                 /* still 16:9 — no crop on the render */
    line-height: 0;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}
.cfg-angles__btn:hover {
    border-color: var(--accent-main);
    transform: scale(1.06) translateY(-2px);
}
.cfg-angles__btn:focus-visible {
    outline: 2px solid var(--accent-main);
    outline-offset: 2px;
}
.cfg-angles__btn img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
    pointer-events: none;
}

/* Hide the angle row briefly during a paint switch so it doesn't flash
   the wrong colors before its own thumbs swap. */
.cfg-viewer.is-switching .cfg-angles {
    opacity: 0;
    pointer-events: none;
}

/* ---------- Interior pano (Three.js inverted-sphere viewer) ---------- */
/* Transparent bg + WebGLRenderer({ alpha: true }) means the panoBox
   never flashes black during texture-load. Whatever's underneath
   (exterior canvas on first entry, previous pano during env-swap)
   shows through until the new sphere paints its first frame. */
.cfg-pano {
    position: absolute;
    inset: 0;
    z-index: 2;
    background: transparent;
    cursor: grab;
    touch-action: none;
}
.cfg-pano[hidden] {
    display: none;
}
.cfg-pano canvas {
    display: block;
    width: 100% !important;
    height: 100% !important;
}
/* When interior is active, hide exterior overlays that don't apply. */
.cfg-viewer.is-interior .cfg-canvas,
.cfg-viewer.is-interior .cfg-angles,
.cfg-viewer.is-interior .cfg-hint,
.cfg-viewer.is-interior .cfg-spinner,
.cfg-viewer.is-interior .cfg-progress {
    display: none;
}

/* ---------- View toggle (exterior ⇄ interior) ---------- */
.cfg-view-toggle {
    position: absolute;
    bottom: 16px;
    left: 16px;
    z-index: 7;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0;
    background: rgba(0, 0, 0, 0.65);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 8px;
    cursor: pointer;
    overflow: hidden;
    transition: border-color var(--transition-fast), transform var(--transition-fast);
    appearance: none;
}
.cfg-view-toggle:hover {
    border-color: var(--accent-main);
    transform: translateY(-1px);
}
.cfg-view-toggle:focus-visible {
    outline: 2px solid var(--accent-main);
    outline-offset: 2px;
}
.cfg-view-toggle__thumb {
    display: block;
    width: 110px;
    height: 70px;
    background: rgba(255, 255, 255, 0.04) center / 220% auto no-repeat;
}
.cfg-view-toggle__label {
    display: block;
    padding: 6px 8px;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #fff;
    text-align: center;
    background: rgba(0, 0, 0, 0.4);
}
@media (max-width: 640px) {
    .cfg-view-toggle {
        bottom: 12px;
        left: auto;
        right: 12px;
        flex-direction: row;
        align-items: center;
    }
    .cfg-view-toggle__thumb { display: none; }
    .cfg-view-toggle__label { padding: 8px 12px; font-size: 10px; background: transparent; }
}

/* ---------- Environment toggle (bottom-right) ---------- */
.cfg-env-toggle {
    position: absolute;
    bottom: 16px;
    right: 16px;
    z-index: 7;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0;
    background: rgba(0, 0, 0, 0.65);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 8px;
    cursor: pointer;
    overflow: hidden;
    transition: border-color var(--transition-fast), transform var(--transition-fast);
    appearance: none;
}
.cfg-env-toggle:hover {
    border-color: var(--accent-main);
    transform: translateY(-1px);
}
.cfg-env-toggle:focus-visible {
    outline: 2px solid var(--accent-main);
    outline-offset: 2px;
}
.cfg-env-toggle__thumb {
    display: block;
    width: 110px;
    height: 70px;
    background: rgba(255, 255, 255, 0.04) center / cover no-repeat;
}
.cfg-env-toggle__label {
    display: block;
    padding: 6px 8px;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: #fff;
    text-align: center;
    background: rgba(0, 0, 0, 0.4);
}
@media (max-width: 640px) {
    .cfg-env-toggle {
        bottom: 12px;
        right: 12px;
        flex-direction: row;
        align-items: center;
    }
    .cfg-env-toggle__thumb { display: none; }
    .cfg-env-toggle__label { padding: 8px 12px; font-size: 10px; background: transparent; }
}

/* ---------- Spinner (variant switch) ----------
   Floating chip — no backdrop, no blur. The full 360 stays visible behind
   it; the user keeps interacting with the previous paint until the new
   one is fully loaded and atomically swapped in. */
.cfg-spinner {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 6;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.18s ease;
}
.cfg-viewer.is-switching .cfg-spinner {
    opacity: 1;
}

.cfg-spinner__chip {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px 10px 12px;
    background: rgba(0, 0, 0, 0.78);
    border-radius: 999px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
}
.cfg-spinner__ring {
    display: block;
    width: 18px;
    height: 18px;
    border: 2px solid rgba(255, 255, 255, 0.25);
    border-top-color: #fff;
    border-radius: 50%;
    animation: cfg-spin 0.85s linear infinite;
}
.cfg-spinner__label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #fff;
    line-height: 1;
}
@keyframes cfg-spin {
    to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
    .cfg-spinner__ring { animation-duration: 2.5s; }
}

/* ---------- Mobile tuning ---------- */
@media (max-width: 640px) {
    .cfg-stage {
        margin-top: 40px;
    }
    .cfg-intro {
        margin-bottom: 22px;
    }
    .cfg-intro__copy {
        font-size: 14px;
    }
    .cfg-viewer {
        border-radius: 12px;
    }
    .cfg-angles {
        gap: 5px;
        padding: 4px;
        top: 10px;
        border-radius: 10px;
    }
    .cfg-angles__btn {
        width: 60px;
        height: 34px;
        border-radius: 5px;
    }
    .cfg-hint__label {
        font-size: 11px;
    }
    .cfg-swatches {
        bottom: 10px;
        gap: 7px;
        padding: 5px 9px;
    }
    .cfg-swatch__dot {
        width: 22px;
        height: 22px;
    }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
    .cfg-hint, .cfg-progress, .cfg-loading {
        transition: none;
    }
}

/* ========================================================================
   COMPREHENSIVE MOBILE PASS — everything ≤ 768px
   Single source of truth for phone/small-tablet styling. Overrides
   anything from styles.min.css that doesn't behave on small screens.
   ======================================================================== */
@media (max-width: 768px) {

    /* ---------- Hero ---------- */
    .hero {
        min-height: 92svh;          /* small-viewport-height respects mobile URL bar */
        min-height: 92vh;
        padding: 0;
    }
    .hero .hero-content {
        padding: 0 20px;
        gap: 0;
    }
    .hero .hero-badge {
        font-size: 9.5px;
        letter-spacing: 0.26em;
        margin-bottom: 16px;
    }
    .hero .hero-title {
        font-size: clamp(2.6rem, 13.5vw, 4.5rem);
        line-height: 0.92;
        letter-spacing: -0.04em;
    }
    .hero .hero-tagline {
        font-size: 12px;
        margin-top: 18px;
        max-width: 340px;
        line-height: 1.5;
    }
    .hero .hero-clients {
        bottom: 16px;
        font-size: 9.5px;
        max-width: 100%;
        padding: 0 16px;
        line-height: 1.5;
    }

    /* ---------- Manifesto (short brand line on yellow) ---------- */
    .manifesto {
        padding: 26px 16px;
    }
    .manifesto__line {
        font-size: clamp(0.95rem, 4vw, 1.2rem);
        line-height: 1.2;
    }
    .manifesto__clients {
        font-size: 9.5px;
        margin-top: 8px;
    }

    /* ---------- Section spacing trim ---------- */
    .services,
    .icp-section,
    .who-we-are,
    .portfolio {
        padding: 64px 0;
    }

    /* ---------- 3 service cards stack 1-col ---------- */
    .services-grid.three-col {
        grid-template-columns: 1fr;
        gap: 16px;
    }

    /* ---------- "Oh yeah" aside ---------- */
    .services-aside {
        margin: 36px auto 18px;
        font-size: 13px;
    }

    /* ---------- Configurator card ---------- */
    .cfg-stage {
        margin: 36px auto 0;
        border-radius: 14px;
    }
    /* Mac-frame chrome compresses on mobile so the title fits without truncation. */
    .cfg-stage .mac-frame__title,
    .ff-stage .mac-frame__title {
        font-size: 10px;
        margin-right: 32px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    /* Viewer slightly taller than 16:9 on phone so the car has room to breathe
       given the angle row + swatch row + corner toggles eat overlay area. */
    .cfg-viewer {
        aspect-ratio: 4 / 3;
    }
    .cfg-loading,
    .cfg-hint__label {
        font-size: 10px;
    }
    .cfg-hint__icon {
        width: 32px;
        height: 32px;
    }
    /* Corner toggles (View Interior / env-toggle) — top corners on mobile so
       they don't fight the swatch row at the bottom. Compact text pills. */
    .cfg-view-toggle,
    .cfg-env-toggle {
        top: 8px;
        bottom: auto;
    }
    .cfg-view-toggle { left: 8px; }
    .cfg-env-toggle  { right: 8px; }
    .cfg-view-toggle__label,
    .cfg-env-toggle__label {
        font-size: 9px;
        padding: 5px 9px;
        letter-spacing: 0.08em;
    }
    /* Hide angle thumbs on mobile — too cramped. Drag works; users don't
       need preset angles in a 360×~270 viewer. */
    .cfg-angles {
        display: none;
    }
    /* Swatches stay at bottom-center but slightly raised so they sit clear
       of any future bottom corner UI. */
    .cfg-swatches {
        bottom: 10px;
    }
    /* Footer caption + price stack centered (already from 700px) — ensure neat. */
    .cfg-footer {
        padding: 14px 14px 16px;
    }
    .cfg-footer .cfg-caption {
        font-size: 12px;
        line-height: 1.55;
    }

    /* ---------- FlatFinder card ---------- */
    .ff-stage {
        margin: 22px auto 0;
        border-radius: 14px;
    }
    .ff-frame {
        height: 60svh;          /* fills 60% of viewport height — feels right on phone */
        height: 60vh;
        min-height: 420px;
        max-height: 600px;
    }
    .ff-footer {
        padding: 14px 14px 16px;
    }
    .ff-caption {
        font-size: 12px;
        line-height: 1.55;
    }

    /* ---------- Quick-call CTA inside How It Works ---------- */
    .quick-call--inline {
        margin-top: 40px;
    }
    .quick-call__title {
        font-size: clamp(1.6rem, 6vw, 2rem);
    }
    .quick-call__body {
        font-size: 14px;
    }
    .quick-call__features {
        gap: 8px 10px;
    }
    .quick-call__features li {
        font-size: 12px;
        padding: 6px 12px;
    }
    .quick-call__btn {
        padding: 12px 22px;
        font-size: 14px;
    }

    /* ---------- Step 1 CTA ---------- */
    .step-cta {
        margin-top: 14px;
        padding: 11px 18px;
        font-size: 13px;
        width: 100%;
        justify-content: center;
    }

    /* ---------- Vibe button ---------- */
    .vibe-button {
        bottom: 12px;
        left: 12px;
        padding: 7px 11px 7px 10px;
        font-size: 10px;
        letter-spacing: 0.04em;
        gap: 6px;
    }
    .vibe-button__indicator {
        width: 12px;
        height: 12px;
    }
    .vibe-eq__bar { width: 1.5px; }
    .vibe-eq      { height: 12px; }

    /* ---------- Availability widget — match the .vibe-button pill ---------- */
    .availability-widget {
        bottom: 12px;
        right: 12px;
    }
    .availability-widget .widget-collapsed {
        padding: 7px 10px 7px 11px;
        gap: 6px;
    }
    .availability-widget .collapsed-text {
        font-size: 10px;
        letter-spacing: 0.04em;
    }
    .availability-widget .live-pulse-small {
        width: 8px;
        height: 8px;
    }

    /* ---------- Quick-call CTA outer (in How It Works) on smaller phones ---------- */
    @media (max-width: 480px) {
        .quick-call__features {
            flex-direction: column;
            align-items: center;
        }
    }
}

/* ---------- Tighten further on very small phones ---------- */
@media (max-width: 380px) {
    .hero .hero-title { font-size: clamp(2.2rem, 14vw, 3rem); }
    .hero .hero-clients { font-size: 9px; }
    .manifesto__line { font-size: 0.95rem; }
    .vibe-button { font-size: 9.5px; padding: 6px 10px 6px 9px; }
    .availability-widget { transform: scale(0.92); transform-origin: bottom right; }
}

/* ========================================
   Quick-call CTA — 15-minute Calendly
   Sits between the configurator/Services section and the Process section.
   ======================================== */

.quick-call {
    padding: 96px 0;
    background: var(--bg-card);
    border-top: 1px solid var(--border-color);
    border-bottom: 1px solid var(--border-color);
}

/* Inline variant — used as a closing CTA inside another section
   (e.g. nested at the end of #process). Renders as a self-contained
   black panel so the "Step 1 starts with a conversation" message
   pops against the lighter parent section. */
.quick-call--inline {
    padding: 72px 48px;
    background: #0a0a0a;
    border: none;
    margin-top: 96px;
    border-radius: 24px;
    color: #fff;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.16);
    overflow: hidden;
    position: relative;
}

/* Subtle radial glow behind the title for depth */
.quick-call--inline::before {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse at top, rgba(207, 255, 4, 0.08) 0%, transparent 60%);
    pointer-events: none;
}
.quick-call--inline > * {
    position: relative;
    z-index: 1;
}

/* Recolor children so they read on the new dark background */
.quick-call--inline .quick-call__title {
    color: #fff;
}
.quick-call--inline .quick-call__body {
    color: rgba(255, 255, 255, 0.72);
}
.quick-call--inline .quick-call__features li {
    background: rgba(255, 255, 255, 0.06);
    border-color: rgba(255, 255, 255, 0.12);
    color: rgba(255, 255, 255, 0.92);
}
.quick-call--inline .quick-call__features svg {
    color: var(--accent-main);
}

@media (max-width: 640px) {
    .quick-call--inline {
        margin-top: 56px;
        padding: 48px 24px;
        border-radius: 18px;
    }
}

/* ========================================
   Who We Work With — 4 cards in a single row (was 2x2). Original
   styles.min.css uses repeat(2, 1fr); this overrides at desktop and
   keeps the existing 2-up tablet / 1-up mobile breakpoints sensible.
   ======================================== */
.icp-grid {
    grid-template-columns: repeat(4, 1fr) !important;
    gap: 20px !important;
}
@media (max-width: 1100px) {
    .icp-grid {
        grid-template-columns: repeat(2, 1fr) !important;
    }
}
@media (max-width: 540px) {
    .icp-grid {
        grid-template-columns: 1fr !important;
    }
}
/* Tile aspect — switched from the 1:1 default (in styles.css:2231) to the
   source PNG's natural 33:56 portrait (≈9:15.3, very close to 9:16). The
   new Who/* webps are 720×1222 = same ratio so they cover-fit edge-to-edge
   with no cropping. */
.icp-card { aspect-ratio: 33 / 56 !important; }
/* Slight typography trim so 4 cards fit comfortably in one row. */
.icp-card-content { padding: 18px !important; }
.icp-card h3 { font-size: 16px !important; }
.icp-card p { font-size: 13px !important; line-height: 1.5 !important; }

/* ========================================
   Manifesto — acid-yellow stripe between hero and services that hammers
   our positioning: we're the rare studio that does both 3D + code, which
   is why we can ship configurators / interactive 3D at all.
   ======================================== */
.manifesto {
    padding: 36px 0;
    background: var(--accent-main);
    color: #0a0a0a;
    border-top: 1px solid rgba(0, 0, 0, 0.08);
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
.manifesto__line {
    max-width: 1100px;
    margin: 0 auto;
    text-align: center;
    font-size: clamp(1.05rem, 2.2vw, 1.5rem);
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.015em;
    color: #0a0a0a;
}
/* Tiny client roster sitting under the slogan on the yellow stripe. */
.manifesto__clients {
    max-width: 720px;
    margin: 10px auto 0;
    text-align: center;
    font-size: 10.5px;
    line-height: 1.5;
    color: rgba(0, 0, 0, 0.55);
    text-wrap: balance;
}
@media (max-width: 640px) {
    .manifesto {
        padding: 28px 16px;
    }
    .manifesto__line {
        font-size: 1.05rem;
    }
}

/* CTA button on Step 1 of the timeline. Sits below the bullet list. */
.step-cta {
    margin-top: 18px;
    padding: 12px 22px;
    font-size: 14px;
}
.step-cta svg {
    transition: transform var(--transition-fast);
}
.step-cta:hover svg {
    transform: translateX(3px);
}

/* ========================================
   Vibe button — fixed bottom-left, plays a silly shopping tune to put
   visitors in a buying mood. Mirrors the bottom-right availability
   widget's positioning and dark pill aesthetic.
   ======================================== */
.vibe-button {
    position: fixed;
    bottom: 24px;
    left: 24px;
    z-index: 100;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px 10px 14px;
    background: #0a0a0a;
    color: #fff;
    border: 0;
    border-radius: 999px;
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.32);
    cursor: pointer;
    font-family: var(--font-main);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    transition: transform var(--transition-fast), background var(--transition-fast), color var(--transition-fast);
    line-height: 1;
}
.vibe-button:hover {
    transform: translateY(-2px);
    background: #1a1a1a;
}
.vibe-button:focus-visible {
    outline: 2px solid var(--accent-main);
    outline-offset: 3px;
}
.vibe-button.is-playing {
    background: var(--accent-main);
    color: #0a0a0a;
    box-shadow: 0 8px 28px rgba(207, 255, 4, 0.35);
    /* Subtle pulse on the whole button so it's obviously alive while playing. */
    animation: vibe-pulse 2.4s ease-in-out infinite;
}
@keyframes vibe-pulse {
    0%, 100% { box-shadow: 0 8px 28px rgba(207, 255, 4, 0.35); }
    50%      { box-shadow: 0 10px 36px rgba(207, 255, 4, 0.55); }
}

.vibe-button__indicator {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: currentColor;
}
/* Hide eq bars when not playing, hide play arrow when playing. */
.vibe-button .vibe-eq { display: none; }
.vibe-button.is-playing .vibe-button__play { display: none; }
.vibe-button.is-playing .vibe-eq { display: inline-flex; }

.vibe-eq {
    align-items: flex-end;
    gap: 2px;
    height: 14px;
}
.vibe-eq__bar {
    display: block;
    width: 2px;
    height: 4px;
    background: currentColor;
    border-radius: 1px;
    animation: vibe-eq-bounce 0.85s ease-in-out infinite;
}
.vibe-eq__bar:nth-child(2) { animation-delay: 0.18s; }
.vibe-eq__bar:nth-child(3) { animation-delay: 0.36s; }
@keyframes vibe-eq-bounce {
    0%, 100% { height: 4px; }
    50%      { height: 12px; }
}
@media (prefers-reduced-motion: reduce) {
    .vibe-button.is-playing { animation: none; }
    .vibe-eq__bar           { animation-duration: 2s; }
}
@media (max-width: 640px) {
    .vibe-button {
        bottom: 16px;
        left: 16px;
        padding: 8px 12px 8px 11px;
        font-size: 10.5px;
    }
}

/* When the nav sits over the hero (not yet scrolled), the original
   dark logo + hamburger lines are unreadable against the dark video.
   Filter the logo pure white and recolor the hamburger spans. The
   .scrolled state restores the original colors automatically. */
.nav:not(.scrolled) .logo img {
    filter: brightness(0) invert(1);
}
.nav:not(.scrolled) .nav-toggle span {
    background: #fff;
}
/* Cycling slogan only appears once the nav has its scrolled chrome —
   while we're sitting over the hero it would clash with the headline.
   Using display:none + !important to defeat any other rule that re-shows it. */
.nav-slogan,
.nav-center {
    transition: opacity var(--transition-base);
}
.nav:not(.scrolled) .nav-slogan,
.nav:not(.scrolled) .nav-center {
    display: none !important;
}

/* Team-sketches name/role popups: lift further above the head so the
   tooltip + arrow sit clearly off the face instead of touching it.
   Also adds a tiny upward rise on hover for a more confident reveal. */
.team-sketches .team-member::before {
    bottom: calc(100% + 16px) !important;
    transform: translateX(-50%) translateY(4px) !important;
    transition: opacity 0.2s ease, transform 0.2s ease !important;
    z-index: 20 !important;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
}
.team-sketches .team-member::after {
    bottom: calc(100% + 6px) !important;
    z-index: 20 !important;
}
.team-sketches .team-member:hover::before {
    transform: translateX(-50%) translateY(0) !important;
}

/* ========================================
   Hero rebuild — full-screen blurred video background with the
   headline overlaid huge. Overrides the older split-layout rules in
   styles.min.css (this file loads after, so these win).
   ======================================== */
.hero {
    /* Sticky so the page literally scrolls UP and OVER the hero. The
       hero stays pinned to the top until the body's containing block
       runs out, while every section after it slides up over the top. */
    position: sticky;
    top: 0;
    z-index: 0;
    min-height: 100svh;        /* small-viewport height — avoids mobile URL-bar jump */
    min-height: 100vh;
    height: 100vh;
    padding: 0;
    overflow: hidden;
    background: #060607;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Every flow section after the hero must sit on a higher z-index with
   an opaque background, otherwise the sticky hero would bleed through. */
.manifesto,
.services,
.process,
.icp-section,
.who-we-are,
.portfolio,
.cta-section,
.quick-call {
    position: relative;
    z-index: 1;
}

/* Video as a true background layer — softly blurred, dimmed. */
.hero .hero-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: blur(3.5px) brightness(0.62) saturate(1.05);
    /* scale up just enough to hide the blur halo at the edges */
    transform: scale(1.02);
    z-index: 0;
    pointer-events: none;
}
/* Dark vignette over the video for guaranteed text contrast. */
.hero-overlay {
    position: absolute;
    inset: 0;
    z-index: 1;
    background:
        radial-gradient(ellipse at center, rgba(0,0,0,0.15) 0%, rgba(0,0,0,0.55) 80%),
        linear-gradient(to bottom, rgba(0,0,0,0.25) 0%, rgba(0,0,0,0.45) 100%);
    pointer-events: none;
}

/* Matrix rain canvas — draws across the whole hero, then masked to a
   ~240px spotlight that follows the cursor via the --mx / --my CSS vars
   that JS updates on mousemove. Pointer-events stay through to the hero
   so headline links / drag still work. */
.hero-matrix {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    /* 240px spotlight, hard center fading out to transparent edge.
       Default off-screen so the effect is hidden until the cursor enters. */
    mask-image: radial-gradient(circle 240px at var(--mx, -1000px) var(--my, -1000px), black 28%, transparent 100%);
    -webkit-mask-image: radial-gradient(circle 240px at var(--mx, -1000px) var(--my, -1000px), black 28%, transparent 100%);
    mix-blend-mode: screen;
    /* Force the canvas onto its own compositor layer — combined with the
       sticky hero + active audio element, mix-blend-mode can otherwise
       trigger a Chrome paint-stall where the page stops repainting on
       scroll until you click somewhere. will-change resolves it. */
    will-change: mask-image;
    transform: translateZ(0);
}
/* Disable on touch devices (no mouse → no spotlight to chase). */
@media (hover: none) {
    .hero-matrix { display: none; }
}

/* Disable legacy hero pieces that the rebuild replaces. */
.hero .hero-glow,
.hero .hero-container,
.hero .hero-visual,
.hero .hero-video-container { display: contents; }
.hero .hero-glow { display: none; }

.hero .hero-content {
    position: relative;
    z-index: 3;       /* above matrix canvas (z-index: 2) */
    text-align: center;
    color: #fff;
    padding: 0 24px;
    max-width: 1200px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0;
}

/* Eyebrow — small-caps label above the headline. */
.hero .hero-badge {
    display: inline-block;
    background: transparent;
    border: 0;
    padding: 0;
    margin-bottom: 28px;
    font-size: clamp(11px, 0.95vw, 14px);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.32em;
    color: rgba(255, 255, 255, 0.78);
    border-radius: 0;
    width: auto;
}

/* Hero headline — pretty large, in your face. */
.hero .hero-title {
    font-size: clamp(3.25rem, 13vw, 10rem);
    font-weight: 800;
    line-height: 0.92;
    letter-spacing: -0.045em;
    color: #fff;
    text-shadow: 0 4px 36px rgba(0, 0, 0, 0.45);
    margin: 0;
}
.hero .hero-title .thin-line {
    font-weight: 300;
}
/* Keep the existing .gradient-text rule from styles.min.css for "Kick Ass". */

.hero .hero-tagline {
    font-size: clamp(0.82rem, 1.05vw, 0.98rem);
    font-weight: 500;
    color: rgba(255, 255, 255, 0.82);
    margin-top: 28px;
    line-height: 1.5;
    max-width: 620px;
    text-wrap: balance;
}
.hero .hero-tagline strong {
    color: var(--accent-main);
    font-weight: 700;
}

/* Client roster anchored at the bottom of the hero, fully centered.
   text-wrap: balance gives roughly even line lengths so we never get
   "and CIRC." dangling on its own line. */
.hero .hero-clients {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 28px;
    margin: 0 auto;
    z-index: 2;
    max-width: 720px;
    padding: 0 24px;
    text-align: center !important;
    text-wrap: balance;
    font-size: 11px;
    line-height: 1.55;
    color: rgba(255, 255, 255, 0.6);
}

@media (max-width: 640px) {
    .hero .hero-video {
        filter: blur(2px) brightness(0.6);
        transform: scale(1.03);
    }
    .hero .hero-badge {
        font-size: 10px;
        letter-spacing: 0.28em;
        margin-bottom: 18px;
    }
    .hero .hero-tagline {
        margin-top: 18px;
    }
    .hero .hero-clients {
        bottom: 18px;
        font-size: 10px;
    }
}

/* ========================================
   macOS-style window chrome — wraps interactive embeds (configurator,
   FlatFinder iframe) so they read as "this is a live app, not a banner."
   Three traffic-light dots, dark title bar, content area below.
   ======================================== */
.mac-frame {
    width: 100%;
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 14px 40px rgba(0, 0, 0, 0.18), 0 2px 8px rgba(0, 0, 0, 0.08);
    border: 1px solid rgba(0, 0, 0, 0.12);
    background: #1d1d1f;
}
.mac-frame__bar {
    display: flex;
    align-items: center;
    height: 32px;
    padding: 0 14px;
    background: linear-gradient(to bottom, #2c2c2e 0%, #1d1d1f 100%);
    border-bottom: 1px solid rgba(0, 0, 0, 0.4);
    user-select: none;
}
.mac-frame__dots {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
}
.mac-frame__dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    box-shadow: inset 0 0 0 0.5px rgba(0, 0, 0, 0.2);
}
.mac-frame__dot--red    { background: #ff5f57; }
.mac-frame__dot--yellow { background: #febc2e; }
.mac-frame__dot--green  { background: #28c840; }
.mac-frame__title {
    flex: 1;
    text-align: center;
    font-size: 12px;
    font-weight: 500;
    color: rgba(255, 255, 255, 0.55);
    /* Offset for the dots so the title visually centers in the bar. */
    margin-right: 52px;
    letter-spacing: 0.01em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Content embedded inside a mac-frame inherits framing from the wrapper —
   strip its own border-radius / shadow / border. */
.mac-frame .cfg-viewer,
.mac-frame .ff-frame {
    border-radius: 0;
    border: 0;
    box-shadow: none;
}

@media (max-width: 640px) {
    .mac-frame__bar {
        height: 28px;
        padding: 0 10px;
    }
    .mac-frame__dot { width: 10px; height: 10px; }
    .mac-frame__title { font-size: 11px; margin-right: 44px; }
}

/* ========================================
   FlatFinder demo embed (lives inside .icp-section, after the ICP grid)
   Same intro/outro rhythm as the configurator, but the interactive piece
   is a sandboxed iframe loading apps/flatfinder/ — own JS, own CSS, no
   conflict with the host page.
   ======================================== */

/* FlatFinder = the 5th thing we deliver. Same card chrome as cfg-stage so
   they read as siblings ("here's what we ship: 3 cards + 2 featured demos"). */
.ff-stage {
    max-width: 1100px;
    margin: 28px auto 0;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 20px;
    overflow: hidden;
    box-shadow: 0 14px 40px rgba(0, 0, 0, 0.06), 0 2px 6px rgba(0, 0, 0, 0.04);
}
.ff-stage .mac-frame {
    border-radius: 0;
    border: 0;
    box-shadow: none;
}

.ff-frame {
    position: relative;
    width: 100%;
    height: 720px;
    background: #0c0c0e;
}
.ff-iframe {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
}

.ff-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 28px;
    padding: 22px 28px;
    border-top: 1px solid var(--border-color);
}
.ff-caption {
    margin: 0;
    flex: 1;
    text-align: left;
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-secondary);
}
.ff-caption strong {
    color: var(--text-primary);
    font-weight: 600;
}
.ff-price {
    margin: 0;
    flex-shrink: 0;
    align-self: center;
}

@media (max-width: 900px) {
    .ff-frame { height: 620px; }
}
@media (max-width: 700px) {
    .ff-footer {
        flex-direction: column;
        align-items: stretch;
        gap: 14px;
        padding: 18px 18px 20px;
    }
    .ff-caption {
        text-align: center;
        font-size: 12.5px;
    }
    .ff-price { align-self: center; }
}
@media (max-width: 640px) {
    .ff-frame {
        height: 540px;
    }
}

.quick-call__inner {
    max-width: 720px;
    margin: 0 auto;
    text-align: center;
}

.quick-call__title {
    font-size: clamp(2rem, 4.5vw, 3rem);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--text-primary);
    margin-bottom: 18px;
}

.quick-call__body {
    font-size: 17px;
    line-height: 1.65;
    color: var(--text-secondary);
    margin-bottom: 28px;
}

/* Three quick wins as inline pills with check/clock/dollar icons. */
.quick-call__features {
    list-style: none;
    padding: 0;
    margin: 0 auto 32px;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px 14px;
}

.quick-call__features li {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    font-size: 14px;
    font-weight: 500;
    color: var(--text-primary);
}

.quick-call__features svg {
    width: 16px;
    height: 16px;
    color: var(--accent-blue-mid);
    flex-shrink: 0;
}

.quick-call__btn {
    /* Tweak the existing .btn-primary slightly for the CTA hero treatment. */
    padding: 14px 28px;
    font-size: 16px;
}

.quick-call__btn svg {
    transition: transform var(--transition-fast);
}
.quick-call__btn:hover svg {
    transform: translateX(3px);
}

@media (max-width: 640px) {
    .quick-call {
        padding: 64px 0;
    }
    .quick-call__body {
        font-size: 15px;
    }
    .quick-call__features li {
        font-size: 13px;
        padding: 7px 12px;
    }
}


/* ================================================================
   PORTFOLIO — Apple/Newsroom-style media grid.
   Scoped to .portfolio-grid--apple so the redesign only affects
   the homepage "Stuff We've Made" section (BMW reveal slider above
   it, show-more button + NDA meme below it untouched).
   Layout: 1 cinematic tall tile (2x2) + 11 squared tiles (3-up)
   on desktop. 2-up on tablet. 1-up on mobile. Bottom-gradient
   caption shows category eyebrow + title; descriptions live in
   the DOM but are hidden visually on small tiles.
   ================================================================ */
.portfolio-grid--apple {
    grid-template-columns: 1fr;
    gap: 16px;
    /* Match the BMW slider → first row gap to the card-to-card gap.
       The legacy .reveal-slider-container sets margin-bottom: 32px,
       so we zero that and let the grid's margin-top own the spacing. */
    margin-top: 16px;
}
.portfolio .reveal-slider-container {
    margin-bottom: 0;
}
@media (min-width: 720px) {
    .portfolio-grid--apple {
        grid-template-columns: 1fr 1fr;
        gap: 18px;
        margin-top: 18px;
    }
}
@media (min-width: 1080px) {
    .portfolio-grid--apple {
        grid-template-columns: repeat(3, 1fr);
        gap: 20px;
        margin-top: 20px;
    }
}

/* Cards: full-bleed media, 28px corners, no extra wrapper chrome.
   `contain: paint` keeps repaints (image zoom, etc.) scoped to the
   card so scrolling past 12 of them doesn't flood the compositor. */
.portfolio-grid--apple .portfolio-card {
    position: relative;
    overflow: hidden;
    border-radius: 28px;
    aspect-ratio: 4 / 3;
    background: #1d1d1f;
    contain: paint;
    /* Beat the legacy .portfolio-card padding/border from styles.min.css */
    padding: 0;
    border: 0;
    box-shadow: none;
    transform: none;
    transition: none;
}
/* No card-lift on hover — :hover flipping on/off as the page scrolls
   under the cursor was causing scroll jank on the long grid. The
   image zoom inside the card stays — it's contained and cheap. */
.portfolio-grid--apple .portfolio-card:hover {
    transform: none;
    box-shadow: none;
}

/* Tall cinematic hero tile — spans 2 cols × 2 rows on desktop.
   Explicit aspect-ratio (not auto) so grid auto-rows resolve
   deterministically before the videos load. */
.portfolio-grid--apple .portfolio-card--tall {
    aspect-ratio: 4 / 3;
}
@media (min-width: 1080px) {
    .portfolio-grid--apple .portfolio-card--tall {
        grid-column: span 2;
        grid-row: span 2;
        aspect-ratio: 4 / 3;
    }
}

/* Media fills the card. Override legacy radii/padding from styles.min.css */
.portfolio-grid--apple .portfolio-image,
.portfolio-grid--apple .portfolio-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    border-radius: 0;
    overflow: hidden;
    background: #1d1d1f;
}
.portfolio-grid--apple .portfolio-image img,
.portfolio-grid--apple .portfolio-video video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 0;
    transition: transform 0.8s ease;
}
.portfolio-grid--apple .portfolio-card:hover .portfolio-image img,
.portfolio-grid--apple .portfolio-card:hover .portfolio-video video {
    transform: scale(1.05);
}

/* Caption: bottom gradient overlay, white type */
.portfolio-grid--apple .portfolio-content {
    position: absolute;
    inset: auto 0 0 0;
    padding: 22px 26px 24px;
    color: #fff;
    background: linear-gradient(180deg,
        transparent 0%,
        rgba(0, 0, 0, 0.18) 35%,
        rgba(0, 0, 0, 0.78) 100%);
    /* Reset legacy alignment/padding */
    text-align: left;
    margin: 0;
    border: 0;
}
.portfolio-grid--apple .portfolio-card--tall .portfolio-content {
    padding: 32px 36px 36px;
}

.portfolio-grid--apple .portfolio-category {
    display: inline-block;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -0.003em;
    color: #2997ff; /* Apple "on-dark" accent blue */
    background: transparent;
    padding: 0;
    margin-bottom: 6px;
    text-transform: none;
}

.portfolio-grid--apple .portfolio-card h3 {
    font-size: clamp(17px, 1.7vw, 21px);
    font-weight: 600;
    letter-spacing: -0.008em;
    line-height: 1.2;
    color: #fff;
    margin: 0 0 4px;
}
.portfolio-grid--apple .portfolio-card--tall h3 {
    font-size: clamp(22px, 2.4vw, 30px);
    margin-bottom: 8px;
}

/* Descriptions hidden on small tiles, visible on the cinematic hero */
.portfolio-grid--apple .portfolio-card p {
    display: none;
}
.portfolio-grid--apple .portfolio-card--tall p {
    display: block;
    font-size: 15px;
    line-height: 1.45;
    color: rgba(255, 255, 255, 0.78);
    max-width: 56ch;
    margin: 0;
}

/* Re-tune the bottom fade so it looks right against the new card sizes.
   Plain selector (not :has()) for max compatibility + zero scroll cost. */
.portfolio-grid--apple ~ .portfolio-fade,
.portfolio .portfolio-fade {
    bottom: 100px;
    height: 200px;
}


/* ================================================================
   SERVICES — Apple feature-card layout for the 3 flagship services.
   Three full-width rows. Media + content side-by-side, alternating
   left/right per row. Featured (Product Animation) is dark; CAD and
   AI are on light grey. Mobile stacks media-on-top.
   Scoped to .services-grid--feature so existing service-card styles
   on other pages stay intact.
   ================================================================ */
.services-grid--feature {
    display: flex;
    flex-direction: column;
    gap: 24px;
    /* Override the legacy .services-grid grid layout from styles.min.css */
    grid-template-columns: none !important;
}

.services-grid--feature .service-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background: #1d1d1f;   /* All 3 cards on dark grey now */
    color: #f5f5f7;
    border-radius: 28px;
    overflow: hidden;
    /* Override legacy .service-card padding/border/shadow */
    padding: 0 !important;
    border: 0 !important;
    box-shadow: none !important;
    transform: none;
    transition: none;
}
.services-grid--feature .service-card:hover {
    transform: none;
    box-shadow: none;
}

/* Media area: 16/9 on mobile, fills its column on desktop */
.services-grid--feature .service-image-container {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    margin: 0;
    border-radius: 0;
    background: #1d1d1f;
}
.services-grid--feature .service-image-container img,
.services-grid--feature .service-image-container video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 0;
}
/* CAD card auto-cycle — 4 images in sequence:
   audi (beauty) → audi (mesh) → truck → truck mesh → loop.
   8s total cycle, each image visible ~2s with brief crossfade overlap.
   Single keyframe shape, staggered via negative animation-delay so all
   four are perfectly out of phase from the same shared timeline.
   Note: overrides the simpler 2-image cadFade in styles.css via the
   higher specificity (3 classes vs 2). */
.services-grid--feature .cad-crossfade .cad-img {
    animation: cadFade4 8s infinite ease-in-out;
    opacity: 0;
}
.services-grid--feature .cad-crossfade .cad-img-1 { animation-delay:  0s; opacity: 1; }
.services-grid--feature .cad-crossfade .cad-img-2 { animation-delay: -6s; }
.services-grid--feature .cad-crossfade .cad-img-3 { animation-delay: -4s; }
.services-grid--feature .cad-crossfade .cad-img-4 { animation-delay: -2s; }
@keyframes cadFade4 {
    0%, 22%   { opacity: 1; }   /* visible window: 0–22%  (≈0–1.76s) */
    27%, 95%  { opacity: 0; }   /* invisible: 27–95% (≈2.16–7.6s) */
    100%      { opacity: 1; }   /* fade back in over the last 5% to loop */
}

/* Body */
.services-grid--feature .service-card-content {
    padding: 32px 28px 36px;
    display: flex;
    flex-direction: column;
    gap: 0;
    text-align: left;
}

/* Eyebrow — small coloured tag above the title */
.services-grid--feature .service-eyebrow {
    display: inline-block;
    font-size: clamp(15px, 1.4vw, 18px);
    font-weight: 600;
    letter-spacing: -0.005em;
    color: #06c;
    margin: 0 0 12px;
}
.services-grid--feature .service-eyebrow--orange { color: #fb6e3a; }
.services-grid--feature .service-eyebrow--green  { color: #2db84a; }

/* Title — Apple feature-page scale */
.services-grid--feature .service-card h3 {
    font-size: clamp(26px, 3.2vw, 40px);
    font-weight: 600;
    letter-spacing: -0.012em;
    line-height: 1.1;
    color: #fff;
    margin: 0 0 14px;
}

/* Body copy — kept compact so the controls + price + CTA always fit
   within the 4:3 (config/ff) and 16:9 (others) card heights. */
.services-grid--feature .service-card p {
    font-size: clamp(13px, 1.05vw, 15px);
    line-height: 1.5;
    color: rgba(245, 245, 247, 0.72);
    max-width: 52ch;
    margin: 0 0 18px;
}

/* Footer row — price + CTA on the same line across ALL 5 cards. Sits at
   the bottom of the card body via margin-top:auto pushing it down within
   the column-flex parent. gap controls the spacing between price text
   and the CTA arrow link; flex-wrap means narrow cards still fit. */
.services-grid--feature .service-footer {
    display: flex;
    flex-direction: row;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px 24px;
    margin-top: auto;
}

/* Price — inline within the footer row (no bottom margin anymore). */
.services-grid--feature .service-price {
    display: inline-block;
    position: static;
    font-size: 17px;
    font-weight: 600;
    color: #fff;
    background: transparent;
    padding: 0;
    margin: 0;
    border: 0;
}

/* CTA arrow link — Apple "on-dark" blue, brightens to white on hover.
   align-self override removed since the parent footer handles alignment. */
.services-grid--feature .service-cta {
    color: #2997ff;
    font-size: 17px;
    font-weight: 400;
    letter-spacing: -0.005em;
    transition: color .2s;
}
.services-grid--feature .service-cta::after {
    content: " ›";
    display: inline-block;
    transition: transform .2s;
}
.services-grid--feature .service-cta:hover {
    color: #fff;
}
.services-grid--feature .service-cta:hover::after {
    transform: translateX(3px);
}
/* The `--light` modifier is now equivalent to the default since
   every card is dark — kept as a no-op so existing markup still works. */
.services-grid--feature .service-cta--light { color: #2997ff; }
.services-grid--feature .service-cta--light:hover { color: #fff; }

/* Desktop: media + content side-by-side, alternating left/right.
   :nth-child(even) reverses the row → media on the right. */
@media (min-width: 880px) {
    .services-grid--feature .service-card {
        flex-direction: row;
        align-items: stretch;
        min-height: 440px;
    }
    .services-grid--feature .service-card:nth-child(even) {
        flex-direction: row-reverse;
    }
    .services-grid--feature .service-image-container {
        flex: 1 1 50%;
        aspect-ratio: auto;
        min-height: 100%;
    }
    .services-grid--feature .service-card-content {
        flex: 1 1 50%;
        justify-content: center;
        padding: clamp(40px, 5vw, 72px);
    }
}


/* ================================================================
   Cards 4 & 5 — Configurator + Flatfinder, embedded in the same
   .services-grid--feature alternating row layout as cards 1–3.
   Strips the legacy mac-frame chrome and fits the interactive media
   into .service-image-container. Swatches & toggles move to the
   text side as part of the card body.
   ================================================================ */
.services-grid--feature .service-card--config,
.services-grid--feature .service-card--ff {
    /* Inherit the dark card chrome and alternating flex layout from
       the base .service-card rules. The legacy standalone .cfg-stage
       styles (max-width, margin, border, custom bg) shouldn't apply
       when the stage IS the card — neutralize them here. */
    max-width: none;
    margin: 0;
    background: #1d1d1f;
    border: 0;
    border-radius: 28px;
    box-shadow: none;
}

/* CARD 4 (configurator) — breaks out of the alternating row layout. The
   card stacks vertically: panoramic mac-window viewer on top, then card
   body (eyebrow + h3 + p + swatches/toggles + price + CTA). The viewer
   sits inside a .mac-frame chrome with traffic-light dots so it reads as
   a real interactive app, not a hero banner. */
.services-grid--feature .service-card--config {
    flex-direction: column !important;
    align-items: stretch !important;
}
.services-grid--feature .service-card--config .service-image-container {
    /* Wrapper — full-width slot for the mac-frame. No fixed aspect-ratio
       (the .cfg-viewer inside owns aspect via 21:9), no own background
       (mac-frame supplies it), padding gives breathing room from the
       card edge. Overflow visible so the mac-frame's shadow can show. */
    aspect-ratio: auto;
    background: transparent;
    overflow: visible;
    padding: 28px 28px 0;
    width: 100%;
    height: auto;
    flex: 0 0 auto;
}
.services-grid--feature .service-card--config .mac-frame {
    width: 100%;
    border-radius: 14px;
    overflow: hidden;
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.45), 0 4px 12px rgba(0, 0, 0, 0.25);
    border: 1px solid rgba(255, 255, 255, 0.06);
}
.services-grid--feature .service-card--config .cfg-viewer {
    /* Panoramic 21:9 — wide cinematic crop on the source 16:9 render
       (the cover-fit math in paintAt clips the empty top/bottom of the
       turntable, leaving only the wide horizontal band where the car is).
       position: relative so internal overlays (hint, spinner, angles)
       still anchor to the viewer rect, not the card. */
    position: relative;
    inset: auto;
    width: 100%;
    height: auto;
    aspect-ratio: 21 / 9;
    background: #060607;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    margin: 0;
}
.services-grid--feature .service-card--ff .service-image-container {
    aspect-ratio: 1 / 1; /* flatfinder building source IS square — match it */
    background: #060607;
    overflow: hidden;
}
.services-grid--feature .service-card--ff .ff-frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border-radius: 0;
    border: 0;
    box-shadow: none;
}
.services-grid--feature .service-card--ff .ff-iframe {
    width: 100%;
    height: 100%;
    border: 0;
}

/* Swatches strip — sits at the TOP of .service-card-content, directly
   below the mac-frame, full-width row of color dots. Centered horizontally
   so it visually anchors to the viewport above. */
.services-grid--feature .service-card--config .cfg-swatches {
    position: static;
    transform: none;
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
    padding: 0;
    gap: 14px;
    justify-content: center;
    margin: 0 0 22px;
    display: flex;
    flex-wrap: wrap;
}
.services-grid--feature .service-card--config .cfg-swatch__dot {
    width: 32px;
    height: 32px;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.2);
}

/* Corner overlay toggles — view (bottom-left) + env (bottom-right) inside
   the viewer. Compact label-only pills (no preview thumb), dark glass
   backdrop so they pop on light env renders without dominating the frame. */
.services-grid--feature .service-card--config .cfg-view-toggle,
.services-grid--feature .service-card--config .cfg-env-toggle {
    position: absolute !important;
    bottom: 14px !important;
    z-index: 6 !important;
    flex-direction: row !important;
    align-items: center !important;
    gap: 0 !important;
    padding: 7px 12px !important;
    background: rgba(0, 0, 0, 0.65) !important;
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.16) !important;
    border-radius: 999px !important;
    overflow: hidden !important;
    width: auto !important;
    height: auto !important;
    transform: none !important;
    cursor: pointer;
    transition: border-color var(--transition-fast), background var(--transition-fast);
}
.services-grid--feature .service-card--config .cfg-view-toggle {
    left: 14px !important;
    right: auto !important;
    top: auto !important;
}
.services-grid--feature .service-card--config .cfg-env-toggle {
    right: 14px !important;
    left: auto !important;
    top: auto !important;
}
.services-grid--feature .service-card--config .cfg-view-toggle:hover,
.services-grid--feature .service-card--config .cfg-env-toggle:hover {
    border-color: var(--accent-main) !important;
    background: rgba(0, 0, 0, 0.78) !important;
    transform: none !important;
}
.services-grid--feature .service-card--config .cfg-view-toggle__label,
.services-grid--feature .service-card--config .cfg-env-toggle__label {
    padding: 0 !important;
    background: transparent !important;
    font-size: 10px !important;
    letter-spacing: 0.12em !important;
    line-height: 1 !important;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.92) !important;
}

/* Card-layout overrides on the configurator viewer overlays. The bottom
   of the canvas belongs to the angles row; everything else either
   relocates or hides so nothing leaks. !important is used because the
   legacy .cfg-* rules are widely scoped and the inline-style background
   image set by configurator.js was making leftover thumbs visible.    */

/* Drag hint → small top-center pill (was a big centered icon). */
.services-grid--feature .service-card--config .cfg-hint {
    inset: auto 0 auto 0 !important;
    top: 14px !important;
    flex-direction: row !important;
    gap: 6px !important;
    padding: 5px 12px !important;
    width: max-content !important;
    margin: 0 auto !important;
    background: rgba(0, 0, 0, 0.5) !important;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-radius: 999px !important;
    color: rgba(255, 255, 255, 0.85) !important;
}
.services-grid--feature .service-card--config .cfg-hint__icon {
    width: 14px !important;
    height: 14px !important;
    opacity: 0.9 !important;
}
.services-grid--feature .service-card--config .cfg-hint__label {
    font-size: 10px !important;
    letter-spacing: 0.12em !important;
}

/* Loading text — hidden in the card layout (progress bar handles it). */
.services-grid--feature .service-card--config .cfg-loading {
    display: none !important;
}

/* CRUSH the corner toggle thumbs in the card layout. The toggle BUTTONS
   live in the card text side now (as label-only pills); the .__thumb
   element used to hold a 110×70 background-image of the next env's frame.
   Without these the thumb was rendering as a wide horizontal slice of
   the car at the bottom-right of the card. */
.services-grid--feature .service-card--config .cfg-view-toggle__thumb,
.services-grid--feature .service-card--config .cfg-env-toggle__thumb,
.services-grid--feature .service-card--ff   .cfg-view-toggle__thumb,
.services-grid--feature .service-card--ff   .cfg-env-toggle__thumb {
    display: none !important;
    width: 0 !important;
    height: 0 !important;
    background: none !important;
}

/* Toggle buttons in the FF card layout — pulled inline. Card 4
   (configurator) uses corner-overlay positioning instead, defined above
   with higher specificity (.service-card--config .cfg-view-toggle). */
.services-grid--feature .service-card--ff .cfg-view-toggle,
.services-grid--feature .service-card--ff .cfg-env-toggle {
    position: static !important;
    flex-direction: row !important;
    align-items: center !important;
    justify-content: center !important;
    width: auto !important;
    height: auto !important;
    top: auto !important;
    bottom: auto !important;
    left: auto !important;
    right: auto !important;
    transform: none !important;
}

/* Angles row sits inside the canvas (.cfg-viewer) at bottom-center. The
   element carries an inline style="..." that locks the position; the
   only thing CSS does here is set the [hidden] state and style the
   inner buttons. No display/position rules — those would compete with
   the inline style and we'd be back to whack-a-mole. */
.services-grid--feature .service-card--config .cfg-angles[hidden] {
    display: none !important;
}
.services-grid--feature .service-card--config .cfg-angles__btn {
    /* position: relative is critical — the cards-1-3 hero-image rule
       `.services-grid--feature .service-image-container img { position:
       absolute; inset: 0 }` (line ~1742) inherits down to our angle thumb
       <img>s. Without a positioned parent, those imgs escape the 56×32
       button and stretch to .cfg-angles (the next positioned ancestor),
       which is why all 3 thumbs were collapsing into one wide image. */
    position: relative !important;
    width: 56px !important;
    height: 32px !important;
    border: 1px solid rgba(255, 255, 255, 0.18) !important;
    border-radius: 6px !important;
    background: #1a1a1a !important;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35) !important;
    flex: 0 0 auto !important;
    overflow: hidden !important;
    transition: border-color 0.15s ease;
}
.services-grid--feature .service-card--config .cfg-angles__btn:hover {
    border-color: var(--accent-main) !important;
    transform: none !important;
}
.services-grid--feature .service-card--config .cfg-angles__btn img {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
}

/* Desktop aspect locks.
   - Configurator: NO card aspect-ratio (column stack flows naturally —
     viewer height = (card-width - 56px padding) ÷ (21/9), then card body
     content adds whatever it needs below). Removing the row-layout
     constraint that was forcing 8/3.
   - Flatfinder: 2/1 card → 1/1 media half. Building source render IS
     1:1 — anything wider than 1:1 was cropping the building top + bottom
     and leaving the iframe's empty .stage gradient showing. */
@media (min-width: 880px) {
    .services-grid--feature .service-card--ff {
        aspect-ratio: 2 / 1 !important;
        min-height: 0 !important;
        max-height: none !important;
    }
    .services-grid--feature .service-card--ff .service-image-container {
        aspect-ratio: auto !important;
        height: 100% !important;
        min-height: 0 !important;
    }
}

/* Mobile: shorten the controls margin so the card body doesn't run long. */
@media (max-width: 880px) {
    .services-grid--feature .service-card--config .cfg-controls {
        margin-bottom: 18px;
    }
}

/* ================================================================
   FLATFINDER scroll-trap fix.
   The iframe is a separate document, so wheel events over it never
   reach the parent page → page scroll feels broken when the cursor
   is over the embed. Solution: iframe is pointer-events:none by
   default (so wheel events pass through to the page), with a
   transparent shield button on top that activates the iframe on
   click and deactivates on mouseleave (or scroll-out-of-view).
   The configurator doesn't need this because it's a same-document
   canvas, not a cross-document iframe.
   ================================================================ */
.ff-frame .ff-iframe {
    pointer-events: none;
    transition: filter .25s ease;
}
.ff-frame.is-active .ff-iframe {
    pointer-events: auto;
}

.ff-shield {
    position: absolute;
    inset: 0;
    z-index: 2;
    background: transparent;
    border: 0;
    padding: 0;
    cursor: pointer;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    /* Keep the shield itself transparent — only the hint pill shows */
}
.ff-frame.is-active .ff-shield {
    /* Hide once user has activated the iframe; reappears on mouseleave */
    opacity: 0;
    pointer-events: none;
}
.ff-shield__hint {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    margin-bottom: 28px;
    border-radius: 980px;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    color: #fff;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: -0.005em;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
    pointer-events: none;
    animation: ff-hint-bob 2.4s ease-in-out infinite;
}
@keyframes ff-hint-bob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) {
    .ff-shield__hint { animation: none; }
}

