/* =========================================================
   SuperPixel theme — main stylesheet
   Figma node 22:830, canvas 1280 × ~4687.
   Every section's pixel values are matched 1:1 to Figma.
   ========================================================= */

:root {
    --color-primary: #eb4700;
    --color-accent: #1566e0;
    --color-text: #000000;
    --color-muted: #535353;
    --color-muted-2: #969696;
    --color-border: #1e1e1e;
    --color-bg: #ffffff;
    --font-sans: "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    /* Canvas (v2.4.25) — caps at 1280 design width and lets content
       fill the full viewport width on narrower screens (no symmetric
       gutter reservation). FREE QUOTE floating button is fixed at
       right:0 and is allowed to overlap the rightmost edge by design. */
    --canvas-width: min(1280px, 100%);
    --content-pad: max(40px, calc((100vw - 1280px) / 2));
}

/* * { box-sizing: border-box; } */ /* disabled v2.4.21 per user request */
/* v2.6.96 — disabled native smooth-scroll; Lenis handles it now and
   the two together cause stuttering. */
html { scroll-behavior: auto; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: clip; }
html, body { margin: 0; padding: 0; }

/* v2.6.52 — overflow-x: clip on html only (no body override) so wide
   elements get clipped without creating a second scrollbar context. */
html { overflow-x: clip; }
body {
    font-family: var(--font-sans);
    color: var(--color-text);
    background: #ffffff;
    line-height: 1.5;
    font-size: 14px;
}

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }

/* Force Figtree everywhere — UA stylesheets default form controls and
   headings to system fonts, which would break the Figma typography. */
h1, h2, h3, h4, h5, h6,
button, input, select, textarea, optgroup {
    font-family: var(--font-sans);
}

.screen-reader-text { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; }
.skip-link { position: absolute; left: -9999px; top: 10px; background:#000; color:#fff; padding: 8px 12px; }
.skip-link:focus { left: 10px; z-index: 1000; }

/* Pin the design to the 1280 canvas and centre on larger viewports.
   v2.6.105 — footer opted OUT of the 1280 cap so it spans the full
   viewport width on wide / zoomed-out monitors with no right-side
   gutter. Footer children below are re-anchored accordingly. */
.site-main, .site-footer { max-width: var(--canvas-width); margin-left: auto; margin-right: auto; width: 100%; }
.site-footer { max-width: none; }

/* Body offsets the fixed header so the hero starts below the navbar. */
body { padding-top: 76px; }

/* =======================================================
   GLOBAL TRANSITIONS
   ======================================================= */
[data-reveal] {
    opacity: 0;
    transform: translateY(28px);
    transition: opacity .9s cubic-bezier(.2,.7,.2,1), transform .9s cubic-bezier(.2,.7,.2,1);
    will-change: opacity, transform;
}
[data-reveal].is-visible { opacity: 1; transform: translateY(0); }
[data-reveal-delay="1"].is-visible { transition-delay: .08s; }
[data-reveal-delay="2"].is-visible { transition-delay: .16s; }
[data-reveal-delay="3"].is-visible { transition-delay: .24s; }
[data-reveal-delay="4"].is-visible { transition-delay: .32s; }
[data-reveal-delay="5"].is-visible { transition-delay: .40s; }

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    [data-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; }
    .testimonials__track { animation: none !important; }
    * { transition-duration: 0s !important; animation-duration: 0s !important; }
}

a, button, .testimonial, .portfolio__card, .cta__portrait, .site-footer__social-icon {
    transition: transform .35s cubic-bezier(.2,.7,.2,1), opacity .25s ease, color .25s ease, background .25s ease, filter .35s ease;
}

/* =======================================================
   BUTTONS
   ======================================================= */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    text-transform: uppercase;
    border: 0;
    cursor: pointer;
    line-height: 1;
    text-decoration: none;
    /* v2.7.0 — explicit so <button class="btn"> matches <a class="btn">. */
    font-family: inherit;
    background: transparent;
}
.btn--primary {
    background: var(--color-primary);
    color: #fff;
    width: 148px;
    height: 36px;
    font-size: 12px;
    transition: background-color .25s ease, box-shadow .25s ease, transform .25s ease;
}
/* Figma 62:1153 / 62:1139 — orange button lifts up + soft orange glow on hover. */
.btn--primary:hover {
    background: #c83b00;
    box-shadow: 0 12px 24px rgba(235, 71, 0, 0.45);
    transform: translateY(-4px);
}

.btn--lg { width: 153.333px; height: 41.333px; font-size: 13.78px; }

.btn--quote {
    background: transparent;
    /* v2.7.0 — pill bumped so the GET A QUOTE label sits on par with the
       16px nav links next to it. Previous 8.99px / 100x30.667 read tiny. */
    border: 1px solid var(--color-primary);
    color: var(--color-primary);
    padding: 0 22px;
    height: 38px;
    font-size: 18px; /* +4 (was 14) */
    letter-spacing: 0.04em;
    transition: background-color .25s ease, color .25s ease, box-shadow .25s ease, transform .25s ease;
}
/* Figma 62:1146 — outline → filled orange + lift + glow on hover. */
.btn--quote:hover {
    background: var(--color-primary);
    color: #fff;
    box-shadow: 0 10px 20px rgba(235, 71, 0, 0.35);
    transform: translateY(-4px);
}

/* Navbar CTA cluster — Get a Quote + tagline */
.navbar__cta {
    display: inline-flex;
    align-items: center;
    gap: 35px;
}
.navbar__cta-tag {
    font-family: var(--font-sans);
    font-size: 16px;
    font-weight: 500;
    color: var(--color-muted);
    white-space: nowrap;
    letter-spacing: 0.2px;
}

.btn--outline-dark {
    background: transparent;
    border: 1.6px solid var(--color-border);
    color: var(--color-border);
    height: 36px;
    padding: 0 24px;
    font-size: 12.8px;
    transition: background-color .25s ease, color .25s ease, border-color .25s ease, box-shadow .25s ease;
}
/* Figma 62:1169 VIEW ALL WORK — fills with black on hover. */
.btn--outline-dark:hover {
    background: var(--color-border);
    border-color: var(--color-border);
    color: #fff;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
}

.btn--start {
    width: 173.898px;
    height: 37.492px;
    border-width: 1.595px;
    font-size: 12.76px;
    /* v2.11.90 — solid orange (was black outline). */
    color: #fff;
    background: var(--color-primary);
    border-color: var(--color-primary);
}
/* v2.7.76 — About section CTA row: START A PROJECT + LEARN MORE link
   side by side. Mirrors hero__actions layout. */
.about__actions {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}
/* START A PROJECT — solid orange; darken + glow on hover. */
.btn--start:hover {
    background: #d63f00;
    border-color: #d63f00;
    color: #fff;
    box-shadow: 0 8px 24px rgba(235, 71, 0, 0.40);
}

/* =======================================================
   HEADER — sticky/frozen, Figma node 22:1133
   76px tall, white-translucent w/ blur, full-width
   ======================================================= */
.site-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 100;
    height: 76px;
    background: rgba(255, 255, 255, 0.37);
    backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px);
    transition: background-color .35s ease, backdrop-filter .35s ease;
}
/* feedback N1 — the fixed header sat UNDER the WP admin bar for logged-in
   users. Push it down by the admin-bar height (only when it's present —
   regular visitors don't see the bar, so the header stays flush at top:0). */
.admin-bar .site-header { top: 32px; }
@media screen and (max-width: 782px) {
    .admin-bar .site-header { top: 46px; }
}
/* v2.6.89 — while the hero carousel is in full-bleed showreel mode,
   the nav becomes a darker glassmorph bar with WHITE text/icons so
   it reads cleanly against the video underneath. */
.site-header.is-over-showreel {
    /* v2.6.95 — dropped backdrop-filter: blur over the playing video.
       Re-rasterising the blur every frame of video playback caused
       severe scroll jank. Solid translucent gradient reads similarly
       and costs almost nothing on the compositor. */
    background: linear-gradient(180deg, rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0));
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}
/* v2.6.89 — make every label inside the nav read white over the video. */
.site-header.is-over-showreel .navbar__links a,
.site-header.is-over-showreel .navbar__links a:hover,
.site-header.is-over-showreel .navbar__link,
.site-header.is-over-showreel .navbar__link-label,
.site-header.is-over-showreel .navbar__caret {
    color: #fff;
    /* v2.9.85 — text-shadow removed per request; the header's dark gradient
       backdrop (below) carries the contrast for the white labels. */
    text-shadow: none;
}
/* v2.9.81 — the Portfolios/Services mega panels are WHITE cards, so their inner
   links must stay dark even in showreel mode (the broad `.navbar__links a` rule
   above was turning them white-on-white). Keep the normal hover tint too. */
.site-header.is-over-showreel .navbar__dropdown a,
.site-header.is-over-showreel .navbar__mega-links a,
.site-header.is-over-showreel .navbar__sub-item > a {
    color: var(--color-text);
    text-shadow: none;
}
.site-header.is-over-showreel .navbar__dropdown a:hover,
.site-header.is-over-showreel .navbar__mega-links a:hover,
.site-header.is-over-showreel .navbar__sub-item:hover > a {
    color: var(--color-primary);
}
/* feedback — over the full-page hero video, hovering the nav (incl. the
   Portfolios/Services triggers) keeps the labels WHITE — no orange tint. The
   blue grow-right underline carries the hover affordance instead. */
.site-header.is-over-showreel .navbar__item--has-sub:hover .navbar__link,
.site-header.is-over-showreel .navbar__item--has-sub:hover .navbar__link-label,
.site-header.is-over-showreel .navbar__item--has-sub:hover .navbar__caret {
    color: #fff;
    text-shadow: none;
}
/* Outlined "Get a Quote" pill keeps a thin white outline + white text. */
.site-header.is-over-showreel .btn--quote {
    color: #fff;
    border-color: #fff;
}
.site-header.is-over-showreel .btn--quote:hover {
    color: var(--color-primary);
    background: #fff;
    border-color: #fff;
}
/* Logo PNG is colored; invert to a pure white silhouette over the video. */
.site-header.is-over-showreel .navbar__logo img {
    filter: brightness(0) invert(1);
}
/* v2.6.89 — floating FREE QUOTE button hides during full-page showreel
   so it doesn't compete with the cinematic reel. Re-enters as the user
   scrolls past the hero runway. */
body.is-showreel .floating-quote {
    opacity: 0 !important;
    transform: translateX(20px) !important;
    pointer-events: none;
}
.navbar {
    position: relative;
    /* v2.5.7 — navbar spans the full viewport so the logo/CTA cluster sit
       at the actual edges; with the 1280 cap the bar looked squished
       against the full-bleed hero video below it. */
    max-width: none;
    margin: 0;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 clamp(20px, 3.3vw, 63px);
}
.navbar__logo img { height: 22px; width: auto; } /* feedback N2 — logo +~15% (19→22) */
.navbar__menu { display: flex; align-items: center; gap: 34.413px; }
.navbar__links { list-style: none; display: flex; gap: 34.413px; margin: 0; padding: 0; }
.navbar__links a {
    color: var(--color-muted);
    font-size: 19px; /* feedback N2 — header text +2pt (16→19) */
    line-height: 1;
    transition: color .2s ease;
}
.navbar__links a:hover { color: var(--color-text); }
/* feedback — nav links reveal a BLUE underline that grows left→right on hover,
   like the "Learn More / Our Work" links. Scoped to the text label so it doesn't
   run under the dropdown caret. */
.navbar__link-label { position: relative; }
.navbar__link-label::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: -5px; height: 1.5px;
    background: #1566e0; transform: scaleX(0); transform-origin: left;
    transition: transform .3s cubic-bezier(.2, .7, .2, 1);
}
.navbar__item:hover .navbar__link-label::after,
.navbar__link:hover .navbar__link-label::after,
.navbar__link--trigger:hover .navbar__link-label::after,
.navbar__link--trigger:focus-visible .navbar__link-label::after { transform: scaleX(1); }

/* =======================================================
   HERO — Figma node 22:1124
   ======================================================= */
/* v2.6.98 — runway lengthened to 250vh.
   v2.6.101 — break the wrap out of .site-main's 1280px cap so the
   hero/carousel are full viewport width on wide / zoomed-out monitors.
   Without this, .hero's overflow:hidden was clipping the carousel's
   own 100vw trick at the 1280 boundary, leaving white gutters.
   v2.11.30 — runway shortened 250vh → 150vh. Hero is sticky ~100vh, so
   the effective pinned scroll-runway drops from ~150vh (felt like 2-3
   scrolls to clear the hero) to ~50vh — the expand/parallax now completes
   in roughly one scroll. EXPAND_END (0.6) is a ratio of the runway, so
   the expand still finishes before the hero unpins; no JS change needed. */
.hero-wrap {
    position: relative;
    height: 150vh;
    width: 100vw;
    margin-left: calc(50% - 50vw);
}
.hero {
    position: sticky;
    top: 76px;
    /* v2.6.67 — Atlure-style fit-to-viewport. Hero fills viewport
       below the 76px nav; carousel uses flex:1 to take the remaining
       space after the copy block. */
    height: calc(100vh - 76px);
    padding: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
/* v2.6.97 — REMOVED .is-showreel-full position:fixed. JS now drives
   the hero's `top` and `height` directly as inline styles, lerped to
   the scroll position so the expand from (top:76, height:100vh-76)
   to (top:0, height:100vh) plays back smoothly across the runway.
   Past the runway the sticky element unsticks naturally and portfolio
   reveals from below — no snap, no fixed jump. */
.hero { will-change: top, height; }
.hero__copy {
    /* v2.5.7 — Figma 166:2067: 820px wide block, centered, text-center.
       v2.6.64 — gap retuned 30px → 24px to match updated Figma spec. */
    width: 820px;
    max-width: calc(100% - 80px);
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 24px;
    flex-shrink: 0;
}
.hero__eyebrow {
    font-size: 16px; /* v2.12.114 — user paste (was 14px) */
    font-weight: 500;
    text-transform: capitalize;
    color: #000;
    margin: 0;
    line-height: 1;
}
.hero__country {
    color: inherit;
    text-transform: uppercase;
    display: inline-block;
}

.hero__title {
    font-size: 52px;
    font-weight: 600;
    line-height: 1.2;
    margin: 0;
    letter-spacing: -0.01em;
    width: 100%;
    max-width: 100%;
    text-align: center;
}
.hero__title-light { font-weight: 500; }
.hero__title-italic { display: block; font-style: italic; font-weight: 600; }

.hero__actions {
    margin-top: 8px;
    display: flex;
    align-items: center;
    gap: 12px;
    height: 41.333px;
}
.hero__link {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-weight: 600;
    font-size: 16px; /* v2.12.114 — user paste (was 14px) */
    text-transform: uppercase;
    color: #000;
    height: 28px;
    padding: 0 14px;
    position: relative;
}
/* v2.9.77 — hero "Start a Project" bumped +2px with it; width auto so the
   longer text isn't clipped by the standard fixed 148px button width. */
.hero__actions .btn--primary {
    font-size: 16px; /* v2.12.114 — user paste (was 14px) */
    width: auto;
    min-width: 148px;
    padding: 0 22px;
}
/* Figma 62:1245 OUR WORKS — bottom underline reveals on hover. */
.hero__link::after {
    content: "";
    position: absolute;
    left: 12px;
    right: 12px;
    bottom: 2px;
    height: 1px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .3s cubic-bezier(.2, .7, .2, 1);
}
.hero__link:hover::after { transform: scaleX(1); }
/* Use a Unicode "→" instead of the buggy Figma SVG so the chevron
   always renders cleanly across browsers. Slides right on hover with
   an elastic ease for a tactile "go forward" feel. */
.hero__link-arrow {
    display: inline-flex;
    align-items: center;
    line-height: 1;
    font-size: 17px;
    transition: transform .25s cubic-bezier(.34, 1.56, .64, 1);
}
.hero__link:hover .hero__link-arrow { transform: translateX(4px); }

.hero__banner {
    /* Full-bleed: span the full viewport width on wide PC monitors so the
       hero video isn't cropped at the 1280px canvas edge. */
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    margin-top: 30px;
    aspect-ratio: 1920 / 1080;
    overflow: hidden;
}
.hero__banner img,
.hero__banner video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Free Quote tab — fixed to viewport right (Figma 218:1361).
   v2.6.68 — clean orange rectangle: no border, no dark drop-shadow.
   Live effect at top-left corner: a white dot wrapped in a pulsing
   blurry orange glow (Figma Ellipse 19/20). */
.floating-quote {
    position: fixed;
    bottom: clamp(72px, 11vh, 180px);
    /* v2.12.32 — user requirement: the button must HUG the scrollbar (nempel), not float
       in from the edge. The 20px gap (v2.12.29) read as "kegeser". right:0 sits flush
       against the scrollbar's inner edge on desktop classic scrollbars. (Mobile: right:0 too.)
       v2.12.53 — but on desktop the right:0 edge slid BEHIND the scrollbar and got clipped.
       --spx-sbw (set in main.js) = exactly how far it overshoots, so the button hugs the
       scrollbar's inner edge without being cut. 0 when right:0 is already flush (no gap). */
    right: var(--spx-sbw, 0px);
    /* v2.6.101 — clamp max bumped from 96/72 → 140/115 so the button
       stays substantial on zoomed-out / ultra-wide monitors. Previously
       it pegged at 96×72 CSS px and read as a tiny rectangle next to
       the full-vw video. Figma 218:1361 baseline still 73×60. */
    /* v2.7.0 — shrunk ~15% per user request. */
    width: clamp(62px, 6vw, 119px);
    height: clamp(51px, 4.9vw, 98px);
    background: var(--color-primary);
    color: #fff;
    border: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 90;
    /* Hidden at top-of-page; JS toggles .is-visible after scroll. */
    opacity: 0;
    transform: translateX(20px);
    pointer-events: none;
    transition: opacity .4s ease,
                transform .4s cubic-bezier(.2, .7, .2, 1),
                background-color .25s ease;
}
.floating-quote.is-visible {
    opacity: 1;
    transform: translateX(0);
    pointer-events: auto;
}
.floating-quote:hover {
    background: #d63f00;
}
/* Live effect — white dot at the top-left corner with an expanding
   orange "signal" ring that loops with a pause between pings.
   v2.6.72 — replaced blurry box-shadow with a real DOM circle. The
   ring is a regular element (no blur), low alpha, expanding via scale.
   Animation timeline: 0-50% expand + fade, 50-100% held invisible
   (the "jeda" / pause). White dot stays static; only the ring animates. */
.floating-quote::before {
    /* Static white dot — centered on the corner point. */
    content: "";
    position: absolute;
    top: -4px;
    left: -4px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #fff;
    pointer-events: none;
    opacity: 0;
    z-index: 2;
}
.floating-quote.is-visible::before { opacity: 1; }

.floating-quote::after {
    /* Expanding orange signal ring — sits behind the dot, centered on
       the same corner point. Base 16×16 → scales up to ~3.5x. */
    content: "";
    position: absolute;
    top: -8px;
    left: -8px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--color-primary);
    pointer-events: none;
    opacity: 0;
    z-index: 1;
}
.floating-quote.is-visible::after {
    animation: floating-quote-signal 2.6s ease-out infinite;
}
@keyframes floating-quote-signal {
    /* Active: 0 → 50% = expand + fade. Pause: 50 → 100% held off. */
    0%   { transform: scale(0.4); opacity: 0.5; }
    50%  { transform: scale(3.5); opacity: 0;   }
    100% { transform: scale(3.5); opacity: 0;   }
}
@media (prefers-reduced-motion: reduce) {
    .floating-quote.is-visible::after { animation: none; }
}
.floating-quote__text {
    font-family: var(--font-sans);
    font-weight: 700;
    font-size: clamp(13px, 1vw, 19px);
    letter-spacing: 0;
    line-height: 1.2;
    color: #fff;
    text-align: center;
}

/* =======================================================
   PORTFOLIO — Figma node 22:1004
   ======================================================= */
.portfolio {
    /* v2.11.26 — was width:1200px, which left the Selected Work grid 40px
       narrower per side than .about__inner / the /portfolios/ page (.works),
       so it read as off-centre. Match the 1280 centred canvas + 40px padding
       used by every other section → content lines up at 1200px wide.
       v2.11.35 — ROOT-CAUSE FIX for the "mepet kanan / space numpuk di kiri"
       reports: global `box-sizing` is disabled (main.css ~L24), so this
       section defaulted to content-box → its real width was 1280 + 2×padding
       (e.g. 1408px with the temporary 64px padding), overflowing the viewport
       on a ~1280px laptop: right column clipped, left looked over-spaced.
       Other sections (.about etc.) were fine because they set border-box
       themselves. Add border-box here and return padding to the canonical
       40px so Selected Work lines up symmetrically with every other section. */
    box-sizing: border-box;
    width: 100%;
    max-width: 1280px;
    margin: 80px auto 0;
    padding: 0 40px;
    display: flex;
    flex-direction: column;
    gap: 38px;
}
.portfolio__filters {
    display: flex;
    flex-wrap: wrap;
    gap: 40px;
    align-items: center;
    min-height: 20.8px;
    position: relative;
    /* Lift the entire filter row above the portfolio grid below it so the
       Others dropdown panel (a descendant) paints on top of the cards
       — without this the grid (later in DOM) wins the paint order. */
    z-index: 10;
}
.portfolio__filter,
.portfolio__filter-other {
    background: none;
    border: 0;
    padding: 0;
    font-size: 18px; /* v2.12.113 — user paste (was 14px → 16px → 18px) */
    font-weight: 500;
    color: var(--color-border);
    cursor: pointer;
    font-family: inherit;
    line-height: 1.2;
    transition: color .2s ease;
}
.portfolio__filter:hover,
.portfolio__filter-other:hover { color: var(--color-accent); }
.portfolio__filter.is-active { color: var(--color-accent); font-weight: 600; }

/* "Others" filter — plain text + small caret (matches Figma).
   Caret is CSS-drawn (right + bottom border square rotated 45°) so it
   inherits the current text colour and never hits the SVG aspect-ratio
   stretching bug. */
.portfolio__filter-others-wrap {
    position: relative;
    display: inline-block;
}
.portfolio__filter-other {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.portfolio__filter-caret {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg) translateY(-1px);
    transition: transform .25s cubic-bezier(.34, 1.56, .64, 1);
}
.portfolio__filter-other:hover .portfolio__filter-caret {
    transform: rotate(45deg) translateY(1px);
}
/* Active state (panel open): flip caret to point up + tint blue. */
.portfolio__filter-other.is-active { color: var(--color-accent); font-weight: 600; }
.portfolio__filter-other.is-active .portfolio__filter-caret,
.portfolio__filter-other.is-active:hover .portfolio__filter-caret {
    transform: rotate(-135deg) translateY(-1px);
}

/* Others dropdown panel (Figma node 62:1270). Sits below the trigger.
   The parent .portfolio__filters carries z-index:10 so this whole
   subtree paints above the grid; nothing extra is needed here. */
.portfolio__filter-panel {
    position: absolute;
    top: calc(100% + 14px);
    left: 0;
    min-width: 280px;
    background: #f3f3f3;
    box-shadow: 0 18px 36px -12px rgba(0, 0, 0, 0.22),
                0 6px 14px -4px rgba(0, 0, 0, 0.12);
    padding: 8px 0;
    display: flex;
    flex-direction: column;
}
.portfolio__filter-panel[hidden] { display: none; }
.portfolio__filter-panel-item {
    background: none;
    border: 0;
    padding: 12px 24px;
    font-family: inherit;
    font-size: 14px; /* v2.11.85 — samakan dgn OUR WORK (was 16px) */
    font-weight: 400;
    color: var(--color-border);
    text-align: left;
    cursor: pointer;
    line-height: 1.4;
    white-space: nowrap;
    transition: background-color .15s ease, color .15s ease;
}
.portfolio__filter-panel-item:hover {
    background-color: rgba(21, 102, 224, 0.06);
    color: var(--color-accent);
}
.portfolio__filter-panel-item.is-active {
    color: var(--color-accent);
    font-weight: 600;
}

.portfolio__grid {
    display: grid;
    /* v2.11.33 — APPROVED fluid fix (user re-confirmed). Was fixed
       `repeat(3, 376.667px)` (needs 1200px); at a ~1280px effective viewport
       the ~17px Windows scrollbar left <1200px content, so the 3rd column
       clipped on the right ("mepet"). The 2-col breakpoint only kicks in at
       ≤1240px, so this band overflowed. Fluid 1fr tracks shrink to fit; at
       ≥1280px content is 1200px → each track is 376.667px, pixel-identical. */
    grid-template-columns: repeat(3, 1fr);
    column-gap: 35px;
    row-gap: 60px;
    align-items: start;
}

.portfolio__card { display: flex; flex-direction: column; transition: opacity .35s ease, transform .35s ease; }
/* Filter: drop the card from the grid entirely so visible cards reflow
   into the staggered position-based heights below. */
.portfolio__card.is-hidden { display: none; }

.portfolio__thumb {
    display: block;
    overflow: hidden;
    width: 100%; /* v2.11.33 — fill the fluid grid track (was 376.667px fixed → clipped at ~1280px). 100% == 376.667px at the design width. */
    background: #eee;
    position: relative;
}

/* Staggered Figma heights bound to GRID POSITION (not to a specific item),
   counting only visible cards. Result: whatever the filter shows, col 1
   is medium, col 2 is tall, col 3 is short — same rhythm every time. */
.portfolio__card:nth-child(3n+1 of .portfolio__card:not(.is-hidden)) .portfolio__thumb { height: 340px; }
.portfolio__card:nth-child(3n+2 of .portfolio__card:not(.is-hidden)) .portfolio__thumb { height: 396.667px; }
.portfolio__card:nth-child(3n+3 of .portfolio__card:not(.is-hidden)) .portfolio__thumb { height: 280px; }
.portfolio__thumb-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    transition: opacity .35s ease, transform .5s ease;
}
.portfolio__thumb-img--rest  { opacity: 1; }
.portfolio__thumb-img--hover { opacity: 0; }
.portfolio__thumb:hover .portfolio__thumb-img--hover { opacity: 1; }
.portfolio__thumb:hover .portfolio__thumb-img--rest  { opacity: 0; }
.portfolio__thumb:hover .portfolio__thumb-img        { transform: scale(1.04); }

.portfolio__info { padding-top: 18px; }
.portfolio__title {
    font-weight: 500;
    font-size: 18px; /* v2.12.113 — user paste (was 14px) */
    color: #000;
    display: block;
    margin-bottom: 8px;
    line-height: 1.3;
}
.portfolio__title:hover { color: var(--color-accent); }

.portfolio__sub {
    font-size: 16px; /* v2.12.113 — user paste (was 14px) */
    color: rgba(35, 31, 32, 0.65);
    margin: 0 0 16px;
    font-weight: 500;
    line-height: 1.4;
}

.portfolio__tags {
    list-style: none;
    display: flex;
    gap: 6px;
    align-items: center;
    margin: 0;
    padding: 0;
    color: var(--color-accent);
    font-size: 16px; /* v2.12.113 — user paste (was 14px) */
    font-weight: 500;
    flex-wrap: wrap;
}
.portfolio__tag-sep {
    width: 2.63px;
    height: 2.63px;
    background: var(--color-accent);
    border-radius: 50%;
    display: inline-block;
}

.portfolio__view-all {
    display: flex;
    justify-content: center;
    margin-top: 20px;
}

/* =======================================================
   ABOUT — Figma node 22:982
   ======================================================= */
.about {
    position: relative;
    padding: 100px 0;
    background: #ffffff;
    /* No overflow:hidden — ::before extends past .site-main's 1280px to reach
       viewport edges, and overflow:hidden would clip it back inside. */
}
/* Pastel multi-blob wash — Figma node 39:270. Extends past the 1280px
   .site-main container via negative left/right (50% - 50vw) so the
   gradient reaches the viewport edges on wide PC monitors instead of
   getting clipped at the canvas boundary. Inside the .about section
   itself the radials still use `closest-side` sizing so blobs never
   touch the section's top/bottom edges. */
.about::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(50% - 50vw);
    right: calc(50% - 50vw);
    /* DESKTOP = the original 4-blob pastel wash (Figma 39:270; opacity already −25%
       from v2.12.21). v2.12.24 — mobile swaps this for a left-concentrated gradient
       (see the @media (max-width:768px) override below). */
    background:
        radial-gradient(circle closest-side at 80% 32%, rgba(74, 222, 128, 0.41), transparent 100%),
        radial-gradient(circle closest-side at 82% 70%, rgba(96, 165, 250, 0.45), transparent 100%),
        radial-gradient(circle closest-side at 55% 50%, rgba(167, 139, 250, 0.21), transparent 100%),
        radial-gradient(circle closest-side at 18% 75%, rgba(236, 72, 153, 0.23), transparent 100%);
    pointer-events: none;
    z-index: 0;
}
.about > * { position: relative; z-index: 1; }
/* v2.12.24 — MOBILE ONLY: swap the 4 desktop blobs for the unified Figma gradient
   (about-glow.webp), concentrated on the LEFT and faded to white toward the right and
   bottom via a radial mask, so it dissolves smoothly into the clients/FAQ below
   (no hard cut) and the right side stays white. Desktop keeps the blobs above. */
@media (max-width: 768px) {
    .about::before {
        background: url('https://superpixel.sg/wp-content/uploads/2026/06/about-glow.webp') left center / cover no-repeat;
        -webkit-mask-image: radial-gradient(115% 125% at 0% 36%, #000 26%, transparent 72%);
        mask-image: radial-gradient(115% 125% at 0% 36%, #000 26%, transparent 72%);
        opacity: 0.55;
    }
}
.about__inner {
    position: relative;
    z-index: 1;
    display: grid;
    /* Text column flexes to fill remaining space so the gallery hugs the
       right edge — was `546.423px 545.625px` which left ~86px of dead
       space inside the content area to the right of the gallery. */
    grid-template-columns: 1fr 545.625px;
    gap: 50px;
    /* Match canvas-width of sections above/below (portfolio is full 1280)
       so .about doesn't read as a narrower island. box-sizing:border-box
       so padding is INCLUDED in width — without it, 1228 + 80 padding =
       1308 outer, which overflowed the 1280 viewport. */
    box-sizing: border-box;
    width: 100%;
    max-width: 1280px;
    margin: 0 auto;
    padding: 0 40px;
    align-items: center; /* feedback — photo gallery middle-aligns (vertically centered) with the text column */
}
.about__title {
    font-size: 52px;
    font-weight: 500;
    line-height: 1.15;
    margin: 0 0 30px;
    letter-spacing: -0.01em;
    width: 546.423px;
    max-width: 100%;
}
.about__title em {
    color: var(--color-accent);
    font-weight: 600;
    font-style: italic;
}

/* Headline reveal — three phrases stagger up word-block by word-block,
   matching the testimonials / FAQ reveal language. */
.about__title-line {
    /* feedback H1 — each phrase on its OWN line (was inline-block, so the three
       phrases flowed inline and wrapped unevenly = "baris gak rata"). Matches
       the Figma: Visual Strategy. / Crafted Stories. / Powerful Experiences. */
    display: block;
    line-height: inherit;
}
.about__title-line + .about__title-line { margin-left: 0; }
.about__body {
    width: 474.667px;
    max-width: 100%;
    margin-bottom: 24px;
}
.about__body p {
    font-size: 18px;
    line-height: 1.5;
    margin: 0 0 14px;
}
.about__body strong { font-weight: 600; }

/* feedback H2 (Figma 345:2289) — "3 Telly Awards" trophy block under the body. */
.about__award {
    display: flex;
    align-items: center;
    gap: 22px;
    margin: 4px 0 24px;
}
.about__award-caption strong { display: block; font-size: 16px; font-weight: 700; color: var(--color-text); }
.about__award-caption span   { display: block; font-size: 16px; color: var(--color-text); }
.about__award-medals {
    display: flex;
    align-items: center;
    gap: 14px;
}
.about__award-medals img { height: 64px; width: auto; display: block; }
.about__award-sep {
    width: 1px;
    height: 48px;
    background: rgba(35, 31, 32, 0.22);
    display: inline-block;
}

/* Photo grid — 2x2 of 262x262 squares; images cover (matches Figma masks) */
.about__gallery {
    position: relative;
    display: grid;
    grid-template-columns: 262px 262px;
    grid-template-rows: 262px 262px;
    column-gap: 20.13px;
    row-gap: 20px;
    width: 545.625px;
    max-width: 100%;
}
.about__photo {
    position: relative;
    width: 262px;
    height: 262px;
    overflow: hidden;
    background: #eee;
}
.about__photo img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}
.about__slider {
    grid-column: 2;
    margin-top: 12px;
    width: 64.579px;
    height: 4.225px;
    justify-self: end;
}
.about__slider img { width: 100%; height: 100%; }

/* =======================================================
   CLIENTS LOGO MARQUEE — Figma node 74:216
   Seamless infinite scroll: track holds 2× logos,
   translates by -50% over one cycle.
   ======================================================= */
.clients {
    position: relative;
    z-index: 2;
    padding: 48px 0;
    background: transparent;
    overflow: hidden;
    /* Break out of .site-main's 1280px max-width so the marquee spans
       the full viewport on wide PC monitors. Inner track auto-flows. */
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
}
.clients__marquee {
    width: 100%;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 8%, #000 92%, transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 8%, #000 92%, transparent 100%);
}
.clients__track {
    display: flex;
    align-items: center;
    gap: 72px;
    width: max-content;
    animation: clients-scroll 60s linear infinite;
    will-change: transform;
}
/* hover-pause only with a real pointer — on touch, taps make :hover stick and freeze the marquee */
@media (hover: hover) and (pointer: fine) {
    .clients__track:hover { animation-play-state: paused; }
}
.clients__logo {
    /* feedback — every client logo sits in the SAME 145×50 box (object-fit:contain
       centres + scales each mark to fit), so logos with small/odd source dimensions
       no longer look smaller than the rest. Shared by homepage + services sliders. */
    width: 145px;
    height: 50px;
    object-fit: contain;
    flex: 0 0 auto;
    /* feedback — was filter:brightness(0), which turned brand logos that have a
       solid coloured container with reversed text (Moment Factory white card,
       FOX oval, Simmons pill, SGX/CIMB/RLB boxes) into solid BLACK boxes — they
       read as "blank". Grayscale keeps every logo legible + uniform; hover
       restores the brand colour. */
    filter: grayscale(1);
    opacity: 0.65;
    transition: opacity .3s ease, filter .3s ease;
}
.clients__logo:hover { opacity: 1; filter: grayscale(0); }
@keyframes clients-scroll {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(-50%, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .clients__track { animation: none; }
}

/* =======================================================
   FAQ — Figma node 22:930
   ======================================================= */
.faq {
    /* v2.11.82 — box-sizing is OFF globally (content-box), so width:100% +
       58.67px side padding made the section 1200+117px wide and the right FAQ
       column got clipped on anything narrower than ~1317px. border-box keeps the
       content box at 1200-117=1083px = exactly the two 508px cols + 66.66 gap. */
    box-sizing: border-box;
    position: relative;
    z-index: 2;
    width: 100%;
    max-width: 1200px;
    margin: 60px auto 0;
    padding: 30px 58.67px;
    background: #ffffff;
}
.faq__eyebrow {
    font-size: 14.659px;
    font-weight: 500;
    margin: 0;
    line-height: 1;
}
.faq__title {
    font-size: 44px;
    font-weight: 500;
    margin: 5.32px 0 76px;
    line-height: 1.1;
    letter-spacing: -0.01em;
}
.faq__grid {
    display: grid;
    grid-template-columns: 508px 508px;
    column-gap: 66.66px;
}
.faq__col {
    display: flex;
    flex-direction: column;
    gap: 13.942px;
    align-items: start;
}
.faq__item { width: 508px; max-width: 100%; }
.faq__q {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    background: none;
    border: 0;
    padding: 0;
    width: 100%;
    cursor: pointer;
    font-size: 16px; /* feedback — all FAQ question text 16px */
    font-weight: 500;
    text-align: left;
    color: #000;
    font-family: inherit;
    line-height: 1;
    min-height: 16.377px;
    transition: color .25s ease;
}
.faq__item:hover .faq__q,
.faq__item.is-open .faq__q { color: #1566e0; }
.faq__q:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 4px; }
.faq__q-text { flex: 1; }

/* v2.12.159 — draw the "+" as an SVG MASK filled with currentColor instead of
   two CSS pseudo-bars. The 1.5px pseudo-bars anti-aliased inconsistently at 1×
   (the horizontal landed on sub-pixel Y per item → some rendered ~2px = "too
   thick"). A vector mask renders a crisp, THIN, uniform cross at every position
   & DPI, still tinted by currentColor (blue on hover) and rotated 45°→× on open. */
.faq__icon {
    position: relative;
    width: 12.57px;
    height: 12.57px;
    flex-shrink: 0;
    display: inline-block;
    background-color: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Crect x='6.35' y='1' width='1.3' height='12' rx='0.65'/%3E%3Crect x='1' y='6.35' width='12' height='1.3' rx='0.65'/%3E%3C/svg%3E") center / contain no-repeat;
            mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Crect x='6.35' y='1' width='1.3' height='12' rx='0.65'/%3E%3Crect x='1' y='6.35' width='12' height='1.3' rx='0.65'/%3E%3C/svg%3E") center / contain no-repeat;
    transition: transform .35s cubic-bezier(.2,.7,.2,1);
}
.faq__item.is-open .faq__icon { transform: rotate(45deg); }

.faq__panel {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows .4s cubic-bezier(.2,.7,.2,1);
    overflow: hidden;
}
.faq__panel > .faq__a {
    min-height: 0;
    margin: 0;
    padding-top: 0;
    opacity: 0;
    transition: opacity .25s ease, padding-top .4s cubic-bezier(.2,.7,.2,1);
    font-size: 16px; /* feedback — all FAQ answer text 16px */
    line-height: 1.6;
    color: rgba(0, 0, 0, 0.72);
    width: 460px;
    max-width: 100%;
}
.faq__a p { margin: 0 0 0.8em; }
.faq__a p:last-child { margin-bottom: 0; }
/* feedback H3 — "Click here" in the last FAQ opens the quote pop-up. */
.faq__cta-link {
    color: var(--color-accent);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}
.faq__cta-link:hover { color: var(--color-primary); }
.faq__a ol { margin: 0.4em 0 0.8em; padding-left: 20px; }
.faq__a ol li { margin-bottom: 0.35em; }
/* v2.11.54 — FAQ opens/closes on CLICK only (toggle .is-open via JS), no
   longer on :hover. Hover-open made it impossible to close by clicking the
   question (desktop kept it open while hovered; touch kept a sticky :hover).
   Now clicking the question toggles it open AND closed, desktop + mobile. */
.faq__item.is-open .faq__panel { grid-template-rows: 1fr; }
.faq__item.is-open .faq__panel > .faq__a {
    opacity: 1;
    padding-top: 14px;
    transition-delay: .1s;
}
.faq__divider {
    display: block;
    width: 100%;
    height: 1px;
    margin: 13.4px 0 0;
    border: 0;
    background: #d9d9d9;
    pointer-events: none;
}

/* v2.11.83 — homepage + services FAQ adopt the AI Lab FAQ "settings" (the look,
   not the content): one full-width column with full-width divider lines + 24px
   row padding, instead of the old compact 2-column grid. Markup, content and the
   click-accordion JS are unchanged. The AI page keeps its own .ai-faq. */
.faq__grid {
    grid-template-columns: 1fr;          /* single column */
    column-gap: 0;
    border-top: 1px solid rgba(35, 31, 32, 0.18);
}
.faq__col { gap: 0; align-items: stretch; }
.faq__item {
    width: 100%;
    max-width: none;
    border-bottom: 1px solid rgba(35, 31, 32, 0.18);
}
.faq__q { padding: 24px 0; min-height: 0; line-height: 1.4; }
.faq__q-text { padding-right: 24px; }
.faq__icon { width: 14px; height: 14px; }
.faq__divider { display: none; }          /* replaced by the per-item border-bottom */
.faq__panel > .faq__a { width: auto; max-width: 880px; }
.faq__item.is-open .faq__panel > .faq__a { padding-top: 0; padding-bottom: 24px; }

/* v2.12.25 — DESKTOP (≥1025px) ONLY: restore the ORIGINAL 2-column FAQ + hover-to-open
   ("efek hover"). v2.11.83 made it single-column and v2.11.54 made it click-only,
   site-wide; the user wants the desktop FAQ back as it was. Tablet (769–1024) keeps the
   single column; the mobile pass (≤768) is untouched. */
@media (min-width: 1025px) {
    .faq__grid { grid-template-columns: 1fr 1fr; column-gap: 66.66px; border-top: 0; }
    .faq__col { gap: 13.942px; align-items: start; }
    .faq__item { width: 100%; max-width: none; border-bottom: 0; }
    .faq__q { padding: 0; line-height: 1; }
    .faq__q-text { padding-right: 0; }
    .faq__divider { display: block; }
    /* hover opens the answer again (the JS click-toggle still works too). */
    .faq__item:hover .faq__panel { grid-template-rows: 1fr; }
    .faq__item:hover .faq__panel > .faq__a { opacity: 1; padding-top: 14px; padding-bottom: 0; }
}

/* =======================================================
   TESTIMONIALS — Figma node 22:834
   ======================================================= */
.testimonials {
    position: relative;
    height: 670.667px;
    margin-top: 80px;
    /* v2.7.0 — gradient now also fades grey → white at the BOTTOM so the
       transition into the next section (about-why on /about/, CTA on /)
       reads as a soft wash instead of a hard #eee → #fff line. */
    background: linear-gradient(
        to bottom,
        #ffffff 0%,
        #eeeeee 90px,
        #eeeeee calc(100% - 120px),
        #ffffff 100%
    );
    overflow: hidden;
    padding: 20.67px 0 0;
    /* Break out of .site-main's 1280px max-width so the grey wash + blue
       glow span the full viewport on wide PC monitors. */
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
}
/* Soft blue glow — Figma node 39:411. Centered ellipse sized to exactly
   match the section dims (50% radius from a 50% center = touches edges
   at 100% transparent). Spreads wide but fades to nothing at every
   border, so there's no hard cut into FAQ above or CTA below. */
.testimonials::before {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse 50% 50% at 50% 50%, rgba(99, 154, 255, 0.55), transparent 100%);
    pointer-events: none;
    z-index: 0;
}
.testimonials > * { position: relative; z-index: 1; }
.testimonials__head { position: relative; z-index: 2; }
.testimonials__eyebrow {
    text-align: center;
    font-size: 14px; /* v2.11.85 — samakan dgn OUR WORK */
    font-weight: 500;
    margin: 0 0 12px;
    line-height: 1;
}
.testimonials__title {
    text-align: center;
    font-size: 44px;
    font-weight: 400;
    margin: 0 0 50px;
    line-height: 1.1;
    letter-spacing: -0.01em;
}
.testimonials__title em { color: var(--color-accent); font-style: italic; font-weight: 600; }

.testimonials__viewport {
    position: relative;
    width: 100%;
    /* clip horizontally so the marquee doesn't bleed past the section,
       but let the vertical axis stay visible so a hover-lifted card's
       shadow isn't cut off at the bottom edge. */
    overflow-x: clip;
    overflow-y: visible;
    padding: 0 0 50px;
    z-index: 1;
}
.testimonials__track {
    display: flex;
    gap: 26.667px;
    padding: 0 0 0 40px;
    width: max-content;
    animation: testimonials-loop 70s linear infinite;
    will-change: transform;
    /* v2.12.117 — draggable: JS drives the marquee + click-drag-to-scrub. */
    cursor: grab;
    touch-action: pan-y;
    user-select: none;
}
.testimonials__track.is-dragging { cursor: grabbing; }
/* while dragging, suppress the per-card hover lift so cards under the moving
   cursor don't jitter/scale mid-drag. */
.testimonials__track.is-dragging .testimonial:hover { transform: none; box-shadow: none; }
/* v2.11.20 — pause-on-hover only on devices with a REAL hover (mouse/trackpad).
   On touch, a tap made :hover stick → the marquee froze ("stuck") until the
   user tapped elsewhere. Touch now never pauses via hover. */
@media (hover: hover) and (pointer: fine) {
    .testimonials__track:hover { animation-play-state: paused; }
}
.testimonials.is-paused .testimonials__track { animation-play-state: paused; }

/* v2.4.38 — rest zone removed per user request; all cards now share the
   same uniform 26.667px gap so the marquee scrolls as one continuous
   stream with no break. */

@keyframes testimonials-loop {
    /* Cycle = one full set + one inter-set gap so the 7th card lands
       exactly where the 1st was = seamless loop.
       6 cards (1912.002) + 5 within-gaps (133.335) + 1 flex gap (26.667)
       = 2072.004px. */
    from { transform: translateX(0); }
    to   { transform: translateX(-2072.004px); }
}

/* Card frame fixed at exact Figma size — Swiper-style lift on hover */
.testimonial {
    position: relative;
    flex: 0 0 318.667px;
    width: 318.667px;
    /* v2.9.77 — frame taller (was 350.667) to fit the bumped 17px quote text.
       WIDTH is unchanged on purpose: the marquee keyframe distance below is
       hardcoded off the card width, so changing width would break the loop. */
    height: 500px;
    background: #fff;
    scroll-snap-align: start;
    box-shadow: 0 4px 14px rgba(20, 30, 60, 0.06);
    /* v2.12.54 — solid BLACK arrow cursor over review cards. The native default
       arrow is white-filled with a thin outline, so on the white card it nearly
       disappears ("nyatu sama bg putih"). A custom black SVG arrow stays visible.
       Card design/size untouched — this only swaps the pointer. */
    cursor: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M2%202%20L2%2018%20L6%2014.5%20L9%2021%20L11%2020.2%20L8%2013.7%20L13.5%2013.7%20Z'%20fill='%23000'%20stroke='%23fff'%20stroke-width='1.2'%20stroke-linejoin='round'/%3E%3C/svg%3E") 2 2, default;
    transition: transform .35s cubic-bezier(.2,.7,.2,1),
                box-shadow .35s cubic-bezier(.2,.7,.2,1);
    z-index: 1;
}
/* v2.12.53 — lift ("popup") only on real-hover devices (desktop, mouse/trackpad).
   On touch there is no sticky :hover; the popup is driven by an explicit
   .is-popped tap class (see the mobile block) so it can be dismissed cleanly. */
@media (hover: hover) and (pointer: fine) {
    .testimonial:hover {
        transform: translateY(-8px) scale(1.035);
        box-shadow: 0 22px 44px -12px rgba(21, 102, 224, 0.28),
                    0 10px 22px -6px rgba(0, 0, 0, 0.18);
        z-index: 3;
    }
}
.testimonial__mark {
    position: absolute;
    top: 31.33px;
    left: 36px;
    width: 24.667px;
    height: 55.333px;
    color: var(--color-accent);
    font-size: 73.333px;
    line-height: 1;
    margin: 0;
    font-weight: 400;
}
.testimonial__quote {
    position: absolute;
    top: 62px;
    left: 38.67px;
    width: 223.333px;
    height: 350px;
    font-size: 17px;
    line-height: 1.8;
    color: #000;
    margin: 0;
    font-weight: 400;
}
.testimonial__rate {
    position: absolute;
    top: 450px;
    left: 220px;
    display: flex;
    align-items: center;
    gap: 4.42px;
}
.testimonial__rate img {
    width: 8.538px;
    height: 8.538px;
    object-fit: contain;
    display: block;
}
.testimonial__logo {
    position: absolute;
    left: 36px;
    overflow: hidden;
    display: block;
}
.testimonial__logo img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

/* =======================================================
   CTA — Figma node 22:1076
   Shares the soft grey wash with testimonials so they read as
   one continuous backdrop (Figma BG node 22:831, 1312.667px tall).
   ======================================================= */
.cta {
    position: relative;
    display: grid;
    grid-template-columns: minmax(384px, 1fr) 1fr;
    gap: 60px;
    align-items: center;
    /* v2.11.26 — was 12.5% (viewport-relative) which pushed the content far
       inside the 1280 canvas (~960px wide, more inset than every other
       section). Use the standard 40px so the CTA content edges line up with
       Selected Work / About / footer. The grey ::before still goes full-bleed. */
    padding: 80px 40px 100px;
    background: transparent;
    z-index: 0;
}
/* Grey #eeeeee wash extends past the 1280px container to viewport edges
   without affecting CTA's grid/padding (content stays in 1280 design). */
.cta::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(50% - 50vw);
    right: calc(50% - 50vw);
    /* v2.12.156 — fade the grey wash to WHITE at the very bottom so the CTA melts
       into the white footer instead of meeting it with a hard grey/white seam.
       Blends on every page that ends with this team CTA (home / about / blog +
       portfolios listings). Solid grey up top stays continuous with the
       testimonials wash above; the ~110px fade lands in the CTA's 100px bottom
       padding (empty), so no content is washed out. */
    background: linear-gradient(to bottom,
        #eeeeee 0,
        #eeeeee calc(100% - 110px),
        #ffffff 100%);
    z-index: -1;
    pointer-events: none;
}
.cta > * { position: relative; z-index: 1; }

.cta__portraits {
    display: grid;
    grid-template-columns: repeat(2, 180px);
    grid-template-rows: repeat(2, 219.333px);
    gap: 16px;
    justify-content: start;
    align-content: center;
}
.cta__portrait {
    position: relative;
    overflow: hidden;
    background: #000;
    width: 180px;
    height: 219.333px;
}
/* v2.6.75 — idle/hover served as pre-graded image pair (270x329 source
   pre-framed to the 180x219.333 frame ratio). Idle image is the desat
   grayscale grade; hover image is the full-color grade. Cross-fade
   between them on hover.
   v2.7.73 — slow zoom-OUT on hover (base 1.08 → 1.0) per Session 12
   framing rule (scale ≥ 1.0 always). Opacity + transform durations
   synced so the two layers move as one — no more "glitch" feel. */
.cta__portrait-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center 25%;
    /* Only the ZOOM animates. translateZ(0) + backface-visibility keep the
       single visible photo crisp during the scale (no compositing blur). */
    transform: translateZ(0) scale(1.06);
    transition: transform .6s cubic-bezier(.2,.7,.2,1);
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}
/* v2.9.76 — the persistent ghosting ("berbayang") was the cross-FADE itself:
   while the idle (desaturated) and hover (graded) photos blended at partial
   opacity, you saw two different faces at once. Fix: NO opacity transition —
   the idle→hover swap is INSTANT. The idle photo stays solid underneath and
   the hover photo simply snaps on top, so at every single frame exactly ONE
   photo is visible while it zooms = clean, never doubled. */
.cta__portrait-img--hover { opacity: 0; }
.cta__portrait:hover .cta__portrait-img--hover { opacity: 1; }
.cta__portrait:hover .cta__portrait-img { transform: translateZ(0) scale(1); }

/* Soft black scrim under every portrait — guarantees the white name +
   country labels stay readable regardless of what's behind them. */
.cta__portrait::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 70px;
    background: linear-gradient(to top, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0));
    pointer-events: none;
    z-index: 1;
}

.cta__portrait-name {
    position: absolute;
    left: 16px;
    bottom: 14px;
    color: #fff;
    line-height: 1.3;
    z-index: 2;
}
.cta__portrait-name strong {
    display: block;
    font-size: 14px;
    font-weight: 500;
    text-transform: capitalize;
}
.cta__portrait-name span {
    display: block;
    font-size: 12px;
    color: var(--color-muted-2);
    text-transform: capitalize;
    margin-top: 2px;
}

.cta__content { max-width: 471.333px; }
.cta__title {
    font-size: 44px;
    font-weight: 500;
    line-height: 1.3;
    margin: 0 0 20px;
    letter-spacing: -0.01em;
}
.cta__title em {
    color: var(--color-accent);
    font-weight: 600;
    font-style: italic;
    display: block;
}
.cta__body {
    font-size: 21.667px;
    line-height: 1.5;
    margin: 0 0 24px;
    width: 372.667px;
    max-width: 100%;
}
/* Get a Quote + tagline sit on one row, 35px apart — same pattern as
   the navbar CTA cluster. */
.cta__cta-row {
    display: inline-flex;
    align-items: center;
    gap: 35px;
}
.cta__note {
    font-size: 17px;
    color: var(--color-muted-2);
    white-space: nowrap;
    letter-spacing: 0.2px;
}

/* =======================================================
   FOOTER — Figma node 22:1098 (1280 × 460.667)
   Absolute Figma layout 1:1; own white base + subtle vector
   + top-right rainbow blur so it doesn't merge with grey CTA.
   ======================================================= */
.site-footer {
    position: relative;
    z-index: 5;
    background: #ffffff;
    /* v2.7.5 — taller so logo + copyright sit further below the
       addresses block per user request. */
    height: 560px;

    /* =====================================================
       v2.7.25 — BOTTOM-ROW GAP CONTROLS (5 components)
       Edit these to tune spacing of the bottom row:
         [Logo]  …  [©2026…]  …  [Privacy | ToS | Proposal]
       1. Logo is anchored from viewport LEFT (left value)
       2. ©2026 right edge from viewport RIGHT (right value)
       3. Privacy/ToS/Proposal right edge from viewport RIGHT
       4. Gap BETWEEN the 3 legal items (via flex gap)

       Visual gap math (right-anchored items):
         gap(©2026 → Privacy) = copy-right − legal-right − legal-text-width
         gap(Logo → ©2026) = viewport_width − logo-left − logo-width
                              − (copy-right + copy-text-width)
       So Logo↔©2026 grows with viewport width (variable).
       The other 3 gaps are fixed regardless of viewport.
       ===================================================== */
    --spx-footer-logo-left:   140px; /* Logo distance from viewport LEFT  */
    --spx-footer-copy-right:  380px; /* ©2026 right edge from viewport RIGHT */
    --spx-footer-legal-right:  80px; /* Privacy/ToS/Proposal right edge   */
    --spx-footer-bottom:       64px; /* Distance from footer's BOTTOM edge */
    --spx-legal-gap:           10px; /* Space between Privacy | ToS | Proposal */
    /* No overflow:hidden — __bg layer needs to escape the 1280px container
       so the rainbow + vector reach viewport edges on wide PC monitors.
       __bg has its own overflow:hidden that clips its children. */
    isolation: isolate;
    border-top: 1px solid rgba(0, 0, 0, 0.04);
}
.site-footer__bg {
    position: absolute;
    /* Extend bg layer past the footer's 1280px max-width to viewport edges. */
    top: 0;
    bottom: 0;
    left: calc(50% - 50vw);
    right: calc(50% - 50vw);
    /* v2.11.26 — was a FIXED 557.333px, ~3px short of the 560px footer so the
       graded bg stopped before the bottom edge. Fill the whole footer. */
    height: 100%;
    overflow: hidden;
    pointer-events: none;
    z-index: 0;
}
/* v2.7.75 — vector + rainbow gradient layers replaced by a single
   pre-graded WebP background (BG-FOOTER_compressed.webp). One image
   covers the full footer at viewport-edge width. */
.site-footer__bg-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
}

.site-footer__nav,
.site-footer__social,
.site-footer__addresses,
.site-footer__brand,
.site-footer__copy,
.site-footer__legal { position: absolute; z-index: 1; }

.site-footer__nav { left: 140px; top: 55.33px; }
.site-footer__nav ul {
    list-style: none;
    padding: 0; margin: 0;
    font-size: 18px;
    line-height: 2.5;
    color: #000;
}
.site-footer__nav a {
    color: inherit;
    text-decoration: none;
    transition: color .2s ease, transform .2s ease;
    display: inline-block;
}
.site-footer__nav a:hover { color: var(--color-primary); transform: translateX(3px); }

/* Footer "Services" — text-only dropdown, same hover behaviour as the header
   mega-menu (no thumbnails). Opens below the label on hover/focus. */
.site-footer__nav-sub { position: relative; }
.site-footer__nav-trigger {
    display: inline-flex; align-items: center; gap: 7px; cursor: pointer; color: inherit;
    transition: color .2s ease, transform .2s ease;
    -webkit-user-select: none; user-select: none;
}
.site-footer__nav-sub:hover .site-footer__nav-trigger,
.site-footer__nav-trigger:hover,
.site-footer__nav-trigger:focus-visible { color: var(--color-primary); transform: translateX(3px); }
.site-footer__nav-caret {
    /* feedback — chevron stroke (outline), not a filled triangle. */
    width: 9px; height: 9px; position: relative;
    transition: transform .25s cubic-bezier(.2,.7,.2,1);
}
.site-footer__nav-caret::before {
    content: ""; position: absolute; left: 50%; top: 40%;
    width: 6px; height: 6px;
    border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
    transform: translate(-50%, -50%) rotate(45deg);
}
.site-footer__nav-sub:hover .site-footer__nav-caret,
.site-footer__nav-sub:focus-within .site-footer__nav-caret { transform: rotate(180deg); }
.site-footer__subnav {
    list-style: none; margin: 0; padding: 8px 0; line-height: 1.4;
    position: absolute; left: 0; top: calc(100% - 8px); min-width: 220px;
    background: #ffffff; border-radius: 12px;
    box-shadow: 0 18px 40px rgba(20, 30, 60, 0.14), 0 2px 6px rgba(20, 30, 60, 0.08);
    opacity: 0; visibility: hidden; transform: translateY(8px); pointer-events: none;
    transition: opacity .2s ease, transform .25s cubic-bezier(.2,.7,.2,1), visibility .25s;
    z-index: 6;
}
.site-footer__nav-sub:hover .site-footer__subnav,
.site-footer__nav-sub:focus-within .site-footer__subnav {
    opacity: 1; visibility: visible; transform: translateY(0); pointer-events: auto;
}
.site-footer__subnav li { margin: 0; }
.site-footer__subnav a {
    display: block; padding: 7px 18px; font-size: 15px; line-height: 1.4;
    color: #231f20; white-space: nowrap; transform: none;
}
.site-footer__subnav a:hover { color: var(--color-primary); transform: translateX(3px); }

/* feedback — even, airier spacing between the social icons (was absolute-positioned
   with uneven gaps). Flex row + fixed gap, like the nav rhythm above it. */
.site-footer__social { left: 140px; top: 341px; width: auto; height: 32px; display: flex; align-items: center; gap: 30px; } /* feedback — gap matches the nav line-height rhythm (18px × 2.5 = 45px) */

/* Default state: dimmed at 70% opacity for a refined, understated look.
   Hover: soft circular backdrop expands behind the icon, the icon
   itself scales up with an elastic ease, and a brand-coloured drop
   shadow blooms underneath. Each platform gets its own brand colour. */
.site-footer__social-icon {
    position: relative; /* feedback — flex child now, not absolutely placed */
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    opacity: 0.7;
    transform-origin: center;
    transition:
        transform .45s cubic-bezier(.34, 1.56, .64, 1),
        opacity .25s ease,
        filter .35s ease;
}
.site-footer__social-icon::before {
    content: "";
    position: absolute;
    inset: -10px;
    background: rgba(0, 0, 0, 0.05);
    border-radius: 50%;
    transform: scale(.5);
    opacity: 0;
    transition:
        transform .45s cubic-bezier(.34, 1.56, .64, 1),
        opacity .25s ease;
    z-index: -1;
}
.site-footer__social-icon img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
    position: relative;
    z-index: 1;
}
.site-footer__social-icon:hover {
    opacity: 1;
    transform: scale(1.18) translateY(-2px);
}
.site-footer__social-icon:hover::before {
    transform: scale(1);
    opacity: 1;
}
.site-footer__social-icon:focus-visible {
    outline: none;
    opacity: 1;
}
.site-footer__social-icon:focus-visible::before {
    transform: scale(1);
    opacity: 1;
    background: rgba(21, 102, 224, 0.15);
}

/* Per-platform brand-colour glow on hover */
.site-footer__social-icon--instagram:hover { filter: drop-shadow(0 6px 14px rgba(225, 48, 108, 0.45)); }
.site-footer__social-icon--linkedin:hover  { filter: drop-shadow(0 6px 14px rgba(0, 119, 181, 0.45)); }
.site-footer__social-icon--youtube:hover   { filter: drop-shadow(0 6px 14px rgba(255, 0, 0, 0.40));  }
.site-footer__social-icon--tiktok:hover    { filter: drop-shadow(0 6px 14px rgba(37, 244, 238, 0.45)); }

.site-footer__social-icon--instagram { width: 22px;     height: 21.333px; }
.site-footer__social-icon--linkedin  { width: 20.667px; height: 19.333px; }
.site-footer__social-icon--youtube   { width: 26px;     height: 16.667px; }
/* v2.12.155 — TikTok was 31.333×30.667 (Figma exported the glyph in a padded box)
   → rendered ~30.7px tall vs ~17–21px for the others, so it looked oversized on
   desktop. Match Instagram's height (21.333) at the SVG's real viewBox aspect
   (19.3/21.2 = 0.910) so it sits the same size as the rest, no distortion. */
.site-footer__social-icon--tiktok    { width: 19.417px; height: 21.333px; }

/* v2.6.108 — addresses shifted RIGHT (right:80 from viewport edge)
   so the block hugs the right side of the footer. 14px font + 3-line
   JK (Indonesia on its own line) kept from v2.6.107. Cols 280px each
   are wide enough for the longest line at 14px Figtree. */
/* v2.7.10 — back toward the right edge so SINGAPORE label lines up
   with the @2026 left edge under it.
   v2.7.19 — nudged further right (80 → 50) per user blue-line guide;
   was still ~25-30px to the LEFT of the © symbol. */
.site-footer__addresses { right: 50px; top: 64px; width: 600px; height: 320px; }
.site-footer__office { position: absolute; color: #000; }
.site-footer__office h3 {
    margin: 0 0 16px;
    /* v2.7.0 — address bumped above copy/legal per user request. */
    font-size: 18px;
    font-weight: 700;
    text-transform: uppercase;
    line-height: 1.2;
}
.site-footer__office p {
    margin: 0;
    /* v2.7.0 — address body bumped above copy/legal. */
    font-size: 16px;
    font-weight: 400;
    line-height: 1.5;
}
.site-footer__office--sg { left: 0;   top: 0;   width: 280px; }
.site-footer__office--mb { left: 320px; top: 0;   width: 280px; }
.site-footer__office--vc { left: 0;   top: 165px; width: 280px; }
.site-footer__office--jk { left: 320px; top: 165px; width: 280px; }

/* Country-title hotspot */
.site-footer__office-link {
    color: inherit;
    text-decoration: none;
    position: relative;
    display: inline-block;
    transition: color .25s ease;
}
.site-footer__office-link::after {
    content: "";
    position: absolute;
    left: 0; right: 0;
    bottom: -2px;
    height: 1px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .3s cubic-bezier(.2,.7,.2,1);
}
.site-footer__office-link:hover { color: var(--color-primary); }
.site-footer__office-link:hover::after { transform: scaleX(1); }

.site-footer__office p a { color: inherit; transition: color .25s ease; }
.site-footer__office p a:hover { color: var(--color-primary); }

/* v2.6.105 — anchored to LEFT not RIGHT now that the footer is
   full-vw. With `right:921` the logo drifted toward the centre on
   wider viewports — fixed left position keeps it where Figma
   intended (near the nav column). */
.site-footer__brand {
    bottom: 54px;
    left: 135px;
    right: auto;
    width: 218.667px;
    height: 42px;
}
.site-footer__brand img { width: 100%; height: 100%; object-fit: contain; display: block; }
/* Bottom-row wrapper (logo + copyright + legal). display:contents keeps the
   desktop absolute layout AND the ≤768 mobile stack exactly as before; only
   the 769–1240 tablet band (below) turns it into a real flex row. */
.site-footer__bottom { display: contents; }

/* v2.6.106 — copy/legal anchored to the RIGHT edge of the full-vw
   footer so they don't drift away from the rightmost addresses on
   wider monitors. Legal lines up with the addresses' right gutter
   (124px), copy sits ~350px left of that. */
.site-footer__copy, .site-footer__legal {
    bottom: var(--spx-footer-bottom);
    margin: 0;
    font-size: 12.5px;
    line-height: 1.4;
    color: #000;
    white-space: nowrap;
}
.site-footer__legal {
    display: inline-flex;
    align-items: center;
    gap: var(--spx-legal-gap);
}
.site-footer__legal-sep {
    color: rgba(0, 0, 0, 0.45);
    user-select: none;
}
.site-footer__copy {
    right: 400px;
    left: auto;
}
.site-footer__legal { right: var(--spx-footer-legal-right); left: auto; }

/* =======================================================
   RESPONSIVE
   ======================================================= */
@media (max-width: 1280px) {
    .site-main, .site-footer { max-width: 100%; }
}

@media (max-width: 600px) {
    /* v2.12.6 — +10% (62→68, 51→56), text 10→11, and dropped lower (72→24) so it
       hugs the bottom edge and stops covering mid-screen content. */
    .floating-quote { width: 68px; height: 56px; bottom: 24px; }
    .floating-quote__text { font-size: 11px; }
}

@media (max-width: 1240px) {
    .portfolio__grid { grid-template-columns: repeat(2, 1fr); }
    .portfolio__card .portfolio__thumb {
        width: 100%;
        height: auto !important;
        aspect-ratio: 565/420;
    }
    .portfolio__filters { gap: 24px; }
    /* Tablet: keep the dropdown anchored to the trigger but cap width so
       it doesn't overflow when sitting near the right edge. */
    .portfolio__filter-panel { max-width: calc(100vw - 80px); }
    .about__inner { grid-template-columns: 1fr; gap: 40px; }
    .about__title { font-size: 42px; }
    .about__gallery {
        grid-template-columns: 1fr 1fr;
        grid-template-rows: auto auto;
        width: 100%;
    }
    .about__photo { width: 100%; height: auto; aspect-ratio: 1; }
    /* v2.12.6 — gap 24→0: the two stacked .faq__col were separated by 24px,
       creating an odd larger gap after the last item of the left column (item 4).
       Zero gap makes every row divider identical. */
    .faq__grid { grid-template-columns: 1fr; gap: 0; }
    .cta { grid-template-columns: 1fr; padding: 60px 40px; }
    .cta__portraits { justify-content: center; }

    /* Footer collapses out of the absolute Figma layout into a stack */
    .site-footer {
        height: auto;
        padding: 50px 40px 30px;
        display: flex;
        flex-direction: column;
        gap: 40px;
    }
    .site-footer__nav,
    .site-footer__social,
    .site-footer__addresses,
    .site-footer__brand,
    .site-footer__copy,
    .site-footer__legal { position: static; }
    .site-footer__nav    { order: 1; }
    .site-footer__social { order: 2; width: auto; height: auto; display: flex; gap: 30px; margin-top: -23px; } /* feedback — match nav rhythm (was 22px) */
    .site-footer__social-icon { position: static; transform: none !important; }
    /* v2.6.103 — at tablet/narrow viewports stack offices in 1 col
       (was 2 col grid which crammed JK's long address into 3 lines).
       Each office gets full container width so address fits in 1 line
       → consistent 4-line read across all viewports. */
    .site-footer__addresses {
        order: 3;
        width: 100%;
        height: auto;
        display: grid;
        grid-template-columns: 1fr;
        gap: 30px;
    }
    .site-footer__office { position: static; width: 100%; }
    .site-footer__brand  { order: 4; margin: 0 auto; }
    .site-footer__copy,
    .site-footer__legal  { order: 5; text-align: center; }
}

/* v2.12.138 — TABLET (769–1240) footer bottom row like DESKTOP: logo LEFT,
   copyright + legal grouped on the RIGHT, one baseline (feedback: "samain kaya
   desktop logo footer dan termsnya"). The ≤1240 block above had centred the
   logo; phones (≤768) keep the Figma left-stack. The wrapper is display:contents
   elsewhere, so this only reshapes the tablet band. */
@media (min-width: 769px) and (max-width: 1240px) {
    /* v2.12.141 — the footer has an explicit width:100% + 40px side padding but
       global box-sizing is content-box, so its border-box = viewport + 80px →
       an 80px horizontal overflow (blank strip you can scroll to on the right,
       visible in dev-mode). Include the padding in the width on tablet. Desktop
       & mobile untouched (they keep their own — already html{overflow-x:clip}'d). */
    .site-footer { box-sizing: border-box; }
    .site-footer__bottom {
        display: flex;
        align-items: center;
        flex-wrap: wrap;
        gap: 12px 28px;
        width: 100%;
        order: 5;
    }
    /* margin-right:auto pushes the logo left and floats ©/legal to the right. */
    .site-footer__bottom .site-footer__brand { margin: 0 auto 0 0; align-self: center; }
    .site-footer__bottom .site-footer__copy,
    .site-footer__bottom .site-footer__legal { text-align: left; }
}

@media (max-width: 768px) {
    body { padding-top: 64px; }
    .site-header { height: 64px; }
    .navbar { padding: 0 20px; }
    .navbar__links { display: none; }
    /* Tagline gets cramped beside the button on phone widths — hide it. */
    .navbar__cta { gap: 0; }
    .navbar__cta-tag { display: none; }
    .hero__title { font-size: 32px; width: 100%; }
    .hero__copy { width: 100%; padding: 0 24px; margin: 0 auto; }
    .hero__banner { width: calc(100% - 48px); margin: 30px auto 0; }
    .portfolio { padding: 0 24px; }
    .portfolio__filters { gap: 16px; }
    .portfolio__filter,
    .portfolio__filter-other { font-size: 14px; }
    .portfolio__filter-panel-item { font-size: 14px; padding: 10px 18px; }
    /* v2.11.79 — On phones the "Others" trigger sits mid-row; the panel is
       anchored to that trigger, so opening it leftward (old right:0) ran it off
       the left edge (cropped, unclickable). main.js positions it fixed + centred
       in the viewport on open (see positionOthersPanel). This is just the safe
       CSS fallback: open RIGHTWARD from the trigger so it's never left-cropped. */
    .portfolio__filter-panel {
        left: 0;
        right: auto;
        top: calc(100% + 12px);
        min-width: 0;
        width: max-content;
        max-width: calc(100vw - 32px);
    }
    .portfolio__grid { grid-template-columns: 1fr; }
    .portfolio__thumb { width: 100%; }
    .about { padding: 60px 0; }
    .about__title { font-size: 32px; }
    .about__body p { font-size: 16px; }
    .faq { padding: 30px 24px; }
    .faq__title,
    .ai-faq__title { font-size: 32px; } /* feedback — AI Lab FAQ title matches homepage at mobile too */
    .testimonials { height: auto; padding-bottom: 30px; }
    .testimonial { flex: 0 0 85vw; }
    .cta__title { font-size: 32px; }
    .cta__body { font-size: 19px; }
    .cta__portraits {
        grid-template-columns: 1fr 1fr;
        grid-template-rows: 200px 200px;
        gap: 12px;
    }
    .cta__portrait { width: 100%; height: 100%; }
    .site-footer__addresses { grid-template-columns: 1fr; }
}

/* =========================================================
   ABOUT PAGE — v2.6.111
   Sections: about-hero / about-work / about-made / about-why
   Reuses .testimonials and .cta from the front page.
   v2.6.111: all accent colour switched from orange (--color-primary)
   to blue (--color-accent #1566e0). The orange brand colour stays for
   buttons + global UI; about page uses blue for hierarchy.
   ========================================================= */
.site-main--about { padding-top: 0; }

/* ----- 1. HERO ----------------------------------------- */
.about-hero {
    padding: clamp(80px, 12vh, 160px) 0 clamp(60px, 10vh, 120px);
    text-align: left;
}
.about-hero__inner {
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 clamp(24px, 5vw, 80px);
}
.about-hero__eyebrow {
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-accent);
    margin: 0 0 24px;
}
.about-hero__title {
    font-size: clamp(48px, 7vw, 108px);
    font-weight: 500;
    line-height: 1.05;
    letter-spacing: -0.02em;
    margin: 0 0 28px;
    color: #000;
}
.about-hero__title em {
    font-style: italic;
    font-weight: 500;
    color: var(--color-accent);
}
.about-hero__lede {
    font-size: clamp(17px, 1.3vw, 22px);
    line-height: 1.55;
    color: var(--color-muted);
    margin: 0;
    max-width: 760px;
}

/* ----- 1.5 PEOPLE & CULTURE MARQUEE -------------------- */
/* Horizontal infinite scroll of studio photos. Track holds 2 sets of
   13 photos; CSS animation translates -50% to seamlessly loop. Photos
   are rendered at 16:9 with object-fit: cover (center-cropped from
   their native size). Section breaks out of the 1280px canvas to span
   the viewport edges. */
.about-marquee {
    /* break out of .site-main cap so the strip spans full viewport */
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    padding: clamp(20px, 3vh, 50px) 0 clamp(40px, 6vh, 80px);
    overflow: hidden;
    background: #fff;
}
.about-marquee__viewport {
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 5%, #000 95%, transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 5%, #000 95%, transparent 100%);
}
.about-marquee__track {
    display: flex;
    align-items: center;
    gap: clamp(16px, 1.6vw, 28px);
    width: max-content;
    animation: about-marquee-scroll 80s linear infinite;
    will-change: transform;
}
@media (hover: hover) and (pointer: fine) {
    .about-marquee__track:hover { animation-play-state: paused; }
}
.about-marquee__item {
    flex: 0 0 auto;
    width: clamp(340px, 32vw, 560px);
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: 0;
    background: #eee;
}
.about-marquee__item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center center;
    display: block;
}
@keyframes about-marquee-scroll {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(-50%, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .about-marquee__track { animation: none; }
}

/* ----- 2. HOW WE WORK ---------------------------------- */
.about-work { padding: clamp(80px, 12vh, 150px) 0; }
.about-work__inner {
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 clamp(24px, 5vw, 80px);
    display: grid;
    grid-template-columns: 380px 1fr;
    gap: clamp(40px, 6vw, 96px);
    align-items: start;
}
.about-work__head { position: sticky; top: 120px; }
.about-work__eyebrow {
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-accent);
    margin: 0 0 18px;
}
.about-work__title {
    font-size: clamp(36px, 4vw, 56px);
    font-weight: 500;
    line-height: 1.1;
    letter-spacing: -0.01em;
    margin: 0 0 20px;
    color: #000;
}
.about-work__title em { font-style: italic; color: var(--color-accent); font-weight: 500; }
.about-work__intro { font-size: 17px; line-height: 1.55; color: var(--color-muted); margin: 0; }
.about-work__steps { list-style: none; margin: 0; padding: 0; counter-reset: work; }
.about-work__step {
    display: grid;
    grid-template-columns: 88px 1fr;
    gap: 24px;
    padding: 32px 0;
    border-top: 1px solid rgba(0, 0, 0, 0.12);
    align-items: start;
}
.about-work__step:first-child { border-top: 0; padding-top: 0; }
.about-work__num {
    font-family: var(--font-sans);
    font-size: 40px;
    font-weight: 600;
    color: var(--color-accent);
    line-height: 1;
    letter-spacing: -0.02em;
}
.about-work__step-title {
    font-size: 24px;
    font-weight: 600;
    line-height: 1.2;
    margin: 0 0 10px;
    color: #000;
}
.about-work__step-text {
    font-size: 16px;
    line-height: 1.6;
    color: var(--color-muted);
    margin: 0;
}
/* v2.7.1 — image lives INSIDE step-body so the original sticky-head
   stop-scroll layout is preserved. Sits above the h3 in the body col. */
.about-work__step-image {
    border-radius: 0;
    overflow: hidden;
    aspect-ratio: 16 / 10;
    background: #f1f1f1;
    margin-bottom: 22px;
}
.about-work__step-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    /* v2.9.88 — match the homepage zoom-OUT: photo sits slightly zoomed and
       un-zooms to 1.0 on hover (was a zoom-IN to 1.04). Same .6s curve. */
    transform: translateZ(0) scale(1.06);
    transition: transform .6s cubic-bezier(.2,.7,.2,1);
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}
.about-work__step:hover .about-work__step-image img { transform: translateZ(0) scale(1); }

/* ----- 3. WHAT WE'VE MADE ------------------------------ */
.about-made { padding: clamp(80px, 12vh, 150px) 0; background: #fafafa; }
.about-made__inner {
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 clamp(24px, 5vw, 80px);
}
/* v2.7.4 — wider gap below the section header so "What We've Made"
   stays comfortably readable above the slider card. */
.about-made__head { margin-bottom: clamp(64px, 8vw, 110px); max-width: 720px; }
.about-made__eyebrow {
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-accent);
    margin: 0 0 18px;
}
.about-made__title {
    font-size: clamp(36px, 4vw, 56px);
    font-weight: 500;
    line-height: 1.1;
    letter-spacing: -0.01em;
    margin: 0;
    color: #000;
}
.about-made__title em { font-style: italic; color: var(--color-accent); font-weight: 500; }
/* v2.7.0 — slider format. The list is a horizontal scroll-snap track,
   each project is a full-width slide with an image + text block. */
.about-made__slider { position: relative; }
.about-made__list {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 100%;
    gap: 0;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
}
.about-made__list::-webkit-scrollbar { display: none; }
.about-made__project {
    scroll-snap-align: start;
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: clamp(28px, 4vw, 56px);
    padding: clamp(28px, 3.4vw, 48px);
    border-radius: 24px;
    background: #fff;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.04);
    align-items: center;
}
.about-made__project-media {
    border-radius: 0;
    overflow: hidden;
    aspect-ratio: 4 / 3;
    background: #eee;
}
.about-made__project-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.about-made__project-text { min-width: 0; }
.about-made__project-head {
    display: flex;
    align-items: baseline;
    gap: 24px;
    margin-bottom: 20px;
}
.about-made__project-num {
    font-size: 18px;
    font-weight: 600;
    color: var(--color-accent);
    letter-spacing: 0.1em;
}
.about-made__project-name {
    font-size: clamp(22px, 2.2vw, 30px);
    font-weight: 600;
    line-height: 1.15;
    margin: 0;
    color: #000;
}
.about-made__project-body {
    font-size: 16px;
    line-height: 1.6;
    color: var(--color-muted);
    margin: 0 0 28px;
}
.about-made__project-body em { color: #000; font-style: italic; font-weight: 500; }
.about-made__stats {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
    padding-top: 24px;
    border-top: 1px solid rgba(0, 0, 0, 0.08);
}
.about-made__stat { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.about-made__stat-num {
    font-size: clamp(24px, 2.6vw, 36px);
    font-weight: 600;
    line-height: 1;
    color: var(--color-accent);
    letter-spacing: -0.02em;
}
.about-made__stat-label {
    font-size: 13px;
    line-height: 1.4;
    color: var(--color-muted);
}

.about-made__cta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 22px;
    padding: 9px 18px;
    background: var(--color-primary);
    color: #fff;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    text-decoration: none;
    transition: background .25s ease, transform .25s ease, box-shadow .25s ease;
}
.about-made__cta:hover {
    background: #c93b00;
    box-shadow: 0 10px 22px rgba(235, 71, 0, 0.26);
}
.about-made__cta:hover .about-made__cta-arrow { transform: translateX(4px); }
.about-made__cta-arrow {
    width: 14px;
    height: auto;
    transition: transform .25s ease;
    flex-shrink: 0;
}

/* Slider controls — sit centered below the track.
   v2.7.4 — pushed further down + smaller arrows per user request. */
.about-made__controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 18px;
    margin-top: 64px;
}
.about-made__arrow {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 1px solid rgba(0, 0, 0, 0.18);
    background: #fff;
    color: #000;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color .2s ease, border-color .2s ease, transform .2s ease;
}
.about-made__arrow:hover { background: #000; color: #fff; border-color: #000; }
.about-made__arrow:disabled { opacity: 0.35; cursor: default; }
.about-made__arrow:disabled:hover { background: #fff; color: #000; border-color: rgba(0, 0, 0, 0.18); }
.about-made__dots {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    gap: 10px;
}
.about-made__dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    border: 0;
    background: rgba(0, 0, 0, 0.22);
    cursor: pointer;
    padding: 0;
    transition: background-color .2s ease, transform .2s ease;
}
.about-made__dot.is-active {
    background: var(--color-accent);
    transform: scale(1.2);
}

@media (max-width: 880px) {
    .about-made__project {
        grid-template-columns: 1fr;
        gap: 24px;
    }
    .about-made__project-media { aspect-ratio: 16 / 9; }
    .about-made__stats { grid-template-columns: 1fr; gap: 14px; }
}

/* ----- 5. WHY SUPERPIXEL ------------------------------- */
.about-why {
    padding: clamp(95px, 8vh, 100px) 0;
    background: #fff;
    position: relative;
    z-index: 1;
}
.about-why__inner {
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 clamp(24px, 5vw, 80px);
}
.about-why__head { text-align: center; margin-bottom: clamp(24px, 3vw, 40px); max-width: 760px; margin-left: auto; margin-right: auto; }
.about-why__eyebrow {
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--color-accent);
    margin: 0 0 18px;
}
.about-why__title {
    font-size: clamp(36px, 4vw, 56px);
    font-weight: 500;
    line-height: 1.1;
    letter-spacing: -0.01em;
    margin: 0 0 20px;
    color: #000;
}
.about-why__title em { font-style: italic; color: var(--color-accent); font-weight: 500; }
.about-why__intro { font-size: 17px; line-height: 1.55; color: var(--color-muted); margin: 0; }
/* v2.7.33 — capability grid: pills stay anchored on a fixed 4-col grid
   so the click target never moves under the cursor (UX rule: don't
   chase the user). The thumbnail floats absolutely ABOVE the pill, so
   it can grow large without reflowing the row or pushing the pill
   itself down. Reserved top padding on the grid is the room the thumb
   lives in. */
.about-why__grid {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    padding-top: clamp(40px, 5vw, 70px);
}
.about-why__item {
    position: relative;
    overflow: visible;
}
.about-why__link {
    position: relative;
    display: block;
    text-decoration: none;
    color: inherit;
}
.about-why__thumb {
    position: absolute;
    left: 50%;
    bottom: calc(100% + 14px);
    width: clamp(280px, 30vw, 440px);
    aspect-ratio: 16 / 10;
    overflow: hidden;
    border-radius: 0;
    background: #111;
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.22);
    opacity: 0;
    transform: translateX(-50%) scale(0.55);
    transform-origin: center bottom;
    pointer-events: none;
    transition: opacity .35s ease,
                transform .55s cubic-bezier(.22,.61,.36,1);
    z-index: 5;
}
.about-why__thumb img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.about-why__item:hover .about-why__thumb,
.about-why__item:focus-within .about-why__thumb {
    opacity: 1;
    transform: translateX(-50%) scale(1);
}
.about-why__label {
    display: block;
    padding: 22px 28px;
    background: #fff;
    border: 1px solid rgba(0, 0, 0, 0.12);
    border-radius: 999px;
    font-size: 16px;
    font-weight: 500;
    line-height: 1.2;
    color: #000;
    text-align: center;
    transform-origin: center center;
    transition: color .25s ease,
                border-color .25s ease,
                background .25s ease,
                transform .35s cubic-bezier(.22,.61,.36,1),
                opacity .35s ease;
}
.about-why__item:hover .about-why__label,
.about-why__item:focus-within .about-why__label {
    border-color: var(--color-accent);
}
/* When ANY pill is hovered, all OTHER pills shrink + fade so the
   hovered one feels dominant. Hovered pill itself stays exactly in
   place (no transform) — click target must not move. */
.about-why__grid:hover .about-why__item:not(:hover) .about-why__label,
.about-why__grid:focus-within .about-why__item:not(:focus-within) .about-why__label {
    transform: scale(0.86);
    opacity: 0.45;
}
@media (hover: none) {
    .about-why__thumb { display: none; }
    .about-why__grid { padding-top: 0; }
}

/* ----- 6. CTA modifier --------------------------------- */
.cta--about .cta__content { margin: 0 auto; }

/* ----- Responsive -------------------------------------- */
@media (max-width: 900px) {
    .about-work__inner { grid-template-columns: 1fr; gap: 40px; }
    .about-work__head { position: static; }
    .about-work__step { grid-template-columns: 56px 1fr; gap: 16px; padding: 24px 0; }
    .about-work__num { font-size: 28px; }
    .about-work__step-title { font-size: 20px; }
    .about-made__stats { grid-template-columns: 1fr; gap: 16px; }
    .about-why__grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 700px) {
    /* v2.12.18 — gap above the capability tiles −50% (was clamp(160,45vw,280); the big
       reserve is for the hover-thumbnail, which is hidden on touch anyway).
       v2.12.110 — the hover-thumbnail is hidden on mobile, so drop the big reserve to
       8px → text→first tile gap = head margin-bottom 24 + 8 = 32px (matches the
       homepage FAQ gaps the user standardised on). */
    .about-why__grid { grid-template-columns: repeat(2, 1fr); padding-top: 8px; }
    .about-why__thumb { width: clamp(220px, 52vw, 340px); }
}
@media (max-width: 600px) {
    .about-hero { padding: 60px 0 50px; }
    /* v2.12.67 — lede matched to portfolio/blog body: 16px + GET A QUOTE right margin (L24 → 103). */
    .about-hero__lede { font-size: 16px; max-width: calc(100vw - 64px); }
    .about-why__grid { grid-template-columns: 1fr; }
    .about-made__project { padding: 28px 20px; border-radius: 16px; }
}

/* =========================================================
   SINGLE PORTFOLIO — /work/<slug>/  (Figma 96:956)
   ========================================================= */
.work-single {
    position: relative;
    max-width: 1280px;
    margin: 0 auto;
    padding: clamp(24px, 5vw, 40px) clamp(20px, 5vw, 40px) clamp(60px, 8vw, 100px);
}
.work-single__accent {
    position: absolute;
    top: -120px;
    left: 50%;
    transform: translateX(-50%);
    width: min(1200px, 95vw);
    height: 560px;
    background: radial-gradient(ellipse 50% 50% at 50% 50%, rgba(99, 154, 255, 0.18), transparent 70%);
    filter: blur(40px);
    opacity: 0.65;
    pointer-events: none;
    z-index: -1;
}
.work-single__head { margin: clamp(20px, 4vw, 48px) 0 clamp(24px, 3vw, 40px); }
.work-single__year {
    font-size: 15px;
    color: var(--color-text);
    margin: 0 0 14px;
}
.work-single__title {
    font-size: clamp(40px, 6vw, 67px);
    font-weight: 400;
    line-height: 1.08;
    letter-spacing: -0.01em;
    margin: 0;
    color: #000;
    max-width: 920px;
}
.work-single__sub {
    font-size: clamp(17px, 1.6vw, 21px);
    font-weight: 500;
    color: rgba(35, 31, 32, 0.65);
    margin: 16px 0 0;
}

/* ---- Hero with play button → YouTube/Vimeo iframe swap ---- */
.work-single__hero {
    position: relative;
    aspect-ratio: 1200 / 614;
    border-radius: 0;
    overflow: hidden;
    background: #e9e9e9;
}
.work-single__hero-img,
.work-single__hero-iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border: 0;
    display: block;
}
.work-single__play {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: clamp(64px, 7vw, 100px);
    height: clamp(64px, 7vw, 100px);
    border-radius: 50%;
    border: 0;
    background: rgba(255, 255, 255, 0.92);
    cursor: pointer;
    display: grid;
    place-items: center;
    transition: transform .25s ease, background .25s ease;
    z-index: 2;
}
.work-single__play:hover { transform: translate(-50%, -50%) scale(1.06); background: #fff; }
.work-single__play-icon {
    width: 0; height: 0;
    border-style: solid;
    border-width: 13px 0 13px 22px;
    border-color: transparent transparent transparent var(--color-primary);
    margin-left: 5px;
}

/* ---- Section blocks (Overview, Gallery) ---- */
.work-single__section { margin-top: clamp(48px, 6vw, 90px); }
.work-single__h {
    font-size: 26px;
    font-weight: 600;
    line-height: 1.5;
    margin: 0 0 clamp(16px, 2vw, 28px);
    color: #000;
}
.work-single__overview {
    max-width: 720px;
    margin-left: auto;
    font-size: 14.667px;
    line-height: 1.5;
    color: #000;
}
.work-single__overview p { margin: 0 0 1em; }
.work-single__overview a { color: var(--color-accent); }

.work-single__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: clamp(10px, 1.2vw, 18px);
}
.work-single__grid-item {
    display: block;
    aspect-ratio: 16 / 10;
    overflow: hidden;
    border-radius: 0;
    background: #d9d9d9;
}
.work-single__grid-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform .5s cubic-bezier(.2,.7,.2,1);
}
.work-single__grid-item:hover img { transform: scale(1.05); }

.work-single__back { margin-top: clamp(48px, 6vw, 80px); }

@media (max-width: 700px) {
    .work-single__overview { margin-left: 0; }
    .work-single__grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}

/* =======================================================
   MOBILE HEADER + FULL-SCREEN MENU (Figma 266:1656 / 266:1667)
   ======================================================= */
.navbar__mobile { display: none; align-items: center; gap: 16px; }
.navbar__mq {
    background: none; border: 0; padding: 0; cursor: pointer; font-family: inherit;
    color: var(--color-primary); font-size: 16px; font-weight: 600; letter-spacing: .04em; /* +4 (was 12) */
    text-transform: uppercase; white-space: nowrap;
}
.navbar__burger {
    background: none; border: 0; padding: 4px 0; cursor: pointer; width: 28px;
    display: inline-flex; flex-direction: column; gap: 6px;
}
.navbar__burger span { display: block; height: 2px; width: 28px; background: var(--color-text); border-radius: 2px; }

.mobile-menu {
    /* v2.11.25 — top/left/right + min-height:100dvh instead of inset:0 so the
       overlay always covers the DYNAMIC viewport. With inset:0 the menu sized
       to the small (URL-bar-visible) layout viewport; scrolling the menu hid
       the URL bar, grew the viewport, and the page footer peeked at the bottom. */
    position: fixed; top: 0; left: 0; right: 0; z-index: 2000;
    /* v2.11.90 — glassmorphism: transparent + backdrop blur (was solid #ededed)
       so the page shows through, blurred. Fallback solid for no-backdrop browsers. */
    background: rgba(237, 237, 237, 0.72);
    -webkit-backdrop-filter: saturate(140%) blur(22px);
    backdrop-filter: saturate(140%) blur(22px);
    min-height: 100vh; min-height: 100dvh;
    /* v2.11.90 — header padding match (0 20px) so the logo + GET A QUOTE don't
       jump position when the menu opens over the header. */
    display: flex; flex-direction: column; padding: 0 20px 28px;
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    /* v2.11.90 — fade transition (JS toggles .is-open; see openMenu/closeMenu). */
    opacity: 0; transition: opacity .3s ease;
}
.mobile-menu.is-open { opacity: 1; }
.mobile-menu[hidden] { display: none; }
/* Bar matches the real header (64px tall, same logo size) → seamless swap. */
.mobile-menu__bar { display: flex; align-items: center; gap: 14px; height: 64px; flex: 0 0 auto; }
.mobile-menu__logo { display: inline-flex; }
/* v2.12.6 — match the closed header logo EXACTLY (.navbar__logo img is height:22px,
   width auto → ~112px) so the SPX logo doesn't visibly shrink when the menu opens. */
.mobile-menu__logo img { height: 22px; width: auto; display: block; }
.mobile-menu__mq { margin-left: auto; }
.mobile-menu__close {
    background: none; border: 0; padding: 0; cursor: pointer; font-size: 30px; line-height: 1;
    color: var(--color-text); width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center;
}
.mobile-menu__nav { display: flex; flex-direction: column; margin-top: 80px; }
.mobile-menu__nav a {
    font-size: 28px; font-weight: 400; color: var(--color-text); text-decoration: none;
    line-height: 1; padding: 15px 0;
}
.mobile-menu__nav a:active { color: var(--color-accent); }
/* v2.11.20 — expandable Portfolios/Services sub-lists in the mobile menu */
.mobile-menu__row { display: flex; align-items: center; }
.mobile-menu__row a { flex: 1 1 auto; }
.mobile-menu__toggle {
    background: none; border: 0; padding: 10px 4px; cursor: pointer;
    color: var(--color-text); display: inline-flex; align-items: center; justify-content: center;
}
.mobile-menu__toggle svg { width: 22px; height: 22px; transition: transform .25s ease; }
.mobile-menu__group.is-open .mobile-menu__toggle svg { transform: rotate(180deg); }
.mobile-menu__sub { display: flex; flex-direction: column; padding: 2px 0 10px 18px; }
/* v2.11.25 — make the accordion actually collapse. The bare [hidden] UA rule
   (display:none) lost to .mobile-menu__sub{display:flex} (same specificity, later
   in cascade), so the Portfolios/Services sub-lists were ALWAYS open and the
   caret did nothing. This restores the JS toggle: collapsed by default, open on tap. */
.mobile-menu__sub[hidden] { display: none; }
.mobile-menu__sub a {
    font-size: 23px; font-weight: 400; color: #4a4a4a; text-decoration: none; /* v2.11.90 — bigger (was 19) */
    line-height: 1; padding: 12px 0;
}
.mobile-menu__sub a:active { color: var(--color-accent); }
.mobile-menu__quote {
    width: 241px; max-width: 100%; height: 48px; margin-top: 48px; border-radius: 0;
    font-size: 16px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
    display: inline-flex; align-items: center; justify-content: center;
}
/* v2.11.48 — social row sits ABOVE the Get a Quote button.
   v2.11.49 — fixed margin instead of margin-top:auto so the social + button sit
   right under the nav (auto pushed them to the very bottom = big empty gap and
   they fell below the fold). */
/* v2.12.124 — social row moved BELOW the Get a Quote button.
   v2.12.129 — was space-between full-width = gaps too wide; cluster the icons
   left with a fixed gap so the row only reaches ~the middle of the button. */
/* v2.12.158 — spread the icons across the SAME width as the Get-a-Quote button
   (241px) so the row's right edge lines up with the button end (per feedback),
   and enlarge them. space-between distributes the extra room evenly. */
.mobile-menu__social { display: flex; justify-content: space-between; align-items: center; width: 241px; max-width: 100%; margin-top: 22px; margin-bottom: 0; }
.mobile-menu__social a { display: inline-flex; align-items: center; opacity: .85; transition: opacity .2s ease; }
.mobile-menu__social a:hover { opacity: 1; }
/* v2.12.130 — each icon at its NATURAL Figma 266:1677 size (not forced into a 22×22
   square, which squished the wide YouTube + tall TikTok = the "stretch"). object-fit:
   contain guards against distortion. */
.mobile-menu__social img { object-fit: contain; display: block; }
/* v2.12.158 — enlarged ~1.4× (Figma 266:1677 proportions kept). TikTok uses
   preserveAspectRatio="meet" (fits INSIDE its box) while the others fill edge-to-edge
   (none), so at an equal box the note reads smaller — give it a slightly taller box
   so its glyph matches the others' visual size. */
.mobile-menu__social img[src*="instagram"] { width: 31px; height: 30px; }
.mobile-menu__social img[src*="linkedin"]  { width: 29px; height: 27px; }
.mobile-menu__social img[src*="youtube"]   { width: 36px; height: 23px; }
.mobile-menu__social img[src*="tiktok"]    { width: 31px; height: 34px; } /* meet-fit → box oversized so the note matches the others */

body.mobile-menu-open { overflow: hidden; }

/* v2.11.86 — TABLET + TOUCH: swap the hover-based desktop nav for the tap-based
   hamburger menu on phones, tablets, and ANY coarse-pointer (touch) device. This
   keeps the desktop-like content layout but makes the menu/mega-menu usable by
   finger (hover menus don't work on touch). `max-width:1024px` catches portrait
   tablets + narrow windows; `pointer:coarse` catches landscape tablets of any
   width. Real mouse/desktop (fine pointer, >1024) keeps the hover mega-menu. */
@media (max-width: 1024px), (pointer: coarse) {
    .navbar__menu { display: none; }
    .navbar__mobile { display: flex; }
    /* GET A QUOTE in the header is ALWAYS orange on touch — guards against any
       page-specific header state (showreel/dark/text-shadow) overriding it. */
    .navbar__mq, .mobile-menu__mq { color: var(--color-primary) !important; }
}
@media (min-width: 1025px) and (pointer: fine) {
    .mobile-menu { display: none !important; }
}

body.mobile-menu-open .floating-quote { display: none; }

/* v2.11.20 — testimonial review popup (touch devices). Tap a card in the
   marquee → an exact copy of that card opens centered over a dim backdrop;
   the marquee keeps running behind. */
.testimonial-modal { position: fixed; inset: 0; z-index: 2100; }
.testimonial-modal[hidden] { display: none; }
.testimonial-modal__backdrop { position: absolute; inset: 0; background: rgba(15, 17, 21, 0.62); }
.testimonial-modal__inner {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    max-width: calc(100vw - 32px); max-height: calc(100vh - 64px);
}
.testimonial-modal__slot { max-height: calc(100vh - 64px); overflow-y: auto; }
.testimonial-modal__close {
    position: absolute; right: -4px; top: -44px; z-index: 2;
    background: none; border: 0; cursor: pointer; padding: 4px;
    color: #fff; font-size: 34px; line-height: 1;
}
/* the cloned card: keep its exact look, just clamp to phone width and
   disable the marquee-hover lift */
.testimonial--modal {
    flex: none; max-width: calc(100vw - 32px);
    transform: none !important; transition: none;
}
body.testimonial-modal-open { overflow: hidden; }

/* Mobile header = clean solid-white bar (Figma) — kill the translucent bg + the
   over-video dark state + logo invert so nothing tints it (was showing blue from
   the hero behind the translucent header). */
@media (max-width: 768px) {
    .site-header,
    .site-header.is-over-showreel {
        background: #fff;
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }
    .site-header.is-over-showreel .navbar__logo img { filter: none; }
}

/* Mobile: kill any horizontal overflow so there's no empty space on the right;
   keep the floating FREE QUOTE as a fixed bottom-right overlay (same concept as
   desktop, just nudged off the edge a touch). */
@media (max-width: 768px) {
    html, body { overflow-x: hidden; max-width: 100%; width: 100%; }
    /* floating quote hugs the phone's right edge — true fixed overlay, never in flow */
    .floating-quote { right: 0; left: auto; }

    /* "How we work" scroll-stop head (AI How It Works + About How We Work):
       stays pinned with a white gradient bg so the numbered steps scroll cleanly
       behind it instead of overlapping the title/intro. */
    .ai-howit__head,
    .about-work__head {
        position: sticky;
        top: 64px;
        z-index: 6;
        background: linear-gradient(180deg, #fff 0%, #fff 82%, rgba(255,255,255,0) 100%);
        padding-bottom: 22px;
    }

    /* footer glow/blur bg must run all the way to the bottom — no crop */
    .site-footer__bg { height: 100%; top: 0; bottom: 0; }
}

/* ============ MOBILE HOMEPAGE — Figma 266:1362 ============ */
@media (max-width: 768px) {
    /* Selected Work: single-column FULL-WIDTH cards (Figma PORTFOLIO 266:1372).
       Base .portfolio__thumb is a FIXED 376.667px wide with fixed nth-child
       heights tied to the 3-col desktop grid — that overflowed the phone.
       Force responsive: 100% wide, 4:3 (Figma thumb = 317×235), heights cleared. */
    .portfolio { padding: 0 20px; }
    .portfolio__grid { grid-template-columns: 1fr !important; gap: 30px; justify-content: stretch; }
    .portfolio__thumb { width: 100% !important; height: auto !important; aspect-ratio: 317 / 235; }
    .portfolio__title { font-size: 14px; } /* v2.11.85 — match OUR WORK */
    .portfolio__sub { font-size: 12px; }
    .portfolio__tags { font-size: 12px; }

    /* About (Figma 266:1446): 2x2 SQUARE photo grid, capped ~150px & centred
       (user: make the photos smaller), heading + paragraph below. */
    /* v2.11.26 — 20px side inset to match Selected Work / portfolio page.
       .about__inner carries its own 40px base padding, so zero it here or the
       inset would double to 64px (.about 24 + inner 40). */
    .about { padding: 60px 20px; }
    .about__inner { padding-left: 0; padding-right: 0; }
    .about__title { font-size: 28px; }
    /* v2.11.21 — .about__body has a FIXED width:474.667px; via grid min-width:auto
       it blew the 1fr track wider than the phone → body text clipped right and the
       gallery pushed right off-screen ("space di kiri"). Cap everything to the track. */
    .about__inner > * { min-width: 0; }
    .about__text { max-width: 100%; }
    .about__body { width: 100%; }
    .about__award { flex-wrap: wrap; gap: 14px 22px; }
    .about__award-medals img { height: 52px; }
    .about__gallery {
        grid-template-columns: repeat(2, minmax(0, 150px));
        grid-template-rows: auto auto;
        gap: 12px;
        width: auto;
        max-width: 100%;
        justify-content: center;
        margin: 0 auto;
    }
    .about__photo { width: 100%; height: auto; aspect-ratio: 1; }
    .about__body p { font-size: 15px; }

    /* CTA: team portraits 2x2 (Figma 266:1607) */
    /* v2.11.26 — 20px side inset to match the other sections (was 60px 40px). */
    .cta { padding: 60px 20px; }
    .cta__portraits { display: grid !important; grid-template-columns: 1fr 1fr; gap: 16px; justify-content: stretch; }
    .cta__portrait { width: 100%; }
    .cta__title { font-size: 30px; }
    .cta__body { font-size: 16px; }
}

/* ============ MOBILE HOMEPAGE — alignment consistency (v2.11.46) ============
   Staging review: Selected Work / FAQ / footer didn't line up with the rest.
   Matches Figma mobile (266:1362): every section shares one left gutter; the
   footer is FULLY left-aligned (Figma 266:1631 — logo/©/legal all at x≈0),
   not the desktop left-vs-right split; the filter row wraps instead of being
   clipped at the right edge. */
@media (max-width: 768px) {
    /* Selected Work filter row — wrap to multiple lines so the last items
       ("Branding & Product", "Others") are never cut off at the right edge.
       (Figma draws it as a horizontal-scroll row, but overflow on this
       container would clip the "Others" dropdown panel, so we wrap instead.) */
    .portfolio__filters {
        flex-wrap: wrap;
        width: 100%;
        max-width: 100%;
        row-gap: 12px;
        column-gap: 20px;
    }
    .portfolio__filter,
    .portfolio__filter-other { white-space: nowrap; }

    /* FAQ — 20px gutter to line up with Selected Work / About / CTA (was 24px).
       box-sizing:border-box is REQUIRED here: global border-box is disabled, so
       `width:100%` + padding was rendering viewport+40px wide → the section
       overflowed right, clipping the answer text and pushing the +/× toggle
       off-screen (un-tappable). border-box keeps it inside the viewport. */
    /* v2.12.35 — FAQ scaled down + pulled inward (more side gutter) per "kotak merah".
       v2.12.108 — top & bottom gap matched to the "VIEW ALL WORK → About photo" gap
       (measured 32px). Top = margin-top 20 + padding-top 12 = 32px. Bottom is the
       .home .testimonials margin-top (below) = 20 + this 12px padding-bottom = 32px. */
    .faq { box-sizing: border-box; padding: 12px 38px; margin-top: 20px; }
    /* FAQ → Testimonials gap (homepage only; testimonials margin-top is 80px and is
       shared with about/services, so scope to .home). */
    .home .testimonials { margin-top: 20px; }
    /* v2.12.109 — gap from "Questions we often get" title to the first question
       trimmed 76→32px (matching the section gaps). .faq is homepage-only. */
    .faq__title { margin-bottom: 32px; }
    /* The +/× toggle: the original empty-span icon (a flex child) collapsed to
       ~0 on mobile, so the thin pseudo-bars never showed. Replace it with a
       real "+" / "×" GLYPH drawn on the button's own ::after (the button always
       renders) — unmissable + a proper tap target. Hide the old span. */
    /* v2.12.15 — FAQ as a CENTRED block (max-width + auto margins = even L/R margins),
       but inside each row the question text is rata KIRI and the +/× toggles line up in
       ONE right-hand column (justify-content:space-between → all glyphs aligned). */
    /* v2.12.45 — FAQ smaller + more inward (don't hug the margin). */
    .faq__grid { max-width: 360px; margin-left: auto; margin-right: auto; }
    .faq__q {
        display: flex; align-items: center; justify-content: space-between; gap: 12px;
        padding: 9px 0; min-height: 0; position: relative; text-align: left;
    }
    /* v2.12.151 — unify the FAQ "+" across ALL breakpoints. Mobile used a 22px
       font "+/×" glyph (::after) instead of the drawn .faq__icon, so the symbol
       didn't match desktop/tablet. Keep the SAME drawn icon on mobile too (it
       rotates 45° to × on open) → one consistent symbol everywhere. */
    .faq__q-text { flex: 1 1 auto; max-width: none; padding-right: 0; }
    .faq__panel > .faq__a { text-align: left; }
    .faq__item.is-open .faq__panel > .faq__a { padding-bottom: 14px; }

    /* Footer — Figma 266:1631: everything LEFT-aligned at the 20px gutter.
       The desktop layout pins the logo near centre and floats ©/legal to the
       right edge; on mobile that read as "not aligned". Pull them all left. */
    .site-footer { padding: 50px 20px 36px; }
    .site-footer__brand { align-self: flex-start; margin: 0; left: auto; right: auto; }
    .site-footer__copy,
    .site-footer__legal {
        align-self: flex-start;
        text-align: left;
        left: auto;
        right: auto;
        white-space: normal;
    }
    .site-footer__legal { justify-content: flex-start; }

    /* Footer glow bg — the source WebP is 1280×780 (landscape); object-fit:cover
       on the tall, narrow phone footer cropped the sides so the glow only showed
       on the right and the LEFT read as blank ("crop di kiri"). The image is a
       very soft pastel gradient, so fill it to the footer dims → the whole glow
       (pink left-of-centre + blue right) spans the full width, no crop. */
    .site-footer__bg-img { object-fit: fill; }

    /* Testimonials heading — "Measurable Impact. Real Feedback." at 44px
       overflowed the right edge on phones (the .testimonials section is
       full-bleed 100vw with no side padding). Add a gutter + shrink so it
       wraps cleanly inside the viewport. */
    .testimonials__head { padding: 0 20px; }
    .testimonials__title { font-size: 30px; margin-bottom: 36px; }
    .testimonials__eyebrow { font-size: 13px; }
}

/* =========================================================
   v2.11.90 — MOBILE-VIEW REVISIONS (homepage). Placed last so it wins.
   ========================================================= */
@media (max-width: 768px) {
    /* Hero: eyebrow not so tight to the top; headline a touch smaller so it
       wraps to 3 lines; a bit more air above the buttons. */
    /* v2.11.97 — tighten headline spacing a bit (not as tight as the original). */
    /* v2.12.33 — home hero LEFT-aligned (was centred), tighter leading on the eyebrow +
       headline, and balanced copy spacing. */
    /* v2.12.55 — left edge = 20px so the eyebrow/headline/buttons line up exactly
       with the SuperPixel logo (20px) and the Selected Work carousel cards (20px). */
    .hero__copy { padding-top: 28px; text-align: left; align-items: flex-start; gap: 14px;
        width: 100%; max-width: none; margin: 0; box-sizing: border-box; padding-left: 20px; padding-right: 20px; }
    .hero__eyebrow { margin-bottom: 0; font-size: 13px; }
    .hero__title { font-size: 28px; line-height: 1.05; text-align: left; }
    .hero__actions { margin-top: 6px; justify-content: flex-start; }
    /* v2.12.40 — "OUR WORK" had 14px left padding, so it sat indented from the headline;
       drop it so its text lines up with the headline's left edge. */
    .hero__actions .hero__link { padding-left: 0; }
    /* v2.12.114 — desktop bumped hero__link + Start-a-Project btn to 16px (user paste);
       keep MOBILE at the previous 14px so the bump is desktop-only. */
    .hero__link { font-size: 14px; }
    .hero__actions .btn--primary { font-size: 14px; }

    /* Selected Work cards: 16:9 like the portfolio page (was 317/235). */
    .portfolio__thumb { aspect-ratio: 16 / 9 !important; height: auto !important; }
    /* v2.12.11 — gap carousel → portfolio −25% (80 → 60). */
    .portfolio { margin-top: 60px; }
    /* v2.12.11 — Selected Work card text +2pt (14 → 16; tags 14 → 15). */
    .portfolio__title, .portfolio__sub { font-size: 16px; }
    /* v2.12.55 — blue tags down 2pt (15→13) so longer sets (e.g. Pokémon) fit one line cleanly. */
    .portfolio__tags { font-size: 13px; }
    /* v2.12.30 — even gaps between the 3 card lines: sub→tags (was 16px) = title→sub (8px). */
    .portfolio__sub { margin-bottom: 8px; }
    /* v2.12.32 — tags ALWAYS one line (user: no 2-line tags). nowrap keeps them on a
       single row; overflow:hidden clips any extra-long set cleanly at the card edge. */
    .portfolio__tags { flex-wrap: nowrap; overflow: hidden; max-width: none; }

    /* VIEW ALL WORK = full width (matches thumbnail width). */
    .portfolio__view-all { display: block; }
    .portfolio__view-all .btn { width: 100%; box-sizing: border-box; }

    /* About: reorder to Photo → Title → text → Telly awards → CTA. */
    .about__gallery { order: -1; margin-bottom: 8px; }
    /* v2.12.33 — Learn More arrow vertically centred with the label via inline-flex
       (replaces the old translateY nudge that read slightly off). */
    .about__learn-more .hero__link { display: inline-flex; align-items: center; line-height: 1; }
    .about__learn-more .hero__link-arrow { font-size: 15px; transform: none; }
}

/* =========================================================
   v2.11.93 — MOBILE-VIEW REVISIONS round 2 (homepage). Placed last so it wins.
   ========================================================= */
@media (max-width: 768px) {
    /* Clients marquee: logos were huge (~1 on screen). Shrink so 4-5 fit. */
    .clients { padding: 26px 0; }
    .clients__track { gap: 26px; }
    .clients__logo { width: 64px; height: 26px; }

    /* FAQ: headline + body a touch smaller. */
    /* v2.12.35 — FAQ text scaled down. */
    /* v2.12.47 — headline kept at its original size (only the inner FAQ layout scales). */
    /* v2.12.48 — FAQ header: eyebrow thin+small, title medium, all left-aligned (mobile). */
    .faq__eyebrow { font-weight: 300; font-size: 13px; text-align: left; }
    .faq__title { font-size: 30px; font-weight: 500; text-align: left; }
    .faq__q { font-size: 16px; } /* feedback — Q text 16px on mobile (home + services) */
    .faq__panel > .faq__a { font-size: 16px; } /* feedback — A text 16px on mobile */

    /* Testimonials cards: smaller + RELATIVE internal layout so more than one
       shows. v2.12.6 — SWIPE: on phones the viewport is a native horizontal
       scroll-snap container (smooth touch swipe + momentum) and the auto-marquee
       is turned OFF (animation:none). The JS pointer-drag also early-returns on
       mobile so it doesn't fight native scroll. */
    /* v2.12.38 — CENTER-focused carousel: one review sits in the middle, neighbours peek;
       each swipe snaps the next card to centre; JS autoplays + loops (see main.js). */
    .testimonials__viewport {
        overflow-x: auto; overflow-y: visible;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }
    .testimonials__viewport::-webkit-scrollbar { display: none; }
    .testimonials__track {
        gap: 16px; animation: none !important; transform: none !important;
        width: max-content; touch-action: pan-x pan-y; cursor: default;
        /* leading/trailing space = half viewport − half card so the first/last card centre. */
        padding-left: calc(50vw - 124px); padding-right: calc(50vw - 124px);
    }
    .testimonial {
        flex: 0 0 248px; width: 248px; height: auto; min-height: 350px;
        display: flex; flex-direction: column; padding: 24px 22px 22px; box-sizing: border-box;
        scroll-snap-align: center;
    }
    .testimonial__mark { position: static; width: auto; height: auto; font-size: 42px; line-height: .7; margin: 0 0 2px; }
    .testimonial__quote { position: static; width: auto; height: auto; font-size: 13.5px; line-height: 1.6; margin: 0 0 16px; }
    .testimonial__rate { position: static; left: auto; top: auto; margin: auto 0 6px; } /* smaller bottom gap so the bigger logo zone below doesn't push the stars up */
    /* v2.12.80 — per-logo logo sizes from the Figma MOBILE testimonial spec
       (frame 266:1511; card 187.68px → our 248px card, scaled ~1.32). The old flat
       24px height made wide wordmarks fine but the square/compact emblems (Oribel)
       look tiny. Now each logo follows its Figma size: wordmarks sit ~22px tall and
       compact/stacked marks are taller so none reads as "kecil". */
    /* One fixed 30px logo zone, every logo CENTERED in it → all logos share a common
       centerline so they look level ("sejajar") regardless of shape (wide wordmark vs
       square circle), and the box height is constant so the stars above don't shift. */
    /* v2.12.128 — back to per-logo heights (the uniform 110-box made the wide
       wordmarks too big). Wordmarks stay 22px; only the compact ones bumped:
       Oribel emblem, and Mount Elizabeth + RWS enlarged per user. */
    .testimonial__logo { position: static !important; left: auto !important; top: auto !important; width: auto !important; height: 44px !important; display: flex; align-items: center; justify-content: flex-start; }
    .testimonial__logo img { width: auto; height: 22px; max-width: 150px; object-fit: contain; display: block; } /* wordmarks: brother, petco, CIMB, SGX, CapitaLand, crypto */
    .testimonial__logo img[src*="client-logo-6"]          { height: 40px; } /* Oribel — circle emblem */
    .testimonial__logo img[src*="client-mount-elizabeth"] { height: 36px; } /* Mount Elizabeth — enlarged */
    .testimonial__logo img[src*="client-rws"]             { height: 44px; } /* RWS (Resorts World) — enlarged */
    /* v2.12.157 — Petco is a heart-EMBLEM logo (~1.9:1); at the 22px wordmark
       height it read tiny. Bump it like the other emblems to match its enlarged
       desktop size. Covers home/about (client-logo-2) + Services (client-petco-love). */
    .testimonial__logo img[src*="client-logo-2"],
    .testimonial__logo img[src*="client-petco-love"]      { height: 34px; } /* Petco — emblem, enlarged */
    /* v2.12.53 — tapped ("popped") card lifts so it reads clearly while the live
       centre-scroll is paused; JS toggles .is-popped and resumes on dismiss. */
    .testimonial.is-popped {
        transform: scale(1.045);
        box-shadow: 0 18px 40px -12px rgba(21, 102, 224, 0.30),
                    0 8px 18px -6px rgba(0, 0, 0, 0.18);
        z-index: 5;
    }

    /* Team CTA: text first, then photos; photos ~30% smaller + centred; the note
       ("no strings attached") drops below the Get a Quote button. Whole content
       centre-aligned to match the centred photos. */
    .cta__content { order: -1; text-align: center; }
    .cta__body { margin-left: auto; margin-right: auto; }
    /* v2.12.122 — portraits grid width = the "Let's Build It Together!" heading width
       (301px @ 30px), centred, so the photo block's left/right edges line up with the
       heading above it. 2 equal cols fill that 301px; aspect-ratio gives cell height
       since the <img> is position:absolute. (width:100% lets it shrink on tiny phones.) */
    .cta__portraits {
        grid-template-columns: 1fr 1fr !important;
        grid-template-rows: auto !important;
        gap: 12px;
        width: 100%;
        max-width: 301px;
        margin-left: auto;
        margin-right: auto;
        justify-content: stretch !important;
    }
    .cta__portrait { width: 100% !important; height: auto !important; aspect-ratio: 120 / 146; }
    .cta__cta-row { flex-direction: column; align-items: center; gap: 12px; }
}

@keyframes testimonials-loop-mobile {
    /* one set = 6 cards (248px) + 6 gaps (16px) = 1584px */
    from { transform: translateX(0); }
    to   { transform: translateX(-1584px); }
}

/* v2.11.96 — mobile-only line break utility: <br class="br-m"> collapses on
   desktop and breaks on phones (AI compare title "3x faster", portfolio CTA
   headline/sub, etc.). desktop layout untouched. */
.br-m { display: none; }
@media (max-width: 768px) { .br-m { display: inline; } }

/* =========================================================
   v2.12.134 — TABLET About "Visual Strategy" TWO-COLUMN (600–1240px).
   Placed LAST so it wins over every earlier ≤768 mobile block (which
   stacked the section: gallery order:-1 on top, photos capped 150px &
   centred). Feedback: "sama kaya desktop" — title + body LEFT, 2x2 photo
   grid on the RIGHT, scaled down.
   ⚠️ Floor is 600 (NOT 768) on purpose: a 768px browser WINDOW on Windows
   has only ~751px viewport (vertical scrollbar eats ~17px), so a 768 floor
   silently missed the user's tablet preview → it stayed in mobile stack.
   600 robustly catches every tablet width incl. that scrollbar gap; real
   phones (portrait ≤430) stay ≤599 → keep the tuned stacked layout.
   Desktop (≥1241) untouched. ========================================= */
@media (min-width: 600px) and (max-width: 1240px) {
    .about__inner {
        grid-template-columns: minmax(0, 1fr) clamp(200px, 30vw, 330px);
        gap: clamp(24px, 4vw, 44px);
        /* v2.12.143 — top-align the photo grid with the "Visual Strategy"
           headline (was center = photos floated down level with the body).
           Tablet only; desktop keeps its centered alignment. */
        align-items: start;
    }
    /* Undo the mobile reorder (order:-1 floated the gallery above the copy)
       so DOM order text→gallery reads as LEFT→RIGHT. */
    .about__gallery {
        order: 0;
        grid-template-columns: 1fr 1fr;
        grid-template-rows: auto auto;
        gap: 16px;
        width: 100%;
        max-width: none;
        margin: 0;             /* undo mobile margin:0 auto centering */
        justify-content: stretch;
    }
    .about__photo { width: 100%; height: auto; aspect-ratio: 1; }
    /* Title stays readable across the band (mobile forced 28px). */
    .about__title { font-size: clamp(30px, 4vw, 44px); }
    .about__body p { font-size: clamp(15px, 1.7vw, 17px); }
    /* v2.12.145 — cap the body so its right edge lines up with the END of the
       3rd Telly trophy (the "3 Telly Awards" medals row ends ~402px from the
       text-column left). Full-size medals here (portrait 769–1000 uses its own
       narrower body via the v2.12.144 block). Feedback: "batesnya sampe akhir
       gambar piala silver ke-3 untuk teks". */
    .about__body { max-width: 402px; }
}

/* =========================================================
   v2.12.136 — TABLET (600–1240px) restore more sections to their desktop
   two-column shape. Feedback: "all CTA yang ada fotonya dibuat kanan-kiri
   sama kaya desktop" + "footer lokasi dibikin 2 kolom". Placed LAST so it
   beats the earlier ≤1240 / ≤768 mobile blocks that stacked them.
   ========================================================= */
@media (min-width: 600px) and (max-width: 1240px) {
    /* Photo CTAs (home / about + blog & porto listings via superpixel_team_cta):
       team portraits LEFT + copy RIGHT like desktop, scaled down (were stacked
       1-col by the ≤1240 block). DOM order is portraits→content so `auto 1fr`
       keeps photos on the left, exactly like the desktop grid. */
    .cta {
        grid-template-columns: auto minmax(0, 1fr);
        /* v2.12.149 — bigger column gap so the copy isn't cramped against the
           team photos ("terlalu mepet ke foto, buat balance"). Was 24–56px. */
        gap: clamp(44px, 6.5vw, 96px);
        padding: clamp(50px, 7vw, 80px) 40px;
        align-items: center;
    }
    .cta__portraits {
        grid-template-columns: repeat(2, clamp(118px, 15vw, 180px));
        grid-template-rows: auto auto;
        gap: 14px;
        justify-content: start;
        align-content: center;
    }
    .cta__portrait { width: 100%; height: auto; aspect-ratio: 180 / 219.333; }
    .cta__content { max-width: none; }
    .cta__title { font-size: clamp(28px, 3.4vw, 44px); }
    .cta__body  { font-size: clamp(17px, 1.9vw, 21.667px); }

    /* Footer office addresses → 2 columns (the ≤1240 block stacked them to 1). */
    .site-footer__addresses { grid-template-columns: 1fr 1fr; column-gap: 40px; row-gap: 30px; }
}

/* =========================================================
   v2.12.139 — TABLET (769–1240) FAQ = 2 columns like desktop. The 2-col FAQ
   layout was gated at ≥1025 only (a v2.12.25 decision kept 769–1024 single-
   column); the ≤1240 mobile block also forces 1fr. Feedback: 2 columns on
   tablet. This replicates the desktop ≥1025 two-column treatment (dividers
   between items, no per-item border) but WITHOUT the hover-to-open (tablets
   are touch → the click-accordion JS handles it). Phones (≤768) keep the
   single-column mobile FAQ. Placed LAST so it wins over both earlier blocks.
   ========================================================= */
@media (min-width: 769px) and (max-width: 1240px) {
    .faq__grid {
        grid-template-columns: 1fr 1fr;
        column-gap: clamp(32px, 5vw, 66.66px);
        border-top: 0;
        max-width: none;
    }
    .faq__col { gap: 13.942px; align-items: start; }
    .faq__item { width: 100%; max-width: none; border-bottom: 0; }
    .faq__q { padding: 0; line-height: 1; }
    .faq__q-text { padding-right: 0; }
    .faq__divider { display: block; }
}

/* =========================================================
   v2.12.144 — TABLET-PORTRAIT (769–1000) "Visual Strategy" (.about) section:
   BIGGER photos + body text wrapped NARROW so its right edge lines up with the
   "3 Telly Awards" trophy row (feedback: "body textnya kurangin lagi, sejajarin
   sama foto piala itu batasnya; biar fotonya dibesarin"). Wider gallery column →
   bigger portraits; the title + medals scale down a touch so they still fit the
   narrower text column; body capped to the trophy width (~328px). Scoped to
   PORTRAIT only — landscape (1001–1240) keeps the approved layout (else the
   fixed-narrow-body + big-gallery leaves a huge empty gap at 1174); ≤768 mobile
   & desktop untouched. Comes after the 600–1240 .about block so it wins.
   v2.12.149 — floor 769→768 so iPad-Mini/portrait at exactly 768 also gets the
   bigger photos (was missing by 1px). */
@media (min-width: 768px) and (max-width: 1000px) {
    /* v2.12.150 — same max-content approach as landscape so the photos grow and
       extend LEFT (feedback "768 juga fotonya belum membesar ke kiri"): text
       column shrinks to its content, gallery (1fr) takes the rest. Title needs
       width:auto too (base has a fixed width:546px that would block the shrink). */
    .about__inner {
        grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
        gap: clamp(20px, 2.6vw, 36px);
    }
    .about__title { font-size: clamp(22px, 2.9vw, 34px); width: auto; }
    .about__body { max-width: 328px; }
    .about__award-medals img { height: 44px; }
}

/* =========================================================
   v2.12.146 — TABLET-LANDSCAPE (1001–1240) "Visual Strategy" (.about): make the
   photo grid BIGGER and pull it LEFT to fill the gap (feedback: "besarin layout
   fotonya ke kiri"). The text column shrinks to its content width (max-content =
   whichever is widest: the title / the 402px body / the trophy row) and the
   gallery (1fr) takes ALL the remaining width → big portraits, minimal centre
   gap. Body stays capped 402 (aligned to the 3rd trophy) & full-size medals from
   the 600–1240 block. Portrait 769–1000 keeps its own block; ≤768 & desktop
   untouched. Comes last so it wins over the 600–1240 grid. */
@media (min-width: 1001px) and (max-width: 1240px) {
    .about__inner {
        grid-template-columns: minmax(0, max-content) minmax(0, 1fr);
        gap: clamp(28px, 3.4vw, 48px);
    }
    /* ⚠️ the base .about__title has an explicit width:546.423px — that fixed
       width becomes the text column's max-content and stops it shrinking, so the
       gallery stayed small. Let the title shrink to its real text width so the
       column collapses to content and the gallery grows to fill the rest. */
    .about__title { width: auto; }
}
