/* v2.12.52 — mobile-only line break helper. The <br class="svc-br-m"> is
   hidden on desktop (layout unchanged) and only forces a break at ≤768px. */
br.svc-br-m { display: none; }
@media (max-width: 768px) { br.svc-br-m { display: inline; } }

/* =========================================================
   v2.4.3 — HERO CAROUSEL (Figma 96:1634)
   5 slides, full-viewport-width, auto-rotate every 5s.
   ========================================================= */
.hero__carousel {
    position: relative;
    /* v2.6.101 — .hero-wrap is now full-vw, so the carousel just takes
       100% of its parent. Removed the 100vw + negative-margin trick
       that used to escape the 1280 cap (it got clipped by .hero's
       overflow:hidden on zoomed-out viewports). */
    width: 100%;
    flex: 1 1 0;
    min-height: 0;
    padding: 0;
    margin-top: 32px;
    box-sizing: border-box;
    user-select: none;
}
.hero__carousel-card {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: #1a1a1a;
}
.hero__slides {
    display: flex;
    width: 100%;
    height: 100%;
    transition: transform .8s cubic-bezier(.7, 0, .3, 1);
    will-change: transform;
}
.hero__slide {
    flex: 0 0 100%;
    position: relative;
    overflow: hidden;
}
.hero__slide img,
.hero__slide-video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
/* v2.6.87 — scroll-runway parallax: video subtly zooms in (1.0 → 1.08)
   as the user scrolls through the 100vh hero runway. JS sets
   `transform: scale(...)` per frame; transform-origin stays center
   so the crop is symmetric, and .hero__slide's overflow:hidden
   hides any edge spill. */
.hero__slide-video {
    transform-origin: center center;
    will-change: transform;
}
/* Soft gradient overlay at the bottom for legible text. */
.hero__slide::after {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    height: 60%;
    background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 100%);
    pointer-events: none;
}
.hero__slide-text {
    position: absolute;
    /* v2.5.7 — Figma 166:2078/2079: caption nudged downward so its subtitle
       baseline sits on the same row as the dash indicators on the right.
       Left inset scales softly from a small viewport gutter up to the Figma
       112px on a 1920 canvas. */
    left: clamp(20px, 5.8vw, 112px);
    bottom: 26px;
    z-index: 2;
    color: #fff;
    max-width: min(860px, 70vw);
}
/* feedback — carousel caption links to its project's portfolio page. */
a.hero__slide-text--link { text-decoration: none; color: #fff; cursor: pointer; display: block; }
a.hero__slide-text--link:hover .hero__slide-title { text-decoration: underline; text-underline-offset: 3px; }
.hero__slide-title {
    /* v2.5.7 — Figma 28px Medium for caption title. */
    font-size: clamp(18px, 1.9vw, 28px);
    font-weight: 500;
    line-height: 1.25;
    margin: 0 0 6px;
    color: #fff;
}
.hero__slide-sub {
    /* v2.5.7 — Figma 16px Regular for caption subtitle; bumped +5px (v2.9.75). */
    font-size: clamp(17px, 1.05vw, 21px);
    font-weight: 400;
    line-height: 1.4;
    margin: 0;
    color: rgba(255, 255, 255, 0.92);
}

/* Progress bar — flush with the bottom edge of the carousel. Fills
   0→100% over a fixed 10s per slide via CSS @keyframes (smooth at 60fps,
   independent of video duration). */
.hero__progress {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 5px;
    background: rgba(245, 245, 245, 0.20);
    z-index: 3;
    pointer-events: none;
}
.hero__progress-fill {
    height: 100%;
    width: 0;
    background: rgba(245, 245, 245, 0.65);
}
.hero__progress-fill.is-running {
    animation: hero-progress 10s linear forwards;
}
.hero__progress-fill.is-paused {
    animation-play-state: paused;
}
@keyframes hero-progress {
    from { width: 0; }
    to   { width: 100%; }
}

/* Dash indicators — 4-5 small white pills stacked in the bottom right. */
.hero__indicators {
    position: absolute;
    /* v2.5.7 — match Figma 166:208x right-edge gutter at 1920 (~125px),
       scale down for narrower viewports. Vertically aligned with the
       slide caption's subtitle baseline (both bottom:26px). */
    right: clamp(20px, 6.5vw, 125px);
    bottom: 26px;
    display: flex;
    gap: 6px;
    z-index: 4;
}
.hero__dash {
    width: 22px;
    height: 3px;
    background: rgba(255, 255, 255, 0.40);
    border: 0;
    padding: 0;
    cursor: pointer;
    transition: background .25s ease, transform .25s ease;
    border-radius: 1px;
}
.hero__dash:hover { background: rgba(255, 255, 255, 0.7); }
.hero__dash.is-active { background: #ffffff; transform: scaleY(1.3); }

/* Mobile: shrink padding and bring text closer to the edge. */
@media (max-width: 768px) {
    /* v2.11.99 — fill the screen like desktop: hero = one viewport tall (minus the
       64px fixed header); copy on top, the carousel takes the REMAINING space so
       its bottom edge (caption + live slider) lands at the screen bottom on every
       phone. Was a fixed 4:5 that overflowed and pushed the slider off-screen. */
    /* v2.12.3 — fill the CURRENT visible viewport with dvh (dynamic = tracks the live
       URL-bar state) so the carousel reaches the screen bottom and the live slider bar
       sits EXACTLY at the bottom edge on every phone. svh (v2.12.2) was too short when
       the address bar was retracted → white gap below the slider; plain vh/var(--vph)
       was too tall → slider fell below the fold. dvh matches the visible area exactly,
       so no gap and no crop. Subtract only the 64px fixed header (body has padding-top
       64px). height:auto kills the leftover desktop height:calc(100vh-76px). The video
       crops per screen via object-fit:cover; slider is the bottom boundary. */
    .hero { height: auto; min-height: calc(100vh - 64px); min-height: calc(100dvh - 64px); display: flex; flex-direction: column; }
    .hero__copy { flex: 0 0 auto; }
    .hero__carousel { flex: 1 1 auto; aspect-ratio: auto; min-height: 0; margin-top: 20px; }
    /* v2.12.5 — THE actual crop/gap cause: the carousel correctly flex-grows to fill
       the hero, but .hero__carousel-card used height:100%, which can't resolve against
       a flex-grown parent (its computed height is `auto`) → the card collapsed to the
       video's intrinsic 16:9 (~269px) and left white space below. Pinning the card to
       fill the carousel (absolute inset:0 = a definite box) makes the video fill the
       whole flex-grown height, so the carousel reaches the screen bottom on every phone
       and the live slider bar is the bottom edge. */
    .hero__carousel-card { position: absolute; inset: 0; height: auto; width: 100%; }
    /* v2.11.90 — caption was filling the frame; shrink it on phones. */
    .hero__slide-text { left: 20px; bottom: 22px; max-width: calc(100% - 40px); }
    .hero__slide-title { font-size: 16px; }
    .hero__slide-sub { font-size: 14px; } /* v2.11.97 — +2pt */
    .hero__indicators { right: 20px; bottom: 24px; }
}

@media (prefers-reduced-motion: reduce) {
    .hero__slides { transition: none; }
    .hero__progress-fill.is-running { animation: none; width: 100%; }
}

/* =========================================================
   v2.6.86 — hero-wrap scroll runway: copy fades + collapses,
   carousel expands to fill the viewport in-place. Mobile opt-out
   handled by JS clearing inline styles + the .hero-wrap height
   override below. */
@media (max-width: 768px) {
    .hero-wrap { height: auto; }
    /* v2.11.99 — keep position/overflow reset but NOT height:auto (the carousel
       block above makes the hero fill one viewport so the slider sits on-screen). */
    .hero { position: relative; top: auto; overflow: visible; }
}

/* =========================================================
   v2.4.x — DROPDOWN NAV + 5 PAGE TEMPLATES (Figma-accurate)
   Loaded after main.css to override.
   Figma source: bHsX3bIqFsAozx1nsx125O (1280 canvas).
   Pixel values are matched 1:1 within the section's content
   wrapper; the wrapper itself scales soft-cap 1600px.
   ========================================================= */

/* ---------- Header dropdown nav ---------- */
.navbar__links { gap: 32px; }
.navbar__item { position: relative; display: flex; align-items: center; }
.navbar__link { display: inline-flex; align-items: center; gap: 6px; padding: 10px 0; }
.navbar__link-label { display: inline-block; }
/* feedback — Services is a non-navigating <span> trigger (hover to pick a
   category). It misses the `.navbar__links a` colour/size rule, so mirror it
   here; pointer cursor signals it still opens the menu. */
.navbar__link--trigger {
    color: var(--color-muted); font-size: 19px; line-height: 1;
    cursor: pointer; transition: color .2s ease; -webkit-user-select: none; user-select: none;
}
.navbar__item--has-sub:hover .navbar__link--trigger,
.navbar__link--trigger:hover,
.navbar__link--trigger:focus-visible { color: var(--color-text); }
.navbar__caret {
    display: inline-block;
    width: 10px; height: 10px;
    position: relative;
    transition: transform .25s cubic-bezier(.2,.7,.2,1);
}
/* feedback — chevron made of two strokes (outline), NOT a filled triangle. */
.navbar__caret::before {
    content: "";
    position: absolute; left: 50%; top: 42%;
    width: 6px; height: 6px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: translate(-50%, -50%) rotate(45deg);
}
.navbar__item--has-sub.is-open .navbar__caret,
.navbar__item--has-sub:hover .navbar__caret,
.navbar__item--has-sub:focus-within .navbar__caret { transform: rotate(180deg); }

.navbar__dropdown {
    position: absolute;
    top: calc(100% + 14px);
    left: 50%;
    transform: translate(-50%, 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);
    padding: 10px 0;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .2s ease, transform .25s cubic-bezier(.2,.7,.2,1), visibility .25s;
    z-index: 1100;
}
.navbar__dropdown::before {
    content: ""; position: absolute;
    top: -14px; left: 0; right: 0; height: 14px;
}
.navbar__dropdown::after {
    content: ""; position: absolute;
    top: -7px; left: 50%;
    transform: translateX(-50%) rotate(45deg);
    width: 14px; height: 14px;
    background: #ffffff;
    box-shadow: -2px -2px 4px rgba(20, 30, 60, 0.04);
}
/* v2.12.4 — open on HOVER **and** CLICK. Pointing the cursor at the Services/
   Portfolios text reveals the dropdown (desktop, restored). Clicking the label
   still does NOT navigate (JS preventDefault) — it just keeps the menu open via
   .is-open so keyboard/touch users can pick a category too. */
.navbar__item--has-sub.is-open .navbar__dropdown,
.navbar__item--has-sub:hover .navbar__dropdown,
.navbar__item--has-sub:focus-within .navbar__dropdown {
    opacity: 1; visibility: visible; pointer-events: auto;
    transform: translate(-50%, 0);
}
.navbar__sub { list-style: none; margin: 0; padding: 0; }
.navbar__sub li a,
.navbar__sub-item > a {
    display: block;
    padding: 9px 22px;
    font-size: 16px; /* feedback — hover dropdown links +2pt (13→16) */
    font-weight: 500;
    color: var(--color-text);
    white-space: nowrap;
    transition: color .2s ease, background .2s ease;
}
.navbar__sub li a:hover,
.navbar__sub-item:hover > a { color: var(--color-primary); background: rgba(235, 71, 0, 0.06); }

/* Album-preview dropdown variant — text column on the left, image
   thumbnail on the right swaps as user hovers each sub-item. Used by
   the Portfolios menu. */
.navbar__dropdown--album {
    padding: 14px;
    width: 560px;
    border-radius: 14px;
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 16px;
    align-items: stretch;
}
.navbar__dropdown--album .navbar__sub {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.navbar__dropdown--album .navbar__sub-item > a {
    padding: 10px 14px;
    border-radius: 8px;
    white-space: normal;
}
.navbar__dropdown--album .navbar__sub-item:hover > a {
    background: rgba(235, 71, 0, 0.08);
    color: var(--color-primary);
}
.navbar__dropdown--album .navbar__sub-preview { display: none; }

/* Image preview pane on the right — each sub-item's thumb stacks here
   absolutely; CSS hover swaps which one is visible. */
.navbar__album {
    position: relative;
    border-radius: 0;
    overflow: hidden;
    background: #f1f1f1;
    aspect-ratio: 4 / 3;
    min-height: 100%;
}
.navbar__dropdown--album .navbar__sub-item img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transform: scale(1.02);
    transition: opacity .35s ease, transform .6s cubic-bezier(.2,.7,.2,1);
    z-index: 1;
}
/* Hoist thumb images out of the <li> and into the album pane visually.
   Anchored to the dropdown (the nearest positioned ancestor), spanning
   the right-hand album column. */
.navbar__dropdown--album .navbar__sub-item .navbar__sub-preview {
    display: block;
    position: absolute;
    top: 14px;
    right: 14px;
    bottom: 14px;
    left: calc(14px + 200px + 16px);
    pointer-events: none;
    border-radius: 0;
    overflow: hidden;
}
.navbar__dropdown--album .navbar__sub-item .navbar__sub-preview img {
    border-radius: 0;
}
/* Default: show the FIRST sub-item's preview. */
.navbar__dropdown--album .navbar__sub-item:first-child .navbar__sub-preview img {
    opacity: 1;
    transform: scale(1);
}
/* When any item is hovered, hide the default first one. */
.navbar__dropdown--album .navbar__sub:hover .navbar__sub-item:first-child .navbar__sub-preview img {
    opacity: 0;
}
/* And reveal the hovered item's preview. */
.navbar__dropdown--album .navbar__sub-item:hover .navbar__sub-preview img {
    opacity: 1 !important;
    transform: scale(1) !important;
}

/* Services 4-column mega-menu (Figma 279:1854). Right-aligned to the Services
   item so it never overflows the right edge; grey thumb header + link list per
   column. */
/* Fixed + right-aligned to the navbar gutter so the panel's right edge lines up
   with the GET A QUOTE button (not the Services item). The panel is wide enough
   to still sit under Services, so hover transfers fine (it's a DOM child of the
   Services <li>). top = 76px navbar + 14px gap. */
.navbar__dropdown--mega {
    position: fixed; top: 90px; left: auto;
    right: clamp(20px, 3.3vw, 63px);
    transform: translateY(8px);
    min-width: 0; width: max-content; max-width: min(92vw, 920px);
    padding: 22px;
}
.navbar__item--has-sub.is-open .navbar__dropdown--mega,
.navbar__item--has-sub:hover .navbar__dropdown--mega,
.navbar__item--has-sub:focus-within .navbar__dropdown--mega { transform: translateY(0); }
.navbar__dropdown--mega::after { display: none; } /* arrow would point at GET A QUOTE, not Services */
/* v2.9.49 — the mega panel is position:fixed at top:90px while the "Services"
   trigger sits centred in the 76px navbar (its lower edge ~58px). The default
   14px ::before bridge only covered 76→90px, leaving a dead band between the
   link and the panel: moving the cursor down to click made the menu flicker
   shut. Extend the invisible hover-bridge up to overlap the trigger so hover
   stays continuous from link → bridge → panel. */
.navbar__dropdown--mega::before { top: -40px; height: 40px; left: 0; right: 0; }
.navbar__mega { display: flex; gap: 22px; }
.navbar__mega-col { flex: 0 0 168px; width: 168px; }
.navbar__mega-head {
    position: relative; display: flex; align-items: flex-end; height: 92px; padding: 12px;
    border-radius: 0; background: #c9c9c9; overflow: hidden; margin-bottom: 12px;
}
.navbar__mega-head img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* v2.11.15 — bottom-only shadow restored under the mega thumbnail labels
   ("add shadow bawahnya aja"); fades out by mid-thumbnail so the image stays clean. */
.navbar__mega-head::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(0,0,0,0) 45%, rgba(0,0,0,.55) 100%);
}
.navbar__mega-head.is-placeholder::after { background: none; }
.navbar__mega-title { position: relative; z-index: 1; font-size: 16px; font-weight: 600; color: #fff; letter-spacing: .01em; } /* feedback — Services column title 14→16 */
.navbar__mega-links { list-style: none; margin: 0; padding: 0; }
.navbar__mega-links li { margin: 0; }
.navbar__mega-links a {
    display: block; padding: 6px 2px; font-size: 16px; font-weight: 500; /* feedback — Services mega links +2pt (13→16) */
    color: var(--color-text); white-space: nowrap;
    transition: color .2s ease;
}
.navbar__mega-links a:hover { color: var(--color-primary); }

/* =========================================================
   Shared page chrome — soft pastel rainbow wash near the top,
   used by Portfolios/Blog-listing/Article/Contact (Figma BG_ABOUT US).
   ========================================================= */
.page-bg-wash {
    position: absolute;
    inset: 0 auto auto 0;
    width: 100%;
    height: 592px;
    pointer-events: none;
    overflow: hidden;
    z-index: -1;
}
.page-bg-wash::before {
    content: "";
    position: absolute;
    left: 50%;
    top: -140px;
    width: 1200px;
    height: 690px;
    transform: translateX(-50%);
    background:
        radial-gradient(closest-side at 18% 30%, rgba(255, 192, 218, 0.55), transparent 65%),
        radial-gradient(closest-side at 82% 28%, rgba(160, 215, 255, 0.55), transparent 65%),
        radial-gradient(closest-side at 50% 70%, rgba(255, 232, 188, 0.45), transparent 65%);
    filter: blur(40px);
    opacity: 0.65;
}

/* =========================================================
   PORTFOLIO LISTING — Figma 96:802 ("Selected Works")
   ========================================================= */
.works {
    position: relative;
    /* v2.11.72 — side gutters matched to the blog (.news) so the blog and
       portfolio "Selected Works" pages share the same view width. */
    padding: 76px clamp(56px, 6.5vw, 100px) 120px;
    max-width: 1280px;
    margin: 0 auto;
}
/* Figma 118:2324 — coloured accent anchored upper-left, rotated 180° so
   the asset's blob (which sits in its lower-left quadrant) ends up
   behind the "Selected" word of the title. Per Figma: container centred
   at calc(21.88% − 23.77px) of 1280 canvas, top:53, width:605.785px,
   image overflowing by ~41% top/bottom and ~29% left/right. The asset
   is intrinsically soft so we render at full alpha for visibility. */
.works__accent {
    position: absolute;
    top: 53px;
    left: clamp(140px, calc(21.88% - 23.77px), 256px);
    transform: translateX(-50%) rotate(180deg);
    width: clamp(480px, 47.3vw, 605.785px);
    aspect-ratio: 961 / 786;
    pointer-events: none;
    z-index: 0;
    opacity: 1;
}
.works__accent::before {
    content: "";
    position: absolute;
    inset: -41.26% -29.35%;
    background: url('../images/coloured-accent.webp') center/contain no-repeat;
}
/* Stacking: head/grid/paging sit above the accent (z=0), but the FILTER
   row needs z-index higher than the grid so its Others dropdown panel
   paints on top of the cards below it. */
.works__head, .works__grid, .works__paging { position: relative; z-index: 1; }
.works__filters { position: relative; z-index: 20; }
.works__head {
    display: grid;
    grid-template-columns: 1fr 400px;
    gap: 60px;
    align-items: end;
    margin-bottom: 48px;
}
/* Figma 96:942 — "Selected" Regular black, "Works" Medium gray on a
   second line. Not italic. 97.333px / line-height 0.905. */
.works__title {
    font-size: 97.333px;
    font-weight: 400;
    line-height: 0.905;
    letter-spacing: -0.01em;
    margin: 0;
}
.works__title-line2 {
    display: block;
    font-weight: 500;
    color: #535353;
}
.works__intro {
    font-size: 18px; /* feedback — landing right-side intro +2pt (14.985→18) */
    line-height: 1.5;
    color: rgba(35, 31, 32, 0.85);
    margin: 0;
    text-align: left;
}
/* =========================================================
   Others dropdown — Figma 62:1181. Used on BOTH homepage portfolio
   filters (.portfolio__filter-*) and /portfolios/ (.portfolio__filter-*
   reused via same classes).
   ========================================================= */
/* Trigger when panel is open: SemiBold ITALIC blue, caret flipped up. */
.portfolio__filter-other.is-active {
    color: var(--color-accent);
    font-weight: 600;
    font-style: italic;
}
/* Panel: 384px wide, frosted-glass white 88%, deep shadow. */
.portfolio__filter-panel {
    position: absolute;
    top: calc(100% + 14px);
    right: 0;
    left: auto;
    width: 384px;
    max-width: calc(100vw - 80px);
    background: rgba(255, 255, 255, 0.88);
    backdrop-filter: blur(7px);
    -webkit-backdrop-filter: blur(7px);
    box-shadow: 0 16px 32.64px rgba(0, 0, 0, 0.35);
    border-radius: 4px;
    padding: 15px 0;
    z-index: 50;
}
.portfolio__filter-panel[hidden] { display: none; }
/* Each item: 46px tall, 20px Medium black. Centered text block in 335px-wide
   row aligned to the panel content area (42px left padding from Figma). */
.portfolio__filter-panel-item {
    display: block;
    width: 100%;
    background: none;
    border: 0;
    padding: 11px 42px;
    font-family: inherit;
    font-size: 20px;
    font-weight: 500;
    line-height: 24px;
    color: var(--color-text);
    text-align: left;
    cursor: pointer;
    position: relative;
    transition: color .2s ease, background .2s ease;
}
/* Hover/active: faint white frosted backdrop + blue SemiBold (matches
   Figma's "HoverColor" overlay component blur(17.5px) opacity 66%). */
.portfolio__filter-panel-item:hover,
.portfolio__filter-panel-item:focus-visible {
    color: var(--color-accent);
    font-weight: 600;
    background: rgba(255, 255, 255, 0.6);
    outline: none;
}
.portfolio__filter-panel-item.is-active {
    color: var(--color-accent);
    font-weight: 600;
    background: rgba(255, 255, 255, 0.6);
}
@media (max-width: 700px) {
    .portfolio__filter-panel { width: calc(100vw - 48px); }
    .portfolio__filter-panel-item { font-size: 17px; padding: 10px 24px; }
}

/* Filter row — mirrors homepage `.portfolio__filters` exactly: 16px Medium,
   --color-border default, blue --color-accent on hover/active. No top/bottom
   borders (homepage doesn't have them). */
.works__filters {
    display: flex;
    flex-wrap: wrap;
    gap: 40px;
    align-items: center;
    min-height: 20.8px;
    margin-bottom: 40px;
    position: relative;
    z-index: 10;
}
.works__filter,
.works__filter--others {
    background: none; border: 0; padding: 0; cursor: pointer;
    font-size: 16px;
    font-weight: 500;
    color: var(--color-border);
    font-family: inherit;
    line-height: 1.2;
    transition: color .2s ease;
}
.works__filter:hover,
.works__filter--others:hover { color: var(--color-accent); }
.works__filter.is-active { color: var(--color-accent); font-weight: 600; }
.works__filter--others { display: inline-flex; align-items: center; gap: 6px; }
.works__filter--others .navbar__caret::before { border-top-color: currentColor; }

/* Figma 96:802 — 2 columns @ 583px wide each, ~33px gap, 16:9 thumbs. */
.works__grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 60px 33px;
}
.works__card { display: block; }
.works__thumb {
    display: block;
    position: relative;
    aspect-ratio: 583 / 328;
    overflow: hidden;
    border-radius: 0;
    background: #f4f4f4;
}
/* Two-layer thumb: rest PNG fades OUT, hover GIF fades IN, both scale up
   slightly — same trio of effects the homepage portfolio uses. GIF src
   is set lazily on first hover (see main.js [data-hover-src]). */
.works__thumb-img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    transition: opacity .35s ease, transform .6s cubic-bezier(.2,.7,.2,1);
}
.works__thumb-img--rest  { opacity: 1; }
.works__thumb-img--hover { opacity: 0; }
/* Two-layer crossfade: featured image fades OUT, work_hover image fades IN,
   both zoom slightly. Hover src is lazy-loaded on first hover (main.js). */
.works__thumb:hover .works__thumb-img--rest,
.works__thumb:focus-within .works__thumb-img--rest  { opacity: 0; }
.works__thumb:hover .works__thumb-img--hover,
.works__thumb:focus-within .works__thumb-img--hover { opacity: 1; }
.works__thumb:hover .works__thumb-img,
.works__thumb:focus-within .works__thumb-img        { transform: scale(1.04); }
/* Title turns blue on card hover — same as homepage. !important guards
   against cache lag where an older v240.css still ships the static rule
   later in the file with equal specificity. */
.works__card:hover .works__card-title,
.works__card:focus-within .works__card-title { color: var(--color-accent) !important; }
/* Fallback for any plain <img> still inside .works__thumb (legacy paths). */
.works__thumb > img:not(.works__thumb-img) {
    width: 100%; height: 100%;
    object-fit: cover;
}
.works__thumb-tag {
    position: absolute; top: 10px; right: 10px;
    background: var(--color-primary); color: #fff;
    font-weight: 700; font-size: 11px;
    padding: 5px 7px; border-radius: 3px;
}
/* Figma 96:809 — 21.788px Medium, black, just under the thumb. */
.works__card-title {
    font-size: 21.788px;
    font-weight: 500;
    margin: 18px 0 4px;
    color: var(--color-text);
    line-height: 1.3;
    transition: color .25s ease;
}
/* Figma 96:810 — 14.007px Medium, 65% black. */
.works__card-sub {
    font-size: 14.007px;
    font-weight: 500;
    color: rgba(35, 31, 32, 0.65);
    margin: 0;
    line-height: 1.4;
}
/* Figma 96:945 — "CLICK HERE" white overlay on the first card thumb.
   Positioned roughly center-ish (35% from left, 44% from top per the
   1280-canvas math). Inter not loaded; Figtree is close enough at 35px. */
.works__click-here {
    position: absolute;
    left: 35%;
    top: 44%;
    font-size: clamp(22px, 2.6vw, 35px);
    font-weight: 400;
    color: #ffffff;
    letter-spacing: 0.01em;
    text-shadow: 0 2px 12px rgba(0, 0, 0, 0.45);
    pointer-events: none;
    white-space: nowrap;
    z-index: 2;
    transition: opacity .35s ease;
}
/* Hide once the hover image kicks in so it doesn't sit on top of it. */
.works__thumb:hover .works__click-here,
.works__thumb:focus-within .works__click-here { opacity: 0; }

/* Figma 96:811 — tag row, blue #1566e0, 14.007px Medium, 5.115px gap,
   3.07px round dot separators. */
.works__card-tags {
    list-style: none;
    display: flex;
    gap: 5.115px;
    align-items: center;
    margin: 12px 0 0;
    padding: 0;
    color: var(--color-accent);
    font-size: 14.007px;
    font-weight: 500;
    flex-wrap: wrap;
}
.works__card-tag-sep {
    width: 3.07px; height: 3.07px;
    background: var(--color-accent);
    border-radius: 50%;
    display: inline-block;
}
.works__paging {
    display: flex; justify-content: center; align-items: center;
    gap: 14px; margin-top: 60px;
}
.works__page-dot {
    width: 8px; height: 8px; border-radius: 50%;
    background: #d4d4d4; border: 0; cursor: pointer; padding: 0;
    transition: transform .2s ease, background .2s ease;
}
.works__page-dot.is-active {
    background: var(--color-text); transform: scale(1.4);
}

/* =========================================================
   PORTFOLIO DETAIL — Figma 96:956
   ========================================================= */
.work-detail {
    position: relative;
    padding: 100px 40px 120px;
    max-width: 1280px;
    margin: 0 auto;
}
.work-detail__year {
    font-size: 14.985px;
    font-weight: 400;
    color: var(--color-text);
    text-transform: capitalize;
    margin: 0 0 16px;
    line-height: 1.5;
}
.work-detail__title {
    font-size: 66.667px;
    font-weight: 400;
    line-height: 1.086;
    letter-spacing: -0.005em;
    margin: 0 0 12px;
    max-width: 894px;
}
.work-detail__sub {
    font-size: 21.333px;
    font-weight: 500;
    color: rgba(35, 31, 32, 0.65);
    margin: 0 0 60px;
}
.work-detail__hero {
    position: relative;
    aspect-ratio: 1200 / 615;
    border-radius: 0;
    overflow: hidden;
    background: #1a1a1a;
    margin-bottom: 100px;
}
.work-detail__hero img,
.work-detail__hero video {
    width: 100%; height: 100%; object-fit: cover; display: block;
}
/* Play button swaps the poster for a YouTube/Vimeo iframe in place (main.js). */
.work-detail__hero iframe {
    position: absolute; inset: 0; width: 100%; height: 100%; border: 0;
}
.work-detail__hero-play {
    position: absolute; inset: 0; margin: auto;
    width: 100px; height: 100px; border-radius: 50%;
    background: rgba(255, 255, 255, 0.85);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer; border: 0;
    backdrop-filter: blur(2px);
    transition: transform .25s ease, background .25s ease;
}
.work-detail__hero-play:hover { transform: scale(1.08); background: #fff; }
.work-detail__hero-play::before {
    content: ""; width: 0; height: 0; margin-left: 6px;
    border-left: 22px solid #000;
    border-top: 14px solid transparent;
    border-bottom: 14px solid transparent;
}
.work-detail__hero-tag {
    position: absolute; top: 16px; right: 16px;
    background: var(--color-primary); color: #fff;
    font-weight: 700; font-size: 14px;
    padding: 8px 10px; border-radius: 3px;
    line-height: 1;
}

.work-detail__overview {
    display: grid;
    grid-template-columns: 1fr 1.6fr;
    gap: 80px;
    margin-bottom: 60px;
}
.work-detail__overview-h {
    font-size: 26px;
    font-weight: 600;
    line-height: 1.5;
    margin: 0;
    color: var(--color-text);
}
.work-detail__overview-body p {
    font-size: 14.667px;
    line-height: 1.5;
    color: var(--color-text);
    margin: 0 0 20px;
}
.work-detail__overview-body p:last-child { margin-bottom: 0; }
/* v2.12.137 — TABLET: stack "The Overview" like mobile (title on top,
   description below) across the whole tablet band. It already stacked at
   ≤900 (see the max-width:900 block); extend that up to 1240 so iPad
   landscape (1024/1180) stacks too instead of staying 2-column. Desktop
   (≥1241) keeps the 1fr 1.6fr side-by-side. Placed before the ≤768/≤600
   gap overrides so those still win on phones. */
@media (max-width: 1240px) {
    .work-detail__overview { grid-template-columns: 1fr; gap: 28px; }
}

.work-detail__phones {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 28px;
    margin-bottom: 80px;
}
.work-detail__phones > div {
    aspect-ratio: 583 / 328;
    background: #f0f0f0;
    border-radius: 0;
    overflow: hidden;
}
.work-detail__phones img {
    width: 100%; height: 100%; object-fit: cover;
}

.work-detail__section-h {
    font-size: 26px;
    font-weight: 600;
    line-height: 1.5;
    margin: 0 0 32px;
    color: var(--color-text);
}

.work-detail__storyboard {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-bottom: 80px;
}
.work-detail__storyboard > div {
    aspect-ratio: 285 / 161;
    background: #d9d9d9;
    border-radius: 0;
}

/* Section wrapper — shared spacing for Storyboard / Styleframes / 3D. */
.work-detail__section { margin-bottom: 80px; }

.work-detail__styleframes,
.work-detail__3d {
    display: grid;
    gap: 20px;
}
.work-detail__sf-2col {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}
.work-detail__sf-2col > div {
    aspect-ratio: 590 / 334;
    background: #d9d9d9;
    border-radius: 0;
}
.work-detail__sf-3col {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
}
.work-detail__sf-3col > div {
    aspect-ratio: 386 / 219;
    background: #d9d9d9;
    border-radius: 0;
}
.work-detail__sf-6col,
.work-detail__3d-6col {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 14px;
}
.work-detail__sf-6col > div,
.work-detail__3d-6col > div {
    aspect-ratio: 183 / 103;
    background: #d9d9d9;
    border-radius: 0;
}
.work-detail__3d-4col {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
}
.work-detail__3d-4col > div {
    aspect-ratio: 285 / 162;
    background: #d9d9d9;
    border-radius: 0;
}
/* Photo fills each fixed frame, cropped to fit (size frame first, then crop). */
.work-detail__storyboard > div,
.work-detail__sf-2col > div,
.work-detail__sf-3col > div,
.work-detail__sf-6col > div,
.work-detail__3d-6col > div,
.work-detail__3d-4col > div {
    overflow: hidden;
}
.work-detail__storyboard > div img,
.work-detail__sf-2col > div img,
.work-detail__sf-3col > div img,
.work-detail__sf-6col > div img,
.work-detail__3d-6col > div img,
.work-detail__3d-4col > div img {
    width: 100%; height: 100%; object-fit: cover; display: block;
}

/* Balanced grids (storyboard / styleframes / category) — fixed 16:9 cells,
   column count chosen in PHP so rows stay even with no lonely orphan. */
.work-detail__balgrid {
    display: grid;
    gap: 16px;
    margin-bottom: 20px;
}
.work-detail__balgrid:last-child { margin-bottom: 0; }
.work-detail__balgrid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.work-detail__balgrid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.work-detail__balgrid.cols-4 { grid-template-columns: repeat(4, 1fr); }
.work-detail__balgrid.cols-5 { grid-template-columns: repeat(5, 1fr); }
.work-detail__balgrid.cols-6 { grid-template-columns: repeat(6, 1fr); }
.work-detail__balcell {
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: 0;
    background: #d9d9d9;
}
.work-detail__balcell img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* v2.9.79 — portfolio detail photos are click-to-zoom (overview / storyboard /
   styleframes / category frames). The JS lightbox shows the full-res image. */
.wd-frame { cursor: zoom-in; }
.wd-lightbox {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4vmin;
    background: rgba(10, 10, 12, 0.92);
    opacity: 0;
    visibility: hidden;
    transition: opacity .28s ease, visibility .28s ease;
    cursor: zoom-out;
}
.wd-lightbox.is-open { opacity: 1; visibility: visible; }
.wd-lightbox img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    box-shadow: 0 24px 80px -20px rgba(0, 0, 0, 0.7);
    transform: scale(.96);
    transition: transform .28s cubic-bezier(.2,.7,.2,1);
}
.wd-lightbox.is-open img { transform: scale(1); }
.wd-lightbox__close {
    position: absolute;
    top: 18px; right: 24px;
    width: 44px; height: 44px;
    border: 0; background: transparent;
    color: #fff; font-size: 34px; line-height: 1;
    cursor: pointer;
    opacity: .85;
}
.wd-lightbox__close:hover { opacity: 1; }
/* feedback P3 — prev/next arrows for stepping through a gallery in the lightbox. */
.wd-lightbox__nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 56px; height: 56px;
    border: 0;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    font-size: 40px; line-height: 1;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    border-radius: 50%;
    opacity: .85;
    transition: background-color .2s ease, opacity .2s ease;
    z-index: 2;
}
.wd-lightbox__nav:hover { background: rgba(255, 255, 255, 0.25); opacity: 1; }
.wd-lightbox__nav--prev { left: 24px; }
.wd-lightbox__nav--next { right: 24px; }
@media (max-width: 600px) {
    .wd-lightbox__nav { width: 44px; height: 44px; font-size: 30px; }
    .wd-lightbox__nav--prev { left: 10px; }
    .wd-lightbox__nav--next { right: 10px; }
}
@media (max-width: 1024px) {
    .work-detail__balgrid.cols-4,
    .work-detail__balgrid.cols-5,
    .work-detail__balgrid.cols-6 { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 600px) {
    .work-detail__balgrid.cols-3,
    .work-detail__balgrid.cols-4,
    .work-detail__balgrid.cols-5,
    .work-detail__balgrid.cols-6 { grid-template-columns: repeat(2, 1fr); }
}

/* "The Results" — self-hosted result videos, 2-col, natural height. */
.work-detail__videos {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}
.work-detail__videos video {
    width: 100%;
    height: auto;
    display: block;
    border-radius: 0;
    background: #000;
}
@media (max-width: 700px) {
    .work-detail__videos { grid-template-columns: 1fr; }
}

/* Portfolio CTA (reuses .ai-bottom-cta) + bottom nav (back + next project). */
.work-detail__cta { margin: 110px auto 0; padding-bottom: clamp(50px, 7vw, 90px); }

/* Bottom-CTA blue glow (portfolio + blog single only; AI page keeps its aurora).
   Pure-CSS blue blob whose CENTRE is moved to the cursor point by JS translate3d
   (GPU-cheap, no per-frame re-blur). margin:-450px puts the element centre at the
   section (0,0) origin, so translate(x,y) places the glow centre at (x,y).
   Section is overflow:visible so the glow can follow the cursor past the box. */
.work-detail__cta.ai-bottom-cta { overflow: visible; }
/* v2.12.123 — tighten the big empty top gap above the portfolio/blog closing CTA
   (the cursor-glow one): the nav row → headline space was ~310px (margin 150 +
   padding-top up to 160). DESKTOP only; scoped to .work-detail__cta so the AI
   page's standalone .ai-bottom-cta spacing stays as-is. Mobile (<=768) untouched. */
@media (min-width: 769px) {
    /* v2.12.170 — top gap = margin-top 40 + padding-top clamp(28,60). The CTA is the
       LAST section in its article container (.work-detail / .article), whose 120/80px
       bottom padding stacked UNDER the CTA made the footer gap ~2× the top. So: CTA
       padding-bottom = padding-top (symmetric), AND trim the container bottom to 40
       (= the CTA margin-top) → total CTA→footer gap = 40 + clamp = the top gap. */
    .work-detail__cta.ai-bottom-cta { margin-top: 40px; padding-top: clamp(28px, 3vw, 60px); padding-bottom: clamp(28px, 3vw, 60px); }
    .work-detail, .article { padding-bottom: 40px; }
}
.work-detail__cta__bg {
    position: absolute;
    top: 0;
    left: 0;
    width: 900px;
    height: 900px;
    margin: -450px 0 0 -450px;
    z-index: 0;
    pointer-events: none;
    border-radius: 50%;
    background: radial-gradient(circle 450px at center,
        rgba(56, 135, 255, 0.32) 0%,
        rgba(56, 135, 255, 0.14) 40%,
        rgba(56, 135, 255, 0) 70%);
    filter: blur(55px);
    transform: translate3d(0, 0, 0);
    will-change: transform;
}
.work-detail__cta-line {
    display: block;
    width: clamp(180px, 28vw, 360px);
    height: 1px;
    margin: 0 auto clamp(28px, 4vw, 48px);
    background: rgba(35, 31, 32, 0.18);
    position: relative;
    z-index: 1;
}

/* CTA typography (portfolio + blog single only — AI page keeps its own sizes).
   campaign / story / experience are <em> → italic; colour kept black here
   (the AI page's em rule tints them accent). */
.work-detail__cta .ai-bottom-cta__title { font-size: 52px; font-weight: 500; font-family: var(--font-sans); }
/* campaign / story / experience: italic SEMI-BOLD (the rest of the headline stays
   medium 500); colour kept black here (the AI-page em rule tints it accent). Force
   Figtree so the italic words don't fall back to a system italic. */
.work-detail__cta .ai-bottom-cta__title em { color: inherit; font-weight: 600; font-style: italic; font-family: var(--font-sans); }
.work-detail__cta .ai-bottom-cta__lede { font-size: 18px; }
/* Blog single only: the CTA headline was 66px = LARGER than the article
   headline (52px), so the closing CTA out-shouted the page title. Bring it down
   to match the .article__title scale so the article headline stays the biggest
   element. Scoped under .article → the portfolio CTA keeps 66px (= its own
   66.667px page title). Responsive steps mirror .article__title (40/34/28). */
.article .work-detail__cta .ai-bottom-cta__title { font-size: 52px; }
@media (max-width: 600px) {
    .work-detail__cta .ai-bottom-cta__title { font-size: 40px; }
    .article .work-detail__cta .ai-bottom-cta__title { font-size: 28px; }
    .ai-bottom-cta__title { font-size: 40px; }
}
.work-detail__nav {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 24px;
    flex-wrap: wrap;
    margin-top: 90px;
}
.work-detail__back { text-decoration: none; color: var(--color-text); font-weight: 500; font-size: 24px; } /* feedback — bigger */
.work-detail__back:hover { color: var(--color-primary); }
.work-detail__next { margin-left: auto; text-align: right; text-decoration: none; max-width: 60%; }
.work-detail__next-label { display: block; font-weight: 600; font-size: 24px; color: var(--color-primary); } /* feedback — bigger (14→24) */
.work-detail__next-title { display: block; font-size: 16px; color: rgba(35, 31, 32, 0.5); line-height: 1.4; margin-top: 4px; } /* feedback — bigger (12→16) */
.work-detail__next:hover .work-detail__next-title { color: rgba(35, 31, 32, 0.75); }
@media (max-width: 600px) {
    /* v2.12.120 — Back + Next on ONE row (not stacked) at 18px so they're side-by-side,
       aligned to their margins (Back left, Next right) — no zig-zag. Fonts per user
       paste; mobile-scoped so desktop stays 24px. */
    .work-detail__nav { flex-direction: row; align-items: flex-start; }
    .work-detail__next { margin-left: auto; align-self: auto; text-align: right; max-width: 55%; }
    .work-detail__back { font-size: 18px; }
    .work-detail__next-label { font-size: 18px; }
    .work-detail__next-title { font-size: 14px; }
}

/* "On this page" sticky table-of-contents rail on single posts.
   Fixed to the left gutter; fades in once you scroll past the hero and
   hides again as you reach the bottom CTA. Auto-built from the article's
   H2/H3 headings by the inline script in single.php. */
.article-toc {
    position: fixed;
    /* v2.12.162/167 — anchored at a FIXED top. The "ON THIS PAGE" eyebrow stays put;
       ONLY the heading list below it scrolls (flex column: eyebrow = fixed row,
       .article-toc__list = the scroll area). Long lists auto-follow the active heading
       via JS (single.php) so the highlight is always visible. Header never moves. */
    top: 120px;
    left: clamp(20px, 4vw, 56px);
    width: clamp(190px, 17vw, 250px);
    max-height: calc(100vh - 160px);
    display: flex;
    flex-direction: column;
    z-index: 900;
    opacity: 0;
    visibility: hidden;
    transition: opacity .4s ease, visibility .4s ease;
}
.article-toc.is-visible { opacity: 1; visibility: visible; }
/* When the list is taller than 80vh (many/long headings) it scrolls with a
   hidden scrollbar — fade the bottom edge so the last item softens out instead
   of hard-cropping mid-line. Class toggled by the TOC script when it overflows. */
/* v2.12.167 — when the LIST overflows (JS toggles this on the toc), fade its bottom
   edge so the last visible item softens instead of hard-cropping. The eyebrow stays
   fixed above it — the earlier "raise the whole rail" (v2.12.165) was removed because
   the header must NOT move; only the list scrolls. */
.article-toc.is-scrollable .article-toc__list {
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 32px), transparent 100%);
            mask-image: linear-gradient(to bottom, #000 calc(100% - 32px), transparent 100%);
}
.article-toc__eyebrow {
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(35, 31, 32, 0.5);
    /* v2.12.167 — a fixed flex row at the top; the list below is what scrolls, so the
       "ON THIS PAGE" header never moves. */
    flex: 0 0 auto;
    margin: 0 0 20px;
}
.article-toc__list {
    list-style: none; margin: 0; padding: 0;
    /* the ONLY scrolling part of the rail; position:relative so the JS auto-scroll
       (li.offsetTop) is measured against the list, not the whole rail. */
    position: relative;
    flex: 1 1 auto; min-height: 0;
    overflow-y: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
.article-toc__list::-webkit-scrollbar { width: 0; height: 0; }
.article-toc__item { margin-bottom: 18px; }
.article-toc__item:last-child { margin-bottom: 0; }
.article-toc__link {
    /* clamp long headings to 2 lines + ellipsis so each item stays compact and
       the whole rail fits the viewport (was wrapping to 3-4 lines → overflow). */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    font-size: 14px;
    line-height: 1.45;
    color: rgba(35, 31, 32, 0.55);
    text-decoration: none;
    padding-left: 14px;
    border-left: 2px solid transparent;
    transition: color .2s ease, border-color .2s ease;
}
.article-toc__item--h3 .article-toc__link { padding-left: 28px; font-size: 18px; }
.article-toc__link:hover { color: var(--color-text); }
.article-toc__item.is-active .article-toc__link {
    color: var(--color-text);
    font-weight: 600;
    border-left-color: var(--color-primary);
}
@media (max-width: 1180px) { .article-toc { display: none; } }

/* "Share" sticky rail on the right gutter — mirror of the TOC. Social links
   + copy-link + back-to-top. Same fade-in timing as the TOC. */
.article-share {
    position: fixed;
    /* v2.12.162 — top-anchored to mirror the TOC (was centred), so both rails line
       up near the top instead of drifting to the middle. */
    top: 120px;
    right: clamp(20px, 4vw, 56px);
    z-index: 900;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 9px;
    opacity: 0;
    visibility: hidden;
    transition: opacity .4s ease, visibility .4s ease;
}
.article-share.is-visible { opacity: 1; visibility: visible; }
.article-share__label {
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    text-transform: uppercase;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.2em;
    color: rgba(35, 31, 32, 0.5);
    margin-bottom: 4px;
}
.article-share__btn {
    width: 34px; height: 34px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 9px;
    background: rgba(35, 31, 32, 0.05);
    color: var(--color-text);
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    transition: background .2s ease, color .2s ease, transform .2s ease;
}
.article-share__btn svg { width: 15px; height: 15px; display: block; }
.article-share__btn:hover { background: var(--color-primary); color: #fff; transform: translateY(-1px); }
.article-share__divider { width: 3px; height: 3px; border-radius: 50%; background: rgba(35, 31, 32, 0.22); margin: 3px 0; }
.article-share.is-copied .article-share__btn[data-copy-link] { background: #2e7d32; color: #fff; }
@media (max-width: 1180px) { .article-share { display: none; } }

/* Hero-video lightbox modal — shared by all portfolio detail pages.
   Body gets [data-video-open] when open so we can lock scroll. */
.video-modal {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.video-modal[hidden] { display: none !important; }
.video-modal.is-open { display: flex; }
.video-modal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(10, 10, 14, 0.86);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    cursor: pointer;
    animation: video-modal-fade .25s ease;
}
.video-modal__panel {
    position: relative;
    width: min(1200px, 96vw);
    max-height: 88vh;
    aspect-ratio: 16 / 9;
    border-radius: 10px;
    overflow: hidden;
    background: #000;
    box-shadow: 0 30px 80px rgba(0, 0, 0, .45);
    animation: video-modal-pop .35s cubic-bezier(.2, .7, .2, 1);
}
.video-modal__player {
    width: 100%;
    height: 100%;
    display: block;
    background: #000;
}
/* YouTube/Vimeo embeds open in an iframe inside the same panel (main.js injects it). */
.video-modal__iframe {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    border: 0; display: block; background: #000;
}
.video-modal__close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 0;
    background: rgba(255, 255, 255, .92);
    color: #000;
    font-size: 26px;
    line-height: 1;
    cursor: pointer;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background .2s ease, transform .2s ease;
}
.video-modal__close:hover { background: #fff; transform: scale(1.06); }
body[data-video-open] { overflow: hidden; }
@keyframes video-modal-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes video-modal-pop {
    from { opacity: 0; transform: translateY(20px) scale(.96); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
@media (max-width: 600px) {
    .video-modal { padding: 12px; }
    .video-modal__close { top: 8px; right: 8px; width: 34px; height: 34px; font-size: 22px; }
}

/* =========================================================
   BLOG LISTING — Figma 96:1049 ("News, Article & Insights")
   ========================================================= */
.news {
    position: relative;
    /* v2.7.0 — wider gutters + roomier top/bottom per user request.
       v2.7.69 — bottom slimmed because pagination now carries the
       extra margin-top, putting the numbers close to the footer. */
    padding: clamp(110px, 14vh, 150px) clamp(56px, 6.5vw, 100px) clamp(70px, 9vh, 110px);
    max-width: 1280px;
    margin: 0 auto;
}
/* v2.11.67 — fill the empty side gutters on large monitors. Laptops
   (≤1500px) keep the 1280 cap untouched; wider screens grow to 90vw
   (capped 1760px) so the grid isn't stranded in the centre.
   v2.11.68 — same for the /portfolios/ "Selected Works" page.
   v2.11.69 — site-wide sweep: portfolio single + AI landing sections.
   Deliberately EXCLUDED: .article (blog reading column) and .contact
   (form) — a centred column reads better there, so they stay at 1280. */
@media (min-width: 1500px) {
    .news,
    .works,
    .work-detail,
    .ai-hero__inner,
    .ai-porto,
    .ai-approach__inner,
    .ai-howit,
    .ai-compare,
    .ai-wishform__inner { max-width: min(90vw, 1760px); }
}
.news__head {
    display: grid;
    grid-template-columns: 1fr 400px;
    gap: 80px;
    align-items: end;
    /* v2.7.0 — wider breathing room above featured cards. */
    margin-bottom: 100px;
}
.news__title {
    font-size: 97.333px;
    font-weight: 400;
    line-height: 0.905;
    letter-spacing: -0.01em;
    margin: 0;
    color: var(--color-text);
}
.news__title-line2 {
    display: block;
    font-weight: 500;
    color: rgba(35, 31, 32, 0.65);
}
.news__intro {
    font-size: 18px; /* feedback — landing right-side intro +2pt so it isn't dwarfed by the headline (14.985→18) */
    line-height: 1.5;
    margin: 0;
    color: var(--color-text);
}

.news__featured {
    display: grid;
    grid-template-columns: 1fr 1fr;
    /* v2.7.0 — wider gap between featured + extra breathing under.
       v2.7.69 — bumped per user request for more breathing room. */
    gap: 60px;
    margin-bottom: 130px;
}
.news__featured-card { display: block; cursor: pointer; }
.news__featured-thumb {
    aspect-ratio: 585 / 329;
    overflow: hidden;
    border-radius: 0;
    background: #eaeaea;
    margin-bottom: 18px;
}
.news__featured-thumb img {
    width: 100%; height: 100%; object-fit: cover;
    transition: transform .6s cubic-bezier(.2,.7,.2,1);
}
.news__featured-card:hover .news__featured-thumb img { transform: scale(1.04); }
.news__featured-title {
    font-size: 24px; /* feedback B1 — blog featured title +2pt (21→24) */
    font-weight: 500;
    line-height: 1.5;
    margin: 0 0 10px;
    color: var(--color-text);
}
.news__featured-meta,
.news__card-meta {
    display: flex;
    align-items: center;
    gap: 6.5px;
    font-size: 16px; /* feedback B1 — blog card meta 14.489→16 */
    font-weight: 500;
}
.news__meta-date { color: rgba(35, 31, 32, 0.65); }
.news__meta-dot { width: 4px; height: 4px; border-radius: 50%; background: rgba(35, 31, 32, 0.5); }
.news__meta-cat { color: var(--color-accent); }

.news__grid {
    display: grid;
    /* v2.11.64 — uniform 3×3 grid (3 columns, 9 cards) per user request;
       all cards use the 16:9 thumb + smaller title style. */
    grid-template-columns: repeat(3, 1fr);
    gap: 64px 40px;
}
.news__card { display: block; cursor: pointer; }
.news__card-thumb {
    aspect-ratio: 16 / 9; /* feedback — 16:9 so the SuperPixel watermark/logo in the thumbnail isn't cropped (was 3/2) */
    overflow: hidden;
    border-radius: 0;
    background: #eaeaea;
    margin-bottom: 14px;
}
.news__card-thumb img {
    width: 100%; height: 100%; object-fit: cover;
    transition: transform .6s cubic-bezier(.2,.7,.2,1);
}
.news__card:hover .news__card-thumb img { transform: scale(1.04); }

/* Sample-mode pages 2–4: "Coming Soon" placeholder thumb (no image). */
.news__thumb--placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background:
        repeating-linear-gradient(135deg, rgba(35,31,32,0.04) 0 12px, rgba(35,31,32,0.07) 12px 24px),
        #e9e9e9;
}
.news__placeholder-label {
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(35, 31, 32, 0.55);
}
.news__card-thumb.news__thumb--placeholder .news__placeholder-label { font-size: 10px; }

.news__card-title {
    font-size: 18px; /* feedback B1 — blog card title (→18) */
    font-weight: 500;
    line-height: 1.5;
    margin: 0 0 6px;
    color: var(--color-text);
}

.news__card-meta {
    font-size: 15px; /* feedback — blog card date + category +2pt (12→15) */
    gap: 6.5px;
}
.news__card-meta .news__meta-dot { width: 3px; height: 3px; }

.news__paging {
    display: flex;
    justify-content: center;
    align-items: center;
    /* v2.11.70 — pagination enlarged: 20px numbers in 40px frames, wider gap. */
    gap: 24px;
    /* v2.7.69 — pushed pagination further down toward the footer
       so the numbered row reads as a closing anchor, not midpage. */
    margin-top: 160px;
}
.news__paging .page-numbers,
.news__paging-num {
    display: inline-flex;
    width: 40px; height: 40px;
    align-items: center; justify-content: center;
    border-radius: 50%;
    font-size: 20px;
    font-weight: 500;
    color: var(--color-text);
    text-decoration: none;
    background: transparent;
    transition: background .2s ease, color .2s ease;
}
.news__paging .page-numbers:hover,
.news__paging-num:hover { background: rgba(35, 31, 32, 0.06); }
.news__paging .page-numbers.current,
.news__paging-num.is-active {
    background: var(--color-text);
    color: #fff;
}
.news__paging-arrow {
    display: inline-flex; width: 40px; height: 40px;
    align-items: center; justify-content: center;
    color: var(--color-text);
}
.news__paging-arrow::before {
    content: ""; width: 0; height: 0;
    border-top: 8px solid transparent;
    border-bottom: 8px solid transparent;
    border-left: 11px solid currentColor;
}

/* =========================================================
   BLOG ARTICLE / SINGLE — Figma 96:1261
   ========================================================= */
.article {
    position: relative;
    /* Figma 96:1261 — MAINPAGE container at top:173 from page top.
       Sides at left:35 / right:35. */
    padding: 173px 35px 80px;
    max-width: 1280px;
    margin: 0 auto;
    overflow: visible;
}
/* Figma 96:1262 — blurred BG_ABOUT US gradient at the top of the article.
   Sized 1281×592 (aspect 132/61), 65% opacity, blur 53.282px. The Figma
   node imports a baked image (imgBgAboutUs); we recreate the same multi-
   blob radial wash with pure CSS so we don't depend on a 7-day-expiring
   asset URL — same palette as .about::before for visual consistency. */
.article__bg {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 1281px;
    max-width: 100vw;
    height: 592px;
    aspect-ratio: 132 / 61;
    opacity: 0.65;
    filter: blur(53.282px);
    pointer-events: none;
    z-index: 0;
    background:
        radial-gradient(circle closest-side at 80% 32%, rgba(74, 222, 128, 0.55), transparent 100%),
        radial-gradient(circle closest-side at 82% 70%, rgba(96, 165, 250, 0.60), transparent 100%),
        radial-gradient(circle closest-side at 55% 50%, rgba(167, 139, 250, 0.28), transparent 100%),
        radial-gradient(circle closest-side at 18% 75%, rgba(236, 72, 153, 0.30), transparent 100%);
}
/* Lift all article content above the .article__bg layer. The fixed TOC rail
   is excluded — it manages its own position/z-index and must NOT be forced
   into the normal flow (else it eats vertical space and pushes content down). */
.article > *:not(.article__bg):not(.article-toc):not(.article-share) { position: relative; z-index: 1; }
.article__head {
    display: grid;
    grid-template-columns: 1fr 200px;
    gap: 40px;
    align-items: start;
    margin-bottom: 50px;
}
.article__title {
    font-size: 52px;
    font-weight: 400;
    line-height: 1.2;
    letter-spacing: -0.01em;
    margin: 0;
    max-width: 817px;
    color: var(--color-text);
}
.article__meta {
    text-align: left;
    padding-top: 22px;
    font-size: 18px;
    line-height: 1.5;
    color: var(--color-text);
}
.article__meta-date { font-weight: 400; display: block; margin-bottom: 6px; }
.article__meta-tag { color: rgba(35, 31, 32, 0.65); font-weight: 500; }
.article__hero {
    position: relative;
    aspect-ratio: 1200 / 675;
    overflow: hidden;
    border-radius: 0;
    background: #1a1a1a;
    margin-bottom: 80px;
    max-width: 1200px;
    margin-left: auto; margin-right: auto;
}
.article__hero img,
.article__hero video {
    width: 100%; height: 100%; object-fit: cover; display: block;
}

.article__body {
    max-width: 700px;
    margin: 0 auto;
    font-size: 18px;
    line-height: 1.7;
    color: var(--color-text);
    font-family: var(--font-sans);
}
/* v2.12.121 — mobile/tablet (<1180px, where the TOC/share side rails are hidden):
   the blog body fills the column to the page gutter (20px) instead of sitting as a
   700px centred strip, so its RIGHT margin reaches the GET-A-QUOTE header line —
   matching the portfolio article. Desktop (>=1180, with the rails) keeps the
   centred reading column unchanged. */
@media (max-width: 1180px) {
    .article__body { max-width: none; margin: 0; }
}
/* v2.12.148 / v2.12.154 — DESKTOP with the side rails visible (≥1181). The fixed
   "ON THIS PAGE" TOC (~250px wide) sits in the LEFT gutter; because the reading
   column is CENTRED, on narrower desktops the left gap (TOC→body) shrank to almost
   nothing while the right gap (body→SHARE) stayed large — the body read as cramped
   INTO the TOC ("mepet"). Scale the reading column with the viewport so the body
   ALWAYS keeps a comfortable gap from the TOC. `min()` caps at the 700px design
   width on wide screens, and shrinks it below that so the gutters stay clear on
   BOTH sides. ≤1180 has no rails → its own rule (max-width:none) applies.
   v2.12.159 — the 720px reserve still read too tight beside the TOC (esp. ~1440–1560
   where the body hit the 700 cap and the left gap fell to ~54px). Widen the reserve
   to 860 so the left gap holds ≥~124px across the band, and add a 460px FLOOR so the
   column doesn't get too narrow on smaller desktops (~1181–1330). */
@media (min-width: 1181px) {
    /* v2.12.163 — user: the gap TOC→body should EQUAL the gap body→SHARE. The left
       rail (TOC, ~250px) is much wider than the right rail (SHARE, ~34px), so a
       centred column left a bigger void on the right. Widen the reading column (up
       to 900) AND nudge it right toward the SHARE side by ~half the rail-width
       difference, so BOTH gaps stay equal across the desktop band. translateX keeps
       the shift responsive without disturbing the full-width title/hero. */
    .article__body {
        max-width: clamp(460px, calc(100vw - 700px), 900px);
        transform: translateX(clamp(70px, 7vw, 105px));
    }
    /* keep the Recent Posts / Writer block (also a narrow centred column) shifted
       with the body so the reading column stays aligned end-to-end. */
    .article-extra { transform: translateX(clamp(70px, 7vw, 105px)); }
}
/* v2.12.153 — TABLET top gap. The base .article padding-top is 173px (desktop
   Figma value) and only dropped to 60px at ≤768 — so the whole 769–1180 tablet
   band inherited a ~173px empty strip under the fixed navbar. Bring it in line
   with the ≤768 rhythm (and trim the oversized hero/head gaps to match). Desktop
   (≥1181) keeps the Figma spacing; phones (≤768) keep their own block. */
@media (min-width: 769px) and (max-width: 1180px) {
    .article { padding: 84px 32px 72px; }
    /* v2.12.153 — TABLET-ONLY "header lock" gap. Give the masthead (title + meta)
       a generous, even gap down to the article content — matching the breathing
       room the body has to the share icons on the right (per feedback). Desktop
       untouched. */
    .article__head { margin-bottom: 56px; }
    .article__hero { margin-bottom: 56px; }
}
/* v2.12.84 — force Figtree across the whole blog body. Legacy Squarespace-imported
   posts carry inline `font-family` on <p>/<span>/headings (and on .sqs-html-content)
   that override inheritance, so the body must win with the site font everywhere. */
.article__body,
.article__body * { font-family: var(--font-sans) !important; }
/* v2.12.153 — even paragraph rhythm. Uniform gap on every new paragraph (was 20px,
   felt cramped/uneven next to the heading spacing). Mobile keeps its own smaller
   values in the ≤768 / ≤480 blocks below. */
.article__body p { margin: 0 0 24px; line-height: 1.7; }
.article__body p:last-child { margin-bottom: 0; }
/* Safety: any paragraph/heading that ends up empty (stray Squarespace break) must
   not add a phantom gap — applied at every width, not just phones. */
.article__body p:empty,
.article__body h1:empty,
.article__body h2:empty,
.article__body h3:empty,
.article__body h4:empty { display: none !important; margin: 0 !important; }
/* v2.11.73 — normalise ~80 legacy Squarespace-imported posts. They carry
   <div class="sqs-html-content"> wrappers + <p style="white-space:pre-wrap">
   inline styles that made their paragraphs wrap/space differently from the
   clean Gutenberg posts. Strip the foreign layout so every post reads uniform. */
.article__body .sqs-html-content {
    display: block;
    max-width: none;
    margin: 0;
    padding: 0;
    font: inherit;
}
.article__body p,
.article__body .sqs-html-content p { white-space: normal !important; }
/* v2.11.74 — also normalise the Squarespace IMAGE blocks in those old posts.
   Squarespace uses an intrinsic-ratio trick (a container with inline
   padding-bottom + an absolutely-positioned img). Our theme forces img to
   width:100%/static, so that padding-bottom became a big empty gap. Kill the
   spacer and give the image block the same 36px rhythm as a clean figure. */
.article__body .image-block-outer-wrapper,
.article__body figure.sqs-block-image-figure {
    margin: 36px 0 !important;
    max-width: 100% !important;
    padding: 0;
}
.article__body .image-block-wrapper,
.article__body .sqs-block-content { margin: 0; padding: 0; }
.article__body .sqs-image-shape-container-element {
    padding-bottom: 0 !important;
    height: auto !important;
    position: static !important;
}
.article__body .sqs-image-shape-container-element img,
.article__body .sqs-block-image-figure img {
    position: static !important;
    width: 100%;
    height: auto;
    display: block;
}
/* v2.11.76 — heading rhythm modelled on growandbless.com/biaya-website:
   BIG gap above a heading (separates it from the previous body text), and a
   tight gap below = the SAME as the paragraph gap (1.75rem), so heading→body
   reads as one block. Heading line-heights tightened (1.8 was too airy). */
.article__body h1 {
    font-size: 40px;
    font-weight: 700;
    line-height: 1.25;
    margin: 56px 0 24px;
}
.article__body h2 {
    font-size: 30px;
    font-weight: 600;
    line-height: 1.3;
    margin: 48px 0 20px;
}
.article__body h3 {
    font-size: 24px;
    font-weight: 600;
    line-height: 1.35;
    margin: 40px 0 18px;
}
.article__body h4 {
    font-size: 20px;
    font-weight: 600;
    line-height: 1.4;
    margin: 32px 0 16px;
}
/* first heading flush with the top — no stray gap at the start of a post */
.article__body > h1:first-child,
.article__body > h2:first-child,
.article__body > h3:first-child,
.article__body > h4:first-child { margin-top: 0; }
/* v2.12.153 — UNIFORM bold in the blog body. Legacy Squarespace-imported posts
   carry mixed inline font-weights (700 / 800 / 900-"black") on <strong>/<b> and on
   inline <span style="font-weight:…">, so emphasised words rendered heavier in some
   posts than others — a few came out fully black. Force ONE weight everywhere (700,
   the standard bold, matching the site) so every bold reads the same and never black.
   Normal (400/500) inline weights are left alone. */
.article__body strong,
.article__body b,
.article__body strong *,
.article__body b *,
.article__body [style*="font-weight: 700"], .article__body [style*="font-weight:700"],
.article__body [style*="font-weight: 800"], .article__body [style*="font-weight:800"],
.article__body [style*="font-weight: 900"], .article__body [style*="font-weight:900"],
.article__body [style*="font-weight: bold"], .article__body [style*="font-weight:bold"] {
    font-weight: 700 !important;
}
.article__body ul,
.article__body ol { padding-left: 27px; margin: 0 0 20px; }
.article__body ul li,
.article__body ol li { margin-bottom: 4px; line-height: 1.7; }

/* Inline body links — clickable + blue highlight (every blog post). Underline
   offset 6px / 1px / skip-ink per the site link convention. Image, button and
   figure links stay un-tinted so CTA images & embeds are unaffected. */
.article__body a {
    color: var(--color-accent);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 6px;
    text-decoration-skip-ink: auto;
    transition: color .2s ease, text-decoration-color .2s ease;
}
.article__body a:hover,
.article__body a:focus-visible { color: var(--color-primary); }
.article__body a:has(img),
.article__body a.btn,
.article__body figure a {
    color: inherit;
    text-decoration: none;
}

.article__banner {
    position: relative;
    background: #d9d9d9;
    border-radius: 0;
    margin: 36px 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
.article__banner::before {
    content: attr(data-label);
    color: rgba(0, 0, 0, 0.2);
    font-size: 41px;
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}
.article__banner--247 { aspect-ratio: 700 / 120; }
.article__banner--169 { aspect-ratio: 700 / 350; }

/* feedback — embedded videos (YouTube/Vimeo oEmbed or a pasted iframe) inside a
   blog post render as a clean full-width 16:9 frame, matching the in-article
   image banners. Neutralises WP's padding-ratio wrapper so it isn't doubled. */
.article__body .wp-block-embed,
.article__body figure { margin: 36px 0; max-width: 100%; }
/* v2.12.82 — equal gap above/below an in-article banner or video: when a heading
   sits directly after one, its big top-margin would stack on the banner's bottom
   margin and make the lower gap look bigger. Drop it so both sides read equal. */
.article__body .wp-block-image + h2,
.article__body .wp-block-image + h3,
.article__body figure + h2,
.article__body figure + h3,
.article__body .wp-block-embed + h2,
.article__body .wp-block-embed + h3,
.article__body .yt-facade + h2,
.article__body .yt-facade + h3 { margin-top: 0; }
/* Body images always sit flush with the 700px text column — regardless of the
   size (Medium/Large/Full) picked at insert. Covers Gutenberg <figure> blocks,
   Classic-Editor [caption] wrappers (.wp-caption carries an inline width:NNNpx
   that we override), and plain inline <img>. yt-facade thumbs are excluded
   (different selector) so the 16:9 video facade keeps its own sizing. */
.article__body .wp-caption,
.article__body figure.wp-block-image,
.article__body figure.aligncenter,
.article__body figure.alignnone { width: 100% !important; max-width: 100%; }
.article__body .wp-caption img,
.article__body figure img,
.article__body p > img,
.article__body > img { display: block; width: 100%; height: auto; }
.article__body .wp-caption-text,
.article__body figcaption { width: 100%; }
.article__body .wp-block-embed__wrapper { position: relative; padding: 0; }
.article__body .wp-block-embed__wrapper::before { content: none; padding: 0; }
.article__body iframe {
    display: block; width: 100%; aspect-ratio: 16 / 9; height: auto; border: 0;
}
/* Body tables — any table (manual, or pasted from Word/Sheets) renders as a
   clean grid that fits the 700px column: zebra rows, a shaded header row, even
   borders. Inline column widths from pastes are neutralised (width:auto) so
   nothing overflows. On phones a wide table scrolls sideways instead of
   squashing the page. */
.article__body table {
    width: 100% !important;
    max-width: 100%;
    border-collapse: collapse;
    margin: 36px 0;
    font-size: 16px;
    line-height: 1.6;
    color: var(--color-text);
}
.article__body table th,
.article__body table td {
    border: 1px solid rgba(35, 31, 32, 0.14);
    padding: 12px 16px;
    text-align: left;
    vertical-align: top;
    width: auto !important;
    height: auto !important;
}
.article__body table thead th,
.article__body table thead td,
.article__body table tr:first-child th {
    background: #f4f4f4;
    font-weight: 600;
    color: #000;
}
.article__body table tbody tr:nth-child(even) td { background: rgba(35, 31, 32, 0.025); }
.article__body figure.wp-block-table { margin: 36px 0; max-width: 100%; overflow-x: auto; }
.article__body figure.wp-block-table > table { margin: 0; }
@media (max-width: 700px) {
    /* v2.12.45 — blog tables SLIDE sideways (like the AI Lab table). Cells get a min-width
       so the table is wider than the screen and the block scrolls, instead of squashing
       every column into per-word wraps. */
    .article__body table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .article__body table th,
    .article__body table td { padding: 10px 12px; min-width: 165px; white-space: normal; }
}
/* YouTube facade — lightweight thumbnail+play swapped in for the heavy player
   until the reader clicks (main.js). Cuts blog page-load dramatically. */
.yt-facade {
    display: block; position: relative; width: 100%; aspect-ratio: 16 / 9;
    margin: 36px 0; padding: 0; border: 0; cursor: pointer; background: #000; overflow: hidden;
}
.yt-facade__thumb { width: 100%; height: 100%; object-fit: cover; display: block; }
.yt-facade__play {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
    width: 72px; height: 50px; border-radius: 12px; background: rgba(20, 20, 20, .72);
    transition: background .2s ease;
}
.yt-facade:hover .yt-facade__play,
.yt-facade:focus-visible .yt-facade__play { background: #f00; }
.yt-facade__play::after {
    content: ""; position: absolute; left: 50%; top: 50%;
    transform: translate(-40%, -50%); width: 0; height: 0;
    border-left: 18px solid #fff; border-top: 11px solid transparent; border-bottom: 11px solid transparent;
}
.yt-facade__iframe { display: block; width: 100%; aspect-ratio: 16 / 9; height: auto; border: 0; margin: 36px 0; }

/* v2.7.13 — Article body images auto-wrapped with /contact/ link by JS.
   Slight hover lift so readers can tell the banner is clickable. */
.article__cta-img {
    display: block;
    cursor: pointer;
    transition: opacity .25s ease, transform .35s cubic-bezier(.2,.7,.2,1);
}
.article__cta-img:hover { opacity: 0.94; transform: translateY(-2px); }
.article__cta-img img { display: block; width: 100%; height: auto; }

/* =========================================================
   BLOG SINGLE — Writer + Recent posts (Figma 381:2271 / 381:2257)
   v2.11.16 — divider line (same look as the CTA line) → 32px →
   Writer block → 80px → Recent posts. Lives in the 700px body column.
   ========================================================= */
.article-extra { max-width: 700px; margin: 80px auto 0; }
.article-extra__line {
    display: block; width: 100%; height: 1px;
    background: rgba(35, 31, 32, 0.18);
    margin-bottom: 32px;
}
.article-writer { display: flex; align-items: flex-start; gap: 32px; }
.article-writer__photo {
    position: relative;
    flex: 0 0 140px; width: 140px; height: 140px;
    overflow: hidden; background: #d9d9d9;
}
/* Same recipe as the CTA portraits (v2.9.76): B&W idle solid underneath,
   color hover snaps on top (no opacity fade = no ghosting), and only the
   zoom-OUT animates (1.06 → 1.0, framing rule scale ≥ 1.0). */
.article-writer__img {
    position: absolute; inset: 0;
    width: 100%; height: 100%; object-fit: cover;
    object-position: center 25%;
    transform: translateZ(0) scale(1.06);
    transition: transform .6s cubic-bezier(.2,.7,.2,1);
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}
.article-writer__img--hover { opacity: 0; }
.article-writer__photo:hover .article-writer__img--hover { opacity: 1; }
.article-writer__photo:hover .article-writer__img { transform: translateZ(0) scale(1); }
.article-writer__eyebrow {
    margin: 0; font-size: 14px; line-height: 1.8;
    text-transform: uppercase; letter-spacing: .04em;
    color: var(--color-accent);
}
.article-writer__name { margin: 0 0 8px; font-size: 19px; font-weight: 600; line-height: 1.6; color: #000; }
.article-writer__name-link { color: inherit; text-decoration: none; transition: color .2s ease; }
.article-writer__name-link:hover { color: var(--color-accent); }
.article-writer__bio { margin: 0; font-size: 15px; line-height: 1.8; color: #535353; }
.article-recent { margin-top: 80px; }
.article-recent__title {
    margin: 0 0 24px; font-size: 28px; font-weight: 500;
    line-height: 1.8; text-transform: capitalize; color: #000;
}
.article-recent__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.article-recent__card { display: block; color: inherit; text-decoration: none; }
.article-recent__thumb {
    /* 16:9 thumbs; the 3-col 1fr grid keeps the row flush with the 700px
       article column on both sides. */
    display: block; aspect-ratio: 16 / 9; overflow: hidden;
    background: #d9d9d9; border-radius: 0; margin-bottom: 10px;
}
.article-recent__thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.article-recent__name {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
    font-size: 15px; line-height: 1.5; color: #000;
    transition: color .2s ease;
}
.article-recent__card:hover .article-recent__name { color: var(--color-accent); }
.article-recent__date { display: block; margin-top: 6px; font-size: 13px; line-height: 1.5; color: #969696; }
@media (max-width: 768px) {
    .article-writer { gap: 20px; }
    .article-writer__photo { flex-basis: 96px; width: 96px; height: 96px; }
    .article-recent__grid { grid-template-columns: 1fr; gap: 28px; }
}

/* =========================================================
   CONTACT / QUOTE — Figma 96:1161
   ========================================================= */
.contact {
    position: relative;
    /* v2.7.0 — wider gutters + roomier top/bottom per user request. */
    padding: clamp(110px, 14vh, 150px) clamp(56px, 6.5vw, 100px) clamp(140px, 16vh, 180px);
    max-width: 1280px;
    margin: 0 auto;
}
.contact__head {
    display: grid;
    grid-template-columns: 1fr 350px;
    gap: 100px;
    align-items: end;
    /* v2.7.0 — extra breathing room before the form. */
    margin-bottom: 130px;
}
.contact__title {
    font-size: 97.333px;
    font-weight: 400;
    line-height: 0.905;
    letter-spacing: -0.01em;
    margin: 0;
    max-width: 760px;
}
.contact__title-soft {
    font-weight: 500;
    color: rgba(35, 31, 32, 0.65);
}
.contact__intro {
    font-size: 18px; /* feedback — landing right-side intro +2pt (14.985→18) */
    line-height: 1.5;
    color: var(--color-text);
    margin: 0 0 24px;
    max-width: 320px;
}

.contact__form {
    /* v2.7.0 — slightly narrower form + roomier vertical gap. */
    max-width: 760px;
    margin: 0 auto;
    display: grid;
    gap: 48px;
}
.contact__row { display: grid; gap: 48px; }
.contact__row--2 { grid-template-columns: 1fr 1fr; }

.contact__field { position: relative; }
/* v2.12.97 — `> label` (DIRECT child) so this ONLY styles the real field labels
   ("Your Name", "Your Email"…). It used to be `.contact__field label`, which also
   matched the nested <label class="contact__pill"> pills and forced them to 18px —
   overriding `.contact__pill{font-size}` (lower specificity). THAT is why the pills
   were 18px and never matched the 15px/16px we set. Pills now size from their own
   `.contact__pill` rules (16px desktop / 15px mobile). */
.contact__field > label,
.contact__field-label {
    display: block;
    font-size: 18px;
    font-weight: 400;
    color: var(--color-text);
    margin-bottom: 18px;
    line-height: 1.2;
    text-transform: capitalize;
}
.contact__field input,
.contact__field textarea {
    width: 100%;
    border: 0;
    border-bottom: 1.5px solid rgba(35, 31, 32, 0.65);
    background: transparent;
    padding: 6px 0;
    font-size: 16px;
    font-family: inherit;
    color: var(--color-text);
    outline: none;
    transition: border-color .25s ease;
}
.contact__field input::placeholder,
.contact__field textarea::placeholder { color: rgba(35, 31, 32, 0.4); }
.contact__field textarea { resize: vertical; min-height: 36px; line-height: 1.5; }
.contact__field input:focus,
.contact__field textarea:focus { border-bottom-color: var(--color-primary); }

.contact__pills {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 20px;
}
.contact__pill {
    background: #ffffff;
    border: 0.898px solid #969696;
    border-radius: 101px;
    padding: 11px 22px;
    font-size: 16px;
    font-weight: 400;
    cursor: pointer;
    color: var(--color-text);
    line-height: 1.2;
    transition: background .2s ease, border-color .2s ease;
    font-family: inherit;
    position: relative;
    user-select: none;
}
.contact__pill:not(.is-checked):not(:has(input:checked)):hover { border-color: var(--color-primary); }
/* v2.5.14 — overlay the radio input across the whole pill so clicks always
   register natively. Previously `pointer-events: none` blocked the label's
   native check-toggle, so the pill never reached the .is-checked state. */
.contact__pill input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
    z-index: 1;
}
.contact__pill.is-checked,
.contact__pill:has(input:checked) {
    background: #d9d9d9;
    border-color: #969696;
}
/* Subtle gray hover preview before click — easier to discover the pills are
   clickable. Skipped when a pill is already checked. */
.contact__pill:not(:has(input:checked)):not(.is-checked):hover { background: #f1f1f1; }

/* v2.11.46 — pill groups are validated in JS (they carry no native `required`,
   which used to silently block submit on the opacity:0 inputs). On a missed
   group we outline its pills red and print the data-error-msg below them. */
.contact__field--error .contact__pill { border-color: #e2241a; }
.contact__field--error::after {
    content: attr(data-error-msg);
    display: block;
    margin-top: 8px;
    color: #e2241a;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.3;
}

/* v2.11.54 — hide the floating reCAPTCHA v3 badge (user request). Google's
   ToS allows hiding it ONLY if the attribution text is shown near the form —
   see .contact__recaptcha-note injected by template-parts/contact-form.php. */
.grecaptcha-badge { visibility: hidden; }
.contact__recaptcha-note {
    margin: 14px auto 0;
    max-width: 460px;
    text-align: center;
    font-size: 12px;
    line-height: 1.4;
    color: #8a8a8a;
}
.contact__recaptcha-note a { color: #8a8a8a; text-decoration: underline; text-underline-offset: 2px; }
.contact__recaptcha-note a:hover { color: var(--color-primary); }

/* v2.11.56 — intl-tel-input on the phone field: make the wrapper fill the
   underline input, and lift the (body-appended) country dropdown above the
   quote modal (z-index 2000) so it isn't hidden/clipped. */
.contact__form .iti { display: block; width: 100%; }
.contact__form .iti > input[type="tel"] { width: 100%; }
.iti--container { z-index: 3000 !important; }
.iti__country-list { text-align: left; }

.contact__share-row {
    display: grid;
    grid-template-columns: 42px 1fr;
    gap: 8px;
    align-items: end;
    border-bottom: 1.5px solid rgba(35, 31, 32, 0.65);
    padding-bottom: 6px;
}
.contact__share-icon {
    width: 30px; height: 30px;
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--color-text);
    transform: rotate(-53deg);
    font-size: 22px;
}
.contact__share-row input {
    border: 0; background: transparent; outline: none;
    font-size: 18px; font-family: inherit;
    padding: 4px 0;
    color: var(--color-text);
}
.contact__share-row input::placeholder { color: rgba(35, 31, 32, 0.55); }

.contact__submit {
    display: flex;
    justify-content: center;
    margin-top: 32px;
}
/* The form's submit reuses .btn .btn--primary from main.css but needs
   to be much larger than the standard 132px hero button. */
.contact__submit .btn--primary {
    width: min(314px, 100%);
    height: 50px;
    font-size: 18px;
    text-transform: capitalize;
}

.contact__status {
    max-width: 807px;
    margin: 0 auto 30px;
    padding: 14px 18px;
    border-radius: 6px;
    font-size: 13px;
}
.contact__status--ok    { background: #ecf7ec; color: #1f6e2c; }
.contact__status--error { background: #fceaea; color: #a01818; }

/* =========================================================
   Mobile breakpoints
   ========================================================= */
@media (max-width: 1100px) {
    .works__title { font-size: 64px; }
    .news__title, .contact__title { font-size: 72px; }
    .work-detail__title { font-size: 48px; }
    .article__title { font-size: 40px; }
    .article .work-detail__cta .ai-bottom-cta__title { font-size: 40px; }
}
@media (max-width: 900px) {
    .works__head, .news__head, .contact__head { grid-template-columns: 1fr; gap: 24px; }
    .article__head { grid-template-columns: 1fr; gap: 16px; }
    .article__meta { padding-top: 0; }
    .works__grid { grid-template-columns: repeat(2, 1fr); }
    .news__featured { grid-template-columns: 1fr; }
    .news__grid { grid-template-columns: repeat(2, 1fr); }
    .work-detail__overview { grid-template-columns: 1fr; gap: 28px; }
    .work-detail__phones { grid-template-columns: 1fr; }
    .work-detail__storyboard,
    .work-detail__sf-3col,
    .work-detail__3d-4col { grid-template-columns: repeat(2, 1fr); }
    .work-detail__sf-6col,
    .work-detail__3d-6col { grid-template-columns: repeat(3, 1fr); }
    .contact__row--2 { grid-template-columns: 1fr; }
    .navbar__links { gap: 18px; }
    .navbar__dropdown { display: none; }
    .works__title { font-size: 56px; }
    .news__title, .contact__title { font-size: 56px; }
    .work-detail__title { font-size: 40px; }
    .article__title { font-size: 34px; }
    .article .work-detail__cta .ai-bottom-cta__title { font-size: 34px; }
    .work-detail__sub { font-size: 17px; margin-bottom: 36px; }
}
@media (max-width: 600px) {
    .works__grid,
    .news__grid,
    .work-detail__sf-2col,
    .work-detail__sf-3col,
    .work-detail__storyboard,
    .work-detail__3d-4col { grid-template-columns: 1fr; }
    .work-detail__sf-6col,
    .work-detail__3d-6col { grid-template-columns: repeat(2, 1fr); }
    .works__title, .news__title, .contact__title { font-size: 44px; }
    .work-detail__title { font-size: 32px; }
    .article__title { font-size: 28px; }
    /* v2.12.37 — "Insights" same size as "News, Article &" (inherit the title size). */
    .news__title-line2 { font-size: inherit; }
    /* v2.11.80 — centre the "Let's talk" CTA button on phones. box-sizing is
       OFF globally (content-box), so width:max-content + padding overflowed the
       container at narrow widths and margin:auto stopped centring (button drifted
       right). Force border-box here so max-width:100% caps the FULL width and the
       auto side margins centre it cleanly at every phone width. */
    .work-detail__cta .btn--ai-cta {
        box-sizing: border-box;
        display: flex;
        width: fit-content;
        max-width: 100%;
        margin-left: auto;
        margin-right: auto;
    }
}

/* =========================================================
   PORTFOLIO LISTING — v2.4.27 Punchy-style filterbar
   Replaces the old chip-style .works__filters with two big
   pill dropdowns (Type + Audience). URL-driven, full-page
   reload on change. See page-portfolios.php.
   ========================================================= */

/* Single-line "Portfolio" title (replaces "Selected / Works" split). */
.works__title--single {
    font-size: 96px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.015em;
}

/* Filterbar: two columns, generous max-width so pills don't stretch
   to 1280 — matches Punchy reference where each pill is ~50% of an
   ~760px container. */
.works__filterbar {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
    max-width: 760px;
    margin: 0 0 64px;
    position: relative;
    z-index: 20;
}
.works__filterbar-submit {
    grid-column: 1 / -1;
    padding: 12px 24px;
    background: var(--color-text);
    color: #fff;
    border: 0;
    border-radius: 999px;
    cursor: pointer;
    font-size: 16px;
    font-family: inherit;
}

/* One dropdown unit. */
.works__select { position: relative; }
.works__select-label {
    display: block;
    font-size: 14px;
    color: rgba(35, 31, 32, 0.7);
    margin-bottom: 8px;
    font-weight: 500;
}
.works__select-trigger {
    display: flex;
    width: 100%;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 18px 26px;
    font-family: inherit;
    font-size: 17px;
    font-weight: 500;
    color: var(--color-text);
    background: #f1f3f6;
    border: 2px solid transparent;
    border-radius: 999px;
    cursor: pointer;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
    text-align: left;
    line-height: 1.2;
}
.works__select-trigger:hover {
    background: #e7eaef;
}
.works__select.is-open .works__select-trigger,
.works__select-trigger:focus-visible {
    border-color: var(--color-accent);
    background: #fff;
    outline: none;
    box-shadow: 0 0 0 4px rgba(21, 102, 224, 0.12);
}
.works__select-value {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.works__select-caret {
    flex: none;
    width: 0; height: 0;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-top: 6px solid currentColor;
    transition: transform .2s ease;
}
.works__select.is-open .works__select-caret { transform: rotate(180deg); }

/* Dropdown panel.
   v2.7.17 — overscroll-behavior: contain + data-lenis-prevent in markup
   so wheel scrolls the dropdown natively instead of bubbling up to Lenis
   and smooth-scrolling the page underneath. */
.works__select-list {
    position: absolute;
    top: calc(100% + 6px);
    left: 0; right: 0;
    background: #fff;
    border: 1px solid rgba(0, 0, 0, 0.08);
    border-radius: 8px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
    margin: 0; padding: 6px 0;
    list-style: none;
    z-index: 30;
    max-height: 320px;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.works__select-list[hidden] { display: none; }
.works__select-list li {
    padding: 12px 26px;
    font-size: 16px;
    font-weight: 500;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
    color: var(--color-text);
}
.works__select-list li:hover { background: #f4f5f8; }
.works__select-list li.is-active {
    background: var(--color-accent);
    color: #fff;
}

/* Play button overlay on each card thumb (Punchy-style). pointer-events
   none so the click bubbles to the wrapping <a class="works__card">. */
.works__play {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 84px;
    height: 84px;
    border-radius: 50%;
    background: var(--color-accent);
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
    z-index: 3;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
    transition: transform .25s ease, background .2s ease;
}
.works__play::before {
    content: "";
    width: 0; height: 0;
    border-top: 14px solid transparent;
    border-bottom: 14px solid transparent;
    border-left: 22px solid #fff;
    margin-left: 6px;
}
.works__card:hover .works__play,
.works__card:focus-within .works__play {
    transform: translate(-50%, -50%) scale(1.08);
    background: #0f4ea8;
}

/* Empty-state when filters return zero matches. */
.works__empty {
    text-align: center;
    padding: 80px 20px;
    color: rgba(35, 31, 32, 0.6);
    font-size: 18px;
}

/* Numbered pagination — replaces the static dot row for the new
   ?portfolio_page=N links. */
.works__pagenav {
    display: flex;
    justify-content: center;
    align-items: center;
    /* v2.11.70 — enlarged to match the blog: 20px numbers, wider gap. */
    gap: 34px;
    margin-top: 80px;
    font-size: 20px;
    font-weight: 500;
}
.works__pagenav-item {
    color: var(--color-text);
    text-decoration: none;
    transition: color .15s ease;
    line-height: 1;
}
.works__pagenav-item:hover { color: var(--color-accent); }
.works__pagenav-item.is-current {
    color: var(--color-accent);
    font-weight: 700;
}
.works__pagenav-arrow {
    width: 0; height: 0;
    border-top: 9px solid transparent;
    border-bottom: 9px solid transparent;
    border-left: 14px solid currentColor;
    background: none;
}
/* Left-pointing arrow for "previous page" — mirror of the right arrow. */
.works__pagenav-arrow--prev {
    border-left: 0;
    border-right: 14px solid currentColor;
}
.works__pagenav-arrow.is-disabled { opacity: 0.3; }

@media (max-width: 700px) {
    .works__filterbar { grid-template-columns: 1fr; max-width: none; }
    .works__title--single { font-size: 56px; }
    .works__play { width: 64px; height: 64px; }
    .works__play::before {
        border-top-width: 10px;
        border-bottom-width: 10px;
        border-left-width: 16px;
    }
}

/* =======================================================
   FOOTER LEGAL — link styling only.
   v2.7.25 — `right` anchor removed from here; positioning now comes
   from --spx-footer-legal-right in main.css (single source of truth).
   ======================================================= */
.site-footer__legal a {
    color: inherit;
    text-decoration: none;
}
.site-footer__legal a:hover { text-decoration: underline; }

@media (max-width: 720px) {
    .site-footer__legal { right: auto; }
}

/* =======================================================
   PROPOSAL TERMS — long-form legal page (Figma 144:1219)
   High-specificity body-class selectors so cached/conflicting
   theme rules don't bleed in and flatten the layout.
   ======================================================= */
body.page-template-page-proposal-terms .site-main.proposal-terms,
.proposal-terms {
    position: relative;
    /* box-sizing is off globally, so width:100% + side padding overflowed the
       viewport to the right (title + text bled off-screen). Force border-box
       here so the padding stays inside the page width. */
    box-sizing: border-box;
    max-width: 100vw;
    padding: 60px var(--content-pad) 120px;
    color: var(--color-text);
}

/* Soft pastel backdrop (Figma BG_ABOUT US 144:1221 + COLOURED ACCENT).
   Anchored to body so it spans the entire viewport — site-main's 1280
   max-width can't clip it. Hidden div fallback below for older markup. */
.proposal-terms__aurora { display: none; }

body.page-template-page-proposal-terms::before,
body.page-template-page-privacy-policy::before,
body.page-template-page-terms-of-service::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    width: 100vw;
    height: 760px;
    pointer-events: none;
    z-index: 0;
    opacity: 0.55;
    background:
        radial-gradient(70% 60% at 20% 38%, rgba(120, 156, 255, 0.45), transparent 70%),
        radial-gradient(60% 55% at 80% 42%, rgba(255, 175, 210, 0.38), transparent 72%),
        radial-gradient(closest-side at 50% 18%, rgba(220, 200, 255, 0.25), transparent 80%);
    /* Soft fade-out at the bottom so the wash blends into the white page
       instead of cutting off at a hard horizontal edge. */
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 45%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 0%, #000 45%, transparent 100%);
}

body.page-template-page-proposal-terms,
body.page-template-page-privacy-policy,
body.page-template-page-terms-of-service { position: relative; }

body .proposal-terms .proposal-terms__article {
    position: relative;
    z-index: 1;
    max-width: 700px !important;
    margin: 0 auto !important;
    width: 100%;
    text-transform: none;
    text-align: left;
}

body .proposal-terms .proposal-terms__head {
    text-align: center !important;
    padding: 80px 0 0 !important;
    margin: 0;
}

body .proposal-terms .proposal-terms__title {
    font-size: 52px !important;
    line-height: 1.2 !important;
    font-weight: 400 !important;
    letter-spacing: -0.005em;
    margin: 0 !important;
    color: var(--color-text);
    text-align: center !important;
    text-transform: none !important;
}

body .proposal-terms .proposal-terms__rule {
    display: block !important;
    width: 252px !important;
    height: 1px !important;
    background: var(--color-text) !important;
    margin: 40px auto 56px !important;
}

/* "Last updated" row — left-aligned within the centred column, with a
   small clock/timer icon (Figma 144:1289). */
body .proposal-terms .proposal-terms__updated {
    display: flex !important;
    align-items: center;
    gap: 10px;
    margin: 0 0 36px !important;
    color: rgba(35, 31, 32, 0.65);
    font-size: 16px !important;
    font-weight: 400;
    position: relative;
    z-index: 1;
    text-align: left;
}

.proposal-terms__updated-icon {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 1.5px solid rgba(35, 31, 32, 0.65);
    position: relative;
    flex-shrink: 0;
}
.proposal-terms__updated-icon::before,
.proposal-terms__updated-icon::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    background: rgba(35, 31, 32, 0.65);
    transform-origin: 0 0;
    border-radius: 1px;
}
.proposal-terms__updated-icon::before {
    width: 5px;
    height: 1.5px;
    transform: translate(0, -50%);
}
.proposal-terms__updated-icon::after {
    width: 4px;
    height: 1.5px;
    transform: translate(0, -50%) rotate(-90deg);
}

body .proposal-terms .proposal-terms__body {
    position: relative;
    z-index: 1;
    color: var(--color-text);
    font-size: 18px !important;
    line-height: 1.8 !important;
    font-weight: 400;
    text-align: left;
}

body .proposal-terms .proposal-terms__body p {
    margin: 0 0 28px !important;
    font-size: 18px !important;
}

body .proposal-terms .proposal-terms__body h2 {
    color: var(--color-text);
    font-size: 24px !important;
    font-weight: 500 !important;
    line-height: 1.8 !important;
    margin: 32px 0 8px !important;
    text-transform: none !important;
    letter-spacing: 0;
}

.proposal-terms__body ul {
    margin: 0 0 28px;
    padding-left: 27px;
    list-style: disc;
}

.proposal-terms__body li {
    margin: 0 0 4px;
    line-height: 1.8;
}

.proposal-terms__body a {
    color: var(--color-text);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 6px;
    text-decoration-skip-ink: auto;
}

.proposal-terms__contact {
    font-weight: 400;
}

@media (max-width: 900px) {
    .proposal-terms__title { font-size: 40px; }
}

@media (max-width: 700px) {
    .proposal-terms { padding: 40px 20px 96px; box-sizing: border-box; }
    body .proposal-terms .proposal-terms__article { box-sizing: border-box; max-width: 100%; }
    .proposal-terms__head { padding: 32px 0 0; }
    body .proposal-terms .proposal-terms__title { font-size: 30px !important; }
    .proposal-terms__rule { width: 180px; margin: 28px auto 40px; }
    .proposal-terms__updated { font-size: 14px; margin-bottom: 28px; }
    /* wrap long words / URLs (e.g. "superpixel.sg") so body text never bleeds
       past the right edge. */
    body .proposal-terms .proposal-terms__body { font-size: 16px; overflow-wrap: break-word; word-wrap: break-word; }
    .proposal-terms__body h2 { font-size: 20px; margin-top: 28px; }
    .proposal-terms__aurora { height: 320px; }
}

/* =========================================================
   FREE QUOTE MODAL — v2.5.12  (Figma 96:1161)
   Inline form rendered in footer.php. Pastel gradient backdrop,
   white card with scrollable form, close ×. No iframe.
   ========================================================= */
.quote-modal {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.quote-modal[hidden] { display: none !important; }
.quote-modal.is-open { display: flex; }

/* Dim layer behind the panel — soft pastel wash (matches the BG_ABOUT US
   gradient elsewhere in the theme) on top of a dark veil so the page
   underneath disappears. */
.quote-modal__backdrop {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(60% 55% at 20% 25%, rgba(120, 156, 255, 0.30), transparent 70%),
        radial-gradient(55% 50% at 80% 30%, rgba(255, 175, 210, 0.28), transparent 72%),
        radial-gradient(closest-side at 50% 80%, rgba(220, 200, 255, 0.22), transparent 80%),
        rgba(10, 10, 14, 0.78);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    cursor: pointer;
    animation: quote-modal-fade .25s ease;
}

.quote-modal__panel {
    position: relative;
    /* v2.7.0 — narrower card so it doesn't dominate the viewport. */
    width: min(820px, 94vw);
    max-height: min(90vh, 880px);
    border-radius: 14px;
    overflow: hidden;
    background: #fff;
    box-shadow: 0 30px 80px rgba(0, 0, 0, .45);
    animation: quote-modal-pop .35s cubic-bezier(.2, .7, .2, 1);
    display: flex;
    flex-direction: column;
}
/* The actual form column scrolls; the panel itself doesn't.
   v2.7.15 — flex:1 + min-height:0 makes the inner respect the panel's
   max-height in a flex column so overflow-y:auto actually engages.
   Without these, the inner sized to content and the wheel had nowhere
   to scroll → user had to drag the scrollbar manually. */
.quote-modal__inner {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    /* v2.7.0 — bigger inner margin (was 56px / clamp(28,6vw,80) — now 64/clamp(40,7vw,90)) */
    padding: 64px clamp(40px, 7vw, 90px) 64px;
    margin: 0;
    max-width: none;
}
/* v2.5.13 — close button is a sibling of .quote-modal__panel (not nested
   inside it) so the scrolling form area can never intercept clicks on it.
   Position fixed to the viewport, always reachable above the modal. */
.quote-modal__close {
    position: fixed;
    top: calc(4vh + 8px);
    right: calc(2vw + 8px);
    width: 44px;
    height: 44px;
    border-radius: 50%;
    border: 0;
    background: rgba(255, 255, 255, .96);
    color: #000;
    font-size: 30px;
    line-height: 1;
    cursor: pointer;
    z-index: 2010;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 14px rgba(0, 0, 0, .35);
    transition: background .2s ease, transform .2s ease;
}
.quote-modal__close:hover { background: #fff; transform: scale(1.06); }
@media (max-width: 600px) {
    .quote-modal__close { top: 14px; right: 14px; width: 36px; height: 36px; font-size: 24px; }
}

/* Tighter title/intro layout inside the modal — Figma 96:1190/1191.
   v2.7.0 — text + columns shrunk per user request. */
.contact--modal .contact__head {
    display: grid;
    grid-template-columns: 1fr 300px;
    gap: 32px;
    align-items: start; /* feedback F1 — intro top-aligns with the headline */
    margin-bottom: 36px;
}
.contact--modal .contact__title {
    font-size: clamp(30px, 5vw, 50px);
    line-height: 0.95;
    letter-spacing: -0.01em;
    font-weight: 400;
    margin: 0;
    max-width: none;
}
.contact--modal .contact__intro {
    font-size: 18px; /* feedback F1 — pop-up right-column body enlarged again (16→18) */
    line-height: 1.5;
    color: var(--color-text);
    margin: 0;
    max-width: none;
}
.contact--modal .contact__form {
    max-width: none;
    margin: 0;
    gap: 30px;
}
.contact--modal .contact__row { gap: 30px; }
.contact--modal .contact__field > label,
.contact--modal .contact__field-label {
    font-size: 15px;
    margin-bottom: 12px;
}
.contact--modal .contact__field input,
.contact--modal .contact__field textarea { font-size: 14px; }
/* v2.12.79 — popup pills flow left→right hugging their text with a fixed gap (so the
   right pill sits just after the left one — different x per row, not snapped to 50%).
   A row-break element (.contact__pill-break) forces 2 per row, per the user's mockup. */
.contact--modal .contact__pills {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 20px;
}
.contact--modal .contact__pill {
    padding: 9px 18px;
    /* v2.12.97 — 16px to match the /contact/ page pills on desktop (was 13px, a
       relic from when the label rule forced everything; now pills size themselves). */
    font-size: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    white-space: nowrap;
}
.contact--modal .contact__field[data-quote-type-field] .contact__pill:last-child {
    flex-basis: 100%;
}
/* row-break: forces the next pill onto a new line (used to keep 2 per row).
   v2.12.98 — the break sits on its OWN zero-height flex line, so the row-gap (8px)
   applied above AND below it doubled the gap between break-separated rows (~16px)
   vs the single 8px gap on rows with no break (e.g. Immersive→Not-sure). Pull the
   break up by one row-gap so EVERY row gap is the same 8px. (Break is display:none
   on desktop, so this only affects mobile.) */
.contact__pill-break { flex-basis: 100%; height: 0; margin: 0; padding: 0; border: 0; }

/* v2.12.91 — DESKTOP pill layout per Figma 96:1213 / 96:1234 (both the /contact/
   page AND the pop-up): a natural LEFT-aligned wrap of hug-text pills with an even
   gap — NOT 2-per-row, and the long "Not sure yet…" is a normal hug-text pill (no
   full-width). So the row reads: [2D][3D][Immersive][Interactive] / [Motion][Not
   sure…]. The .contact__pill-break elements (which force 2-per-row) are hidden at
   ≥769px; they only take effect in the ≤768 mobile block below. */
@media (min-width: 769px) {
    .contact .contact__pill-break { display: none; }
    .contact .contact__pills {
        display: flex;
        flex-wrap: wrap;
        justify-content: flex-start;
        /* gap tightened to 12px so all 4 row-1 pills (2D, 3D, Immersive,
           Interactive) fit on ONE line → exactly 2 rows like Figma. */
        gap: 12px;
    }
    .contact .contact__pill {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        text-align: center;
        white-space: nowrap;
        flex: 0 0 auto;
        width: auto;
        /* slightly tighter horizontal padding (Figma-like) so the 4 pills fit
           the form width without wrapping to a 3rd row. */
        padding: 10px 18px;
    }
    /* the long option is just another hug-text pill on desktop (no full row) */
    .contact .contact__field[data-quote-type-field] .contact__pill:last-child {
        flex-basis: auto;
        width: auto;
    }
}
.contact--modal .contact__share-row input { font-size: 14px; }
.contact--modal .contact__submit { margin-top: 24px; }

/* v2.11.53 — body scroll-lock flag. MUST stay distinct from the trigger
   selector [data-quote-open]: when the body carried data-quote-open, the
   delegated opener click-handler matched the body for EVERY click inside the
   open modal and preventDefault'd them — the Submit button never fired. */
body[data-quote-active] { overflow: hidden; }
@keyframes quote-modal-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes quote-modal-pop {
    from { opacity: 0; transform: translateY(20px) scale(.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

@media (max-width: 760px) {
    .contact--modal .contact__head { grid-template-columns: 1fr; gap: 16px; }
    /* v2.11.93 — more breathing room in the headline (was line-height 0.95). */
    .contact--modal .contact__title { font-size: clamp(30px, 7.5vw, 44px); line-height: 1.1; }
    /* v2.11.93 — body/intro text smaller. */
    .contact--modal .contact__intro { font-size: 15px; }
    .quote-modal__inner { padding: 44px 24px 44px; }
}
@media (max-width: 600px) {
    .quote-modal { padding: 12px; }
    .quote-modal__panel { max-height: 94vh; border-radius: 10px; }
    .contact--modal .contact__row--2 { grid-template-columns: 1fr; }
}

/* =========================================================
   AI PAGE — v2.6.0  (Figma node 173:2746)
   ========================================================= */

/* The AI page bypasses the global 1280 site-main cap because
   several sections (hero aurora, dark band, blue band) need
   full-bleed treatment. */
.site-main--ai { max-width: none; width: 100%; margin: 0; }

/* ---------- shared utilities ---------- */
.ai-page-pad { padding-left: clamp(20px, 4vw, 80px); padding-right: clamp(20px, 4vw, 80px); }

/* Inline italic blue accent used by every AI section heading. */
.ai-hero__title em,
.ai-services__title em,
.ai-howit__title em,
.ai-compare__title em,
.ai-bottom-cta__title em,
.ai-approach__title em { font-style: italic; color: var(--color-accent); font-weight: 600; }

/* "Soft" greyed inline span used by Our Approach headline. */
.ai-approach__title-soft { color: #d9d9d9; font-weight: 500; display: block; }

/* v2.6.5 — Explore Services: bordered rectangle that turns blue
   (text + border) on hover. Matches Figma 173:3373 default/hover
   component variants. */
.ai-hero__explore {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    padding: 14px 26px;
    background: #fff;
    color: var(--color-text);
    font-size: 16px;
    font-weight: 600;
    line-height: 1;
    /* v2.6.6 — no default outline; border only appears (blue) on hover. */
    border: 1.5px solid transparent;
    border-radius: 4px;
    box-shadow: 0 2px 10px rgba(35, 31, 32, 0.08);
    transition: color .25s ease, border-color .25s ease, box-shadow .25s ease, transform .25s ease;
}
.ai-hero__explore:hover {
    color: var(--color-accent);
    border-color: var(--color-accent);
    box-shadow: 0 10px 26px rgba(21, 102, 224, 0.18);
    transform: translateY(-1px);
}
.ai-hero__explore-label { display: inline-block; }
.ai-hero__explore-arrow { font-size: 16px; transition: transform .25s ease; }
.ai-hero__explore:hover .ai-hero__explore-arrow { transform: translateX(4px); }

/* AI-page Discovery-Call CTA variant — wider and taller than the
   homepage `.btn--primary` 132×30 default. */
.btn--ai-cta {
    width: auto;
    min-width: 250px;
    height: 50px;
    padding: 0 28px;
    font-size: 16px;
    font-weight: 600;
    text-transform: none;
}
.btn--ai-cta-lg {
    height: 56px;
    min-width: 270px;
    padding: 0 36px;
    font-size: 18px;
}

/* ---------- 1. HERO ---------- */
.ai-hero {
    position: relative;
    padding: clamp(60px, 8vw, 120px) clamp(20px, 4vw, 80px) clamp(80px, 9vw, 140px);
    text-align: center;
    overflow: hidden;
    background: #fff;
}
.ai-hero__aurora {
    position: absolute;
    inset: -120px 0 auto 0;
    height: 760px;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(closest-side at 18% 35%, rgba(255, 192, 218, 0.55), transparent 65%),
        radial-gradient(closest-side at 82% 30%, rgba(160, 215, 255, 0.55), transparent 65%),
        radial-gradient(closest-side at 50% 70%, rgba(255, 232, 188, 0.45), transparent 65%);
    filter: blur(60px);
    opacity: 0.55;
    -webkit-mask-image: linear-gradient(to bottom, #000 30%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 30%, transparent 100%);
}
.ai-hero__inner {
    position: relative;
    z-index: 1;
    max-width: 1280px;
    margin: 0 auto;
}
/* feedback — decorative floating 3D arrow to the LEFT of the (centered) headline.
   User-supplied size/rotation; gentle bob + slight wobble for a "live" feel.
   Hidden under 1200px where there's no side room beside the centred title. */
.ai-hero__arrow {
    position: absolute;
    /* Figma "Desktop V2" — sits in the LEFT gutter at the lede / sub-headline
       level (lower than the headline), pointing down-right toward the copy. */
    left: 8%;
    right: auto;
    top: 15%;
    width: clamp(190px, 18.5vw, 305px);
    height: auto;
    aspect-ratio: 148 / 113;
    z-index: 2;
    pointer-events: none;
    transform: rotate(22deg);
    animation: ai-arrow-float 4.2s ease-in-out infinite;
    will-change: transform;
}
@keyframes ai-arrow-float {
    0%, 100% { transform: rotate(22deg) translateY(0); }
    50%      { transform: rotate(25deg) translateY(-18px); }
}
@media (prefers-reduced-motion: reduce) {
    .ai-hero__arrow { animation: none; transform: rotate(22deg); }
}
@media (max-width: 1200px) {
    .ai-hero__arrow { display: none; }
}
.ai-hero__title {
    font-size: clamp(54px, 7vw, 99px);
    font-weight: 400;
    line-height: 1.05;
    margin: 0;
    letter-spacing: -0.01em;
    color: #000;
    position: relative;
    display: inline-block;
}
.ai-hero__title em { font-weight: 600; }
.ai-hero__rotator {
    /* v2.6.10 — typewriter line below "AI-Powered". The text node grows
       letter-by-letter via JS; cursor blinks via CSS animation. */
    display: block;
    position: relative;
    width: 100%;
    min-height: 1.15em;
    text-align: center;
    margin-top: 8px;
    line-height: 1.05;
}
.ai-hero__rotator-text {
    font-style: italic;
    font-weight: 500;
    color: var(--color-accent);
    white-space: pre;
}
.ai-hero__rotator-cursor {
    display: inline-block;
    margin-left: 2px;
    font-weight: 400;
    font-style: normal;
    color: var(--color-accent);
    animation: ai-cursor-blink 1s steps(1) infinite;
    transform: translateY(2px);
}
@keyframes ai-cursor-blink {
    0%, 50%   { opacity: 1; }
    51%, 100% { opacity: 0; }
}
.ai-hero__arrow {
    /* v2.6.1 — anchor near top-left of the rotating-word line. */
    position: absolute;
    width: 60px;
    height: 60px;
    left: calc(50% - 240px);
    top: calc(1em + 18px);
    transform: rotate(-12deg);
    pointer-events: none;
    opacity: 0.85;
}

.ai-hero__lede {
    font-size: clamp(16px, 1.3vw, 22px);
    line-height: 1.8;
    color: var(--color-text);
    max-width: 920px;
    margin: 32px auto 0;
}
.ai-hero__actions {
    margin: 40px auto 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    flex-wrap: wrap;
}
.ai-hero__stats {
    list-style: none;
    margin: 64px auto 0;
    padding: 18px clamp(20px, 3vw, 40px);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: clamp(20px, 3.5vw, 60px);
    max-width: 940px;
    background: rgba(255, 255, 255, 0.45);
    border: 1px solid rgba(255, 255, 255, 0.7);
    border-radius: 18px;
    box-shadow: 0 4px 60px rgba(255, 255, 255, 0.35), 0 12px 40px rgba(120, 156, 255, 0.10);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.ai-hero__stats li {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    text-align: center;
    position: relative;
    padding: 0 clamp(8px, 1.5vw, 20px);
}
.ai-hero__stats li + li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 12%;
    height: 76%;
    width: 1px;
    background: rgba(35, 31, 32, 0.15);
}
.ai-hero__stats strong {
    font-size: clamp(22px, 2vw, 32px);
    font-weight: 500;
    color: var(--color-accent);
    line-height: 1;
}
.ai-hero__stats span {
    font-size: 12px;
    color: #444;
    line-height: 1.3;
    max-width: 140px;
}

.ai-hero__clients {
    margin: 56px auto 0;
    max-width: 980px;
}
.ai-hero__clients-label {
    font-size: 16px;
    color: var(--color-text);
    margin: 0 0 20px;
}
.ai-hero__clients-row {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: clamp(24px, 4vw, 56px);
    opacity: 0.65;
}
.ai-hero__clients-row img { width: 145px; height: 50px; object-fit: contain; filter: grayscale(1) contrast(1.1); } /* feedback — uniform 145×50 logo box */

/* ---------- 2. PORTFOLIO ---------- */
.ai-porto {
    max-width: 1280px;
    /* v2.6.40 — uniform 150px gap between AI page sections. */
    margin: 150px auto 0;
    padding: 0 clamp(20px, 4vw, 80px);
}
.ai-porto__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 40px;
    row-gap: clamp(40px, 5vw, 80px);
}
/* v2.6.3 — tiles sit on the same baseline (no zig-zag stagger). */
.ai-porto__thumb {
    /* v2.6.4 — square corners on portfolio thumbs. */
    display: block; /* it's an <a> (inline) — block so aspect-ratio gives it height */
    position: relative;
    aspect-ratio: 730 / 410;
    overflow: hidden;
    border-radius: 0;
    background: #1a1a1a;
}
/* v2.6.7 — homepage-style two-image hover fade. Rest image fades
   OUT and the lazy-loaded animated GIF fades IN; both scale up
   slightly. JS in main.js assigns the GIF src on first hover so
   the heavy assets don't ship with initial page load. */
.ai-porto__thumb-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    transition: opacity .35s ease, transform .6s cubic-bezier(.2,.7,.2,1);
}
.ai-porto__thumb-img--rest  { opacity: 1; }
.ai-porto__thumb-img--hover { display: none; } /* v2.6.25 — drop GIF swap; hover now blurs the cover instead */
.ai-porto__thumb:hover .ai-porto__thumb-img--rest {
    filter: blur(8px);
    -webkit-filter: blur(8px);
    transform: scale(1.04);
}

/* Circular play overlay — hidden by default, fades in on card hover. */
.ai-porto__play {
    position: absolute;
    left: 50%; top: 50%;
    transform: translate(-50%, -50%) scale(.85);
    width: 72px;
    height: 72px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.85);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.22);
    pointer-events: none;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity .3s ease, transform .35s cubic-bezier(.2, .7, .2, 1), background .25s ease;
}
.ai-porto__play::before {
    content: "";
    width: 0; height: 0;
    border-top: 11px solid transparent;
    border-bottom: 11px solid transparent;
    border-left: 18px solid var(--color-accent);
    margin-left: 4px;
}
.ai-porto__thumb:hover .ai-porto__play {
    opacity: 1;
    background: #fff;
    transform: translate(-50%, -50%) scale(1);
}
.ai-porto__title {
    font-size: 26px; /* feedback S3 — Selected Work card title +2pt (23→26) */
    font-weight: 500;
    margin: 18px 0 4px;
    color: #000;
    line-height: 1.3;
}
.ai-porto__sub {
    font-size: 19px; /* feedback S3 — sub-headline +~4pt, needed >2pt (14.74→19) */
    font-weight: 500;
    color: var(--color-accent);
    margin: 0;
    line-height: 1.4;
}

/* ---------- 3. SERVICES ---------- */
.ai-services {
    /* v2.6.40 — uniform 150px gap; tight side padding for 4 cards. */
    max-width: 1440px;
    margin: 150px auto 0;
    padding: 0 clamp(16px, 2vw, 32px);
    /* v2.6.41 — leave space for the 76px sticky header when scrolled to via #ai-services anchor. */
    scroll-margin-top: 110px;
}
.ai-services__head { margin-bottom: 48px; }
.ai-services__title {
    font-size: clamp(34px, 4.2vw, 52px);
    font-weight: 400;
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin: 0;
    max-width: 1080px;
}
.ai-services__grid {
    /* v2.6.35 — flexible 4-col grid that fits the 1280 container. */
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
}
.ai-services__card {
    /* v2.6.38 — internal padding tightened (44 → 32 sides) so body text
       wraps to 4 lines consistently at 1280-1440 viewports. */
    position: relative;
    background:
        radial-gradient(circle at 18% 14%,
            rgba(255, 255, 255, 0.95) 0%,
            rgba(255, 255, 255, 0) 55%),
        #efefef;
    border-radius: 0;
    padding: 48px 32px 36px;
    box-shadow: 0 6px 14px rgba(0, 0, 0, 0.10);
    display: flex;
    flex-direction: column;
    gap: 22px;
    min-height: 32px;
    color: #000;
    overflow: hidden;
    isolation: isolate;
    cursor: pointer;
    /* v2.6.43 — text color snaps faster (0.15s) so it doesn't lag behind the bg gradient. */
    transition: color .15s ease, box-shadow .35s ease;
}
.ai-services__card:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }
/* v2.6.32 — hover: blue center fading out to white at the edges. */
.ai-services__card::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    background:
        radial-gradient(circle at 50% 50%,
            #2E72D8 0%,
            #4585E0 28%,
            #79A4EC 52%,
            #B5CCF1 75%,
            #E3EDF8 92%,
            #FFFFFF 100%);
    opacity: 0;
    transition: opacity .4s ease;
    pointer-events: none;
}
/* v2.6.42 — white inset border removed per user request. */
.ai-services__card::after { content: none; }
.ai-services__card > * { position: relative; z-index: 1; }
.ai-services__card:hover { color: #fff; }
.ai-services__card:hover::before,
.ai-services__card:hover::after { opacity: 1; }
.ai-services__card-title {
    /* v2.6.30 — bumped to match Figma 25.57px, capitalize. */
    font-size: 26px;
    font-weight: 500;
    color: var(--color-accent);
    text-transform: capitalize;
    margin: 0;
    line-height: 1.2;
    /* v2.6.43 — quicker color transition so it doesn't visibly lag. */
    transition: color .15s ease;
}
.ai-services__card:hover .ai-services__card-title { color: #fff; }
.ai-services__card-body {
    font-size: 14px;
    line-height: 1.5;
    color: inherit;
    margin: 0;
    text-transform: capitalize;
}
/* v2.6.30 — standard list bullets per Figma; bullet colour follows text colour. */
.ai-services__card-list {
    list-style: disc;
    padding: 0 0 0 22px;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 15px;
    color: inherit;
    text-transform: capitalize;
}
.ai-services__card-list li {
    position: static;
    padding-left: 0;
}
.ai-services__card-list li::before { content: none; }
.ai-services__card-link {
    margin-top: auto;
    font-size: 14px;
    font-weight: 400;
    color: inherit;
    display: inline-flex;
    gap: 8px;
    align-items: center;
    text-transform: capitalize;
    transition: color .2s ease, transform .2s ease;
}
.ai-services__card:hover .ai-services__card-link { color: #fff; }

/* ---------- 4. OUR APPROACH (dark band) ---------- */
.ai-approach {
    background: #231f20;
    color: #fff;
    /* v2.6.40 — uniform 150px gap between AI page sections. */
    margin-top: 150px;
    padding: clamp(70px, 8vw, 130px) clamp(20px, 4vw, 80px);
}
.ai-approach__inner {
    max-width: 1280px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(40px, 6vw, 110px);
    align-items: center;
}
.ai-approach__photos {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    position: relative;
    /* v2.6.31 — cap so portraits stay close to Figma's 240x292 even on
       wider columns; centered within the column. */
    max-width: 500px;
}
.ai-approach__photo {
    /* v2.6.4 — square corners on director portraits. */
    position: relative;
    aspect-ratio: 240 / 292;
    border-radius: 0;
    overflow: hidden;
    background: #1a1a1a;
}
/* v2.6.31 — Figma 173:2877: column 2 (Mark + Jean) sits ~48px HIGHER
   than column 1, not the other way around. */
.ai-approach__photo--2 { margin-top: -48px; }
.ai-approach__photo--3 { margin-top: 0; }
.ai-approach__photo--4 { margin-top: -48px; }
/* v2.6.3 — grayscale by default, color on hover (mirrors homepage
   .cta__portrait pattern). */
/* v2.6.47 — image always fills frame (scale ≥ 1.0). Zoom-out effect =
   base scale 1.1 → hover scale 1.0. object-position: center 25% biases
   the crop toward the upper portion of the source so natural headroom
   stays visible (heads aren't mepet at the top). */
/* v2.9.88 — matched to the homepage CTA portraits exactly: ONLY the zoom
   animates and the idle→hover swap is INSTANT (no opacity transition), so the
   two pre-graded photos never blend = no ghosting. Idle stays solid underneath,
   hover snaps on top; both share one transform and zoom out 1.06 → 1.0. */
.ai-approach__photo img {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    object-position: center 30%;
    display: block;
    transform: translateZ(0) scale(1.06);
    transition: transform .6s cubic-bezier(.2,.7,.2,1);
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}
.ai-approach__img--hover { opacity: 0; }
.ai-approach__photo:hover .ai-approach__img--hover { opacity: 1; }
.ai-approach__photo:hover img { transform: translateZ(0) scale(1); }
.ai-approach__name {
    /* v2.6.31 — Figma 173:2877: plain text labels in bottom-left, no chip. */
    position: absolute;
    left: 21px;
    bottom: 14px;
    color: #fff;
    font-size: 12.5px;
    line-height: 1.35;
    z-index: 2;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}
.ai-approach__name strong { display: block; font-weight: 500; }
.ai-approach__name span { color: #969696; font-size: 9px; font-weight: 500; }

.ai-approach__copy { max-width: 660px; }
.ai-approach__eyebrow {
    font-size: clamp(15px, 1.2vw, 21px);
    font-weight: 500;
    color: var(--color-accent);
    margin: 0 0 22px;
}
.ai-approach__title {
    font-size: clamp(34px, 4.4vw, 56px);
    font-weight: 500;
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin: 0;
    color: #fff;
}
/* v2.6.31 — Figma 173:2877: first line is light-grey, italic phrase stays white. */
.ai-approach__title-soft { color: #d9d9d9; display: block; }
.ai-approach__title em { color: #fff; font-style: italic; font-weight: 600; }
.ai-approach__body {
    margin: 28px 0 32px;
    font-size: 16px;
    line-height: 1.65;
    color: #fff;
}
.ai-approach__body p { margin: 0 0 1em; }
.ai-approach__body p:last-child { margin-bottom: 0; }
/* v2.6.8 — minimal "tick + text" row (no pill background or border).
   Each item is a checkmark icon (circle with tick) followed by the
   white label. */
.ai-approach__pills {
    list-style: none;
    padding: 0;
    margin: 0 0 36px;
    display: flex;
    flex-wrap: wrap;
    gap: 32px;
}
.ai-approach__pills li {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 0;
    border: 0;
    background: none;
    font-size: 15px;
    font-weight: 500;
    color: #fff;
}
.ai-approach__pill-check {
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 1.5px solid #fff;
    flex-shrink: 0;
    position: relative;
    display: inline-block;
}
.ai-approach__pill-check::after {
    content: "";
    position: absolute;
    left: 4px;
    top: 1.5px;
    width: 4px;
    height: 8px;
    border-right: 1.5px solid #fff;
    border-bottom: 1.5px solid #fff;
    transform: rotate(45deg);
}

/* ---------- 5. HOW IT WORKS ---------- */
/* v2.7.22 — reverted from scroll-pinned runway back to sticky-head
   pattern (same as About How We Work). Title pinned in left col,
   step list flows in right col. */
.ai-howit {
    max-width: 1280px;
    /* v2.6.40 — uniform 150px gap between AI page sections. */
    margin: 150px auto 0;
    padding: 0 clamp(20px, 4vw, 80px);
}
.ai-howit__inner {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(40px, 6vw, 100px);
    align-items: start;
}
.ai-howit__head { max-width: 480px; position: sticky; top: 120px; }
.ai-howit__title {
    font-size: clamp(34px, 4.2vw, 52px);
    font-weight: 400;
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin: 0 0 24px;
}
.ai-howit__lede {
    font-size: 16px;
    line-height: 1.6;
    color: var(--color-text);
    margin: 0;
}
/* v2.7.22 — back to flowing list (no absolute stacking). */
.ai-howit__steps {
    list-style: none;
    padding: 0;
    margin: 0;
    counter-reset: ai-steps;
    position: relative;
}
.ai-howit__step {
    position: relative;
    padding: 4px 0 26px 56px;
    min-height: 64px;
}
.ai-howit__step:not(:last-child)::before {
    content: "";
    position: absolute;
    left: 19px;
    top: 40px;
    bottom: -6px;
    width: 1px;
    background: rgba(35, 31, 32, 0.25);
}
.ai-howit__step-num {
    position: absolute;
    left: 0; top: 0;
    width: 40px; height: 40px;
    border-radius: 50%;
    border: 1.5px solid rgba(35, 31, 32, 0.35);
    color: var(--color-text);
    background: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    font-weight: 500;
    z-index: 1;
}
/* v2.6.3 — active/CTA step circle uses black instead of blue. */
.ai-howit__step.is-active .ai-howit__step-num,
.ai-howit__step-num--cta {
    background: #000;
    border-color: #000;
    color: #fff;
}
.ai-howit__step-body h3 {
    font-size: 21px;
    font-weight: 500;
    margin: 0 0 8px;
    line-height: 1.25;
}
.ai-howit__step-body p {
    margin: 0;
    font-size: 16px;
    line-height: 1.55;
    color: var(--color-text);
}
.ai-howit__step-note {
    margin-top: 8px !important;
    font-size: 14px !important;
    font-style: italic;
    color: #909090 !important;
}
.ai-howit__step--cta { padding-top: 8px; }
.ai-howit__step--cta .btn { margin-top: 18px; }

/* ---------- 6. COMPARISON TABLE ---------- */
.ai-compare {
    max-width: 1280px;
    /* v2.6.40 — uniform 150px gap between AI page sections. */
    margin: 150px auto 0;
    padding: 0 clamp(20px, 4vw, 80px);
    position: relative;
}
.ai-compare__head { max-width: 860px; margin-bottom: 56px; }
.ai-compare__title {
    font-size: clamp(34px, 4.2vw, 52px);
    font-weight: 400;
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin: 0 0 20px;
}
.ai-compare__lede {
    font-size: 16px;
    line-height: 1.6;
    color: var(--color-text);
    margin: 0;
    max-width: 600px;
}
.ai-compare__table {
    max-width: 860px;
    margin: 0 auto;
    background: rgba(255, 255, 255, 0.65);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    border: 1px solid rgba(35, 31, 32, 0.08);
    border-radius: 12px;
    overflow: hidden;
}
.ai-compare__row {
    display: grid;
    grid-template-columns: 1.2fr 1fr 1.1fr;
    gap: 0;
    align-items: stretch;
}
.ai-compare__row--head {
    background: rgba(255, 255, 255, 0.75);
}
.ai-compare__row--head .ai-compare__cell--col1,
.ai-compare__row--head .ai-compare__cell--col2 {
    font-size: 20px;
    font-weight: 600;
    color: #1e1e1e;
}
/* v2.6.3 — separate column borders: each cell carries its own
   bottom + right border so the table reads as a grid of cells
   rather than full-width horizontal rows. */
.ai-compare__cell {
    font-size: 15px;
    line-height: 1.5;
    color: #444;
    padding: 16px 22px;
    border-right: 1px solid rgba(35, 31, 32, 0.10);
    border-bottom: 1px solid rgba(35, 31, 32, 0.10);
    display: flex;
    align-items: center;
}
.ai-compare__cell:last-child { border-right: 0; }
.ai-compare__row:last-child .ai-compare__cell { border-bottom: 0; }
.ai-compare__row--head .ai-compare__cell { padding-top: 22px; padding-bottom: 22px; }
.ai-compare__cell--label {
    font-weight: 600;
    color: #000;
}
.ai-compare__cell--col2 {
    color: #000;
    font-weight: 500;
}

/* ---------- 7. WISHFORM (blue band) ---------- */
.ai-wishform {
    background: var(--color-accent);
    color: #fff;
    /* v2.6.40 — uniform 150px gap between AI page sections. */
    margin-top: 150px;
    padding: clamp(60px, 7vw, 100px) clamp(20px, 4vw, 80px);
}
.ai-wishform__inner {
    max-width: 1280px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(40px, 6vw, 80px);
    align-items: center;
}
.ai-wishform__title {
    font-size: clamp(36px, 5vw, 66px);
    font-weight: 500;
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin: 0;
    color: #fff;
    max-width: 660px;
}
.ai-wishform__body {
    margin: 24px 0 28px;
    font-size: 18px;
    line-height: 1.6;
    color: rgba(255, 255, 255, 0.95);
}
.ai-wishform__tags {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}
.ai-wishform__tags li {
    border: 1px solid rgba(255, 255, 255, 0.85);
    border-radius: 999px;
    padding: 6px 16px;
    font-size: 14px;
    color: #fff;
}
.ai-wishform__form { max-width: 480px; }
.ai-wishform__field {
    display: flex;
    align-items: stretch;
    background: #fff;
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
}
.ai-wishform__field input[type="email"] {
    flex: 1;
    border: 0;
    outline: 0;
    padding: 14px 18px;
    font-size: 16px;
    font-family: inherit;
    color: var(--color-text);
    background: #fff;
}
.ai-wishform__field input[type="email"]::placeholder { color: #999; }
.ai-wishform__submit {
    width: auto;
    min-width: 0;
    height: auto;
    border-radius: 0;
    padding: 0 22px;
    font-size: 14px;
    font-weight: 700;
    text-transform: none;
    white-space: nowrap;
}
.ai-wishform__help {
    margin: 14px 0 0;
    font-size: 14px;
    color: rgba(255, 255, 255, 0.92);
}
/* v2.12.148 — honeypot (must stay invisible & unfocusable) */
.spx-hp {
    position: absolute !important;
    left: -9999px !important;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}
/* v2.12.148 — waitlist submit confirmation (replaces the form on ?waitlist=ok) */
.ai-wishform__done {
    max-width: 480px;
    padding: 26px 28px;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: 10px;
}
.ai-wishform__done-check {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    margin-bottom: 12px;
    border-radius: 50%;
    background: #fff;
    color: var(--color-accent, #ff5a1f);
    font-size: 20px;
    font-weight: 700;
}
.ai-wishform__done-title {
    margin: 0 0 6px;
    font-size: 24px;
    font-weight: 700;
    color: #fff;
}
.ai-wishform__done-body {
    margin: 0;
    font-size: 15px;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.92);
}
/* v2.12.148 — inline error above the field on ?waitlist=err */
.ai-wishform__alert {
    margin: 0 0 12px;
    padding: 10px 14px;
    border-radius: 6px;
    background: rgba(255, 255, 255, 0.95);
    color: #a01818;
    font-size: 13px;
    font-weight: 600;
}

/* ---------- 8. FAQ ---------- */
.ai-faq {
    max-width: 1120px;
    /* v2.6.40 — uniform 150px gap between AI page sections. */
    margin: 150px auto 0;
    padding: 0 clamp(20px, 4vw, 80px);
}
/* v2.12.50 — AI FAQ header now mirrors home ("FAQ" eyebrow + "Questions we often get"). */
.ai-faq__eyebrow {
    font-size: 14.659px;
    font-weight: 500;
    margin: 0 0 5.32px;
    line-height: 1;
}
.ai-faq__title {
    font-size: 44px; /* feedback — match homepage .faq__title (was clamp 34-66) */
    font-weight: 500;
    line-height: 1.1;
    letter-spacing: -0.01em;
    margin: 0 0 36px;
}
.ai-faq__list {
    display: flex;
    flex-direction: column;
    border-top: 1px solid rgba(35, 31, 32, 0.18);
}
/* v2.12.29 — each column is its own flex stack; on mobile the two columns simply
   stack so all items read as one column. */
.ai-faq__col { display: flex; flex-direction: column; }
.ai-faq__item { border-bottom: 1px solid rgba(35, 31, 32, 0.18); }
.ai-faq__q {
    width: 100%;
    background: none;
    border: 0;
    padding: 24px 0;
    font-family: inherit;
    font-size: 16px; /* feedback — all FAQ question text 16px */
    font-weight: 500;
    color: var(--color-text);
    text-align: left;
    display: flex;
    align-items: center;
    justify-content: space-between;
    cursor: pointer;
    line-height: 1.4;
    transition: color .25s ease;
}
/* v2.6.3 — hover OR is-open opens the panel & tints the question
   blue (mirrors homepage .faq__item behaviour). */
.ai-faq__item:hover .ai-faq__q,
.ai-faq__item.is-open .ai-faq__q { color: var(--color-accent); }
.ai-faq__q-text { padding-right: 24px; flex: 1; }
/* v2.12.159 — SVG-mask "+" (see .faq__icon note): crisp, thin, uniform cross at
   any sub-pixel position / DPI, tinted by currentColor, rotates 45°→× on open.
   Identical to the home/services .faq__icon so all FAQ "+" match exactly. */
.ai-faq__icon {
    width: 14px; height: 14px;
    position: relative;
    flex-shrink: 0;
    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);
}
.ai-faq__item.is-open .ai-faq__icon { transform: rotate(45deg); }

/* Smooth grid-rows expand (same recipe as homepage .faq__panel). */
.ai-faq__panel {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows .4s cubic-bezier(.2,.7,.2,1);
    overflow: hidden;
}
.ai-faq__panel[hidden] { display: grid; }
.ai-faq__panel > p {
    min-height: 0;
    margin: 0;
    padding-top: 0;
    opacity: 0;
    transition: opacity .25s ease, padding-top .4s cubic-bezier(.2,.7,.2,1), padding-bottom .4s cubic-bezier(.2,.7,.2,1);
    font-size: 16px; /* feedback — all FAQ answer text 16px */
    line-height: 1.6;
    color: #444;
    max-width: 880px;
}
/* v2.11.54 — click-only open/close (no hover-open), matches homepage .faq. */
.ai-faq__item.is-open .ai-faq__panel { grid-template-rows: 1fr; }
.ai-faq__item.is-open .ai-faq__panel > p {
    opacity: 1;
    padding: 0 0 24px;
    transition-delay: .08s;
}
/* v2.12.26 — AI FAQ matches the homepage .faq "settings" (home/services use .faq; the
   AI page has its own .ai-faq, so mirror the rules here). DESKTOP (≥1025px) = 2 columns
   + hover-to-open; MOBILE (≤768px) = a centred 460px block with tighter rows. */
@media (min-width: 1025px) {
    /* 2 independent columns (the .ai-faq__col children) — align-items:start so a column
       only grows with its OWN open items; the neighbour column never gains an empty gap. */
    .ai-faq__list { display: grid; grid-template-columns: 1fr 1fr; column-gap: 66.66px; align-items: start; border-top: 0; }
    .ai-faq__item:hover .ai-faq__panel { grid-template-rows: 1fr; }
    .ai-faq__item:hover .ai-faq__panel > p { opacity: 1; padding: 0 0 24px; transition-delay: .08s; }
}
@media (max-width: 768px) {
    /* v2.12.47 — AI FAQ inner layout scaled to match the services/home FAQ (smaller,
       tighter, narrower). */
    /* v2.12.49 — headline shrunk to 30px to match home/services FAQ on mobile. */
    /* v2.12.50 — eyebrow thin+small+left to match home FAQ on mobile. */
    .ai-faq__eyebrow { font-weight: 300; font-size: 13px; text-align: left; }
    .ai-faq__title { font-size: 30px; font-weight: 500; text-align: left; }
    .ai-faq__list { max-width: 360px; margin-left: auto; margin-right: auto; }
    .ai-faq__q { padding: 9px 0; font-size: 16px; position: relative; } /* feedback — Q text 16px on mobile */
    .ai-faq__q-text { padding-right: 0; }
    .ai-faq__panel > p { font-size: 16px; } /* feedback — A text 16px on mobile */
    .ai-faq__item.is-open .ai-faq__panel > p { padding-bottom: 14px; }
    /* v2.12.151 — unify the FAQ "+" across breakpoints: keep the drawn
       .ai-faq__icon on mobile too (was swapped for a 22px font glyph) so it
       matches home/services + desktop. */
}

/* ---------- 9. BOTTOM CTA ---------- */
.ai-bottom-cta {
    position: relative;
    text-align: center;
    padding: clamp(90px, 10vw, 160px) clamp(20px, 4vw, 80px) clamp(120px, 12vw, 200px);
    max-width: 1100px;
    /* v2.6.40 — uniform 150px gap between AI page sections. */
    margin: 150px auto 0;
    /* v2.9.22 — visible so the cursor-follow blue glow (.work-detail__cta__bg,
       added to this CTA too) isn't hard-clipped at the section box. */
    overflow: visible;
}
.ai-bottom-cta__aurora {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(closest-side at 25% 40%, rgba(160, 215, 255, 0.45), transparent 70%),
        radial-gradient(closest-side at 75% 50%, rgba(220, 200, 255, 0.45), transparent 70%),
        radial-gradient(closest-side at 50% 75%, rgba(255, 232, 188, 0.40), transparent 65%);
    filter: blur(60px);
    opacity: 0.4;
}
/* v2.12.140 — REVERTED the v2.12.135 tablet/touch `overflow:hidden` on the
   bottom CTA: it hard-clipped the soft blue glow to the section rectangle
   (gradient looked chopped on tablet). The page's `html{overflow-x:clip}`
   already prevents any sideways scroll from the glow, so the CTA can keep
   `overflow:visible` (glow fades softly to the viewport edge, like desktop). */
.ai-bottom-cta__title,
.ai-bottom-cta__lede,
.ai-bottom-cta .btn { position: relative; z-index: 1; }
.ai-bottom-cta__title {
    font-size: 52px;
    font-weight: 500;
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin: 0;
    color: #000;
}
.ai-bottom-cta__lede {
    font-size: 18px;
    line-height: 1.6;
    color: var(--color-text);
    max-width: 760px;
    margin: 32px auto 40px;
}

/* ---------- responsive breakpoints ---------- */
@media (max-width: 1000px) {
    .ai-services__grid { grid-template-columns: repeat(2, 1fr); }
    .ai-approach__inner,
    .ai-howit__inner,
    .ai-wishform__inner { grid-template-columns: 1fr; }
    /* v2.12.62 — How It Works body text right edge aligned to where "GET A QUOTE"
       ends (~79px gap), like the other body copy. The lede starts at the 24px
       section padding (103 = 24 + 79); the step text is indented ~80px after the
       number (159 = 80 + 79), so it needs a bigger inset to land at the same edge. */
    .ai-howit__lede { max-width: calc(100vw - 64px); }
    /* constrain the step TEXT (not the whole step-body) so the CTA button below
       it isn't squeezed into a narrow 2-line block. */
    .ai-howit__step-body > h3,
    .ai-howit__step-body > p { max-width: calc(100vw - 159px); }
    /* v2.12.62 — Book a Discovery Call button: shorter rectangle (drop the 250px
       min-width + trim the side padding so it hugs its label).
       v2.12.63 — centre the button (rectangle) + its label. */
    .ai-howit__step--cta .btn--ai-cta {
        /* block-level flex (was inline-flex) so margin:auto can centre the rectangle
           without centring the heading/paragraph above it. */
        display: flex;
        /* v2.12.65 — longer rectangle again (wider padding), label centred inside. */
        min-width: 0; width: fit-content; padding: 0 44px; white-space: nowrap;
        margin-left: auto; margin-right: auto;
        justify-content: center; text-align: center;
        /* v2.12.66 — the body text above ends at the GET A QUOTE edge (rGap 79) while
           the step-body runs wider (rGap 39), so a step-body-centred button looks
           shifted right. Nudge it left by half that difference so it sits centred
           under the body text. */
        transform: translateX(-20px);
    }
    /* v2.12.64 — more AI Lab + About body copy gets the GET A QUOTE right-edge
       clearance (rGap 79). All start at the 24px section padding → 103 = 24 + 79. */
    .ai-compare__lede,
    .ai-wishform__body,
    .about-work__intro { max-width: calc(100vw - 64px); }
    .ai-compare__row { grid-template-columns: 1.4fr 1fr 1fr; padding: 14px 16px; }
    .ai-hero__arrow { display: none; }
}
@media (max-width: 700px) {
    .ai-porto__grid { grid-template-columns: 1fr; row-gap: 40px; }
    .ai-services__grid { grid-template-columns: 1fr; }
    .ai-services__card { min-height: 0; padding: 32px 24px; }
    .ai-approach__photos { grid-template-columns: 1fr 1fr; gap: 12px; }
    .ai-approach__photo--2 { margin-top: 0; }
    .ai-approach__photo--3 { margin-top: 0; }
    /* v2.12.37 — table slides sideways (3 cols kept, min-width) instead of stacking. */
    .ai-compare__row { grid-template-columns: 1.4fr 1fr 1fr; min-width: 560px; gap: 0; }
    .ai-compare__cell--label { font-size: 14px; }
    .ai-wishform__field { flex-direction: column; }
    .ai-wishform__submit { width: 100%; padding: 14px; }
    .ai-hero__stats { flex-direction: column; }
    .ai-hero__stats li + li::before { display: none; }
}

/* =========================================================
   v2.12.9 — AI LAB mobile revisions
   ========================================================= */
@media (max-width: 768px) {
    /* GAP -50%: section rhythm 150px → 75px. */
    .ai-porto, .ai-services, .ai-approach, .ai-howit, .ai-compare, .ai-faq { margin-top: 75px; }
    /* v2.12.35 — gap FAQ→CTA matched to the services testimonials→CTA rhythm
       (margin-top 50 + padding-top 50 = the same ~130px gap). */
    .ai-bottom-cta { margin-top: 50px !important; padding-top: 50px !important; padding-bottom: 90px; }

    /* Right (+left) gutter so no AI section hugs the screen edge. box-sizing:border-box
       because global box-sizing is OFF — without it the padding widens the section and
       pushes content past the right edge ("mepet kanan"). */
    .ai-hero, .ai-porto, .ai-services, .ai-approach, .ai-howit, .ai-compare,
    .ai-wishform, .ai-faq { box-sizing: border-box; padding-left: 24px; padding-right: 24px; }

    /* v2.12.35 — AI hero buttons: equal width + centred so "Book a Discovery Call"
       (was wider than Explore Services) reads balanced with proper side margin. */
    .ai-hero__actions { flex-direction: column; align-items: center; gap: 12px; }
    .ai-hero__actions > * { width: 100%; max-width: 280px; justify-content: center; box-sizing: border-box; }

    /* Portfolio grid = ONE column on phones, centered like the homepage (the 2-col base
       overflowed/cropped on the right). !important guards against any stale/specific rule. */
    .ai-porto__grid { grid-template-columns: 1fr !important; }

    /* Static (reverted) trusted-by row: tidy wrapping logos at a uniform height. */
    .ai-hero__clients-row { gap: 18px 26px; opacity: 0.7; }
    .ai-hero__clients-row img { width: auto; height: 26px; }

    /* "Model" porto cards: smaller text on ONE line, matching the home/porto cards. */
    .ai-porto__title { font-size: 18px; margin: 12px 0 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .ai-porto__sub { font-size: 14px; }

    /* Team/approach photos: smaller + centred like the homepage CTA (120px cells). */
    .ai-approach__photos {
        grid-template-columns: 120px 120px; gap: 12px;
        max-width: max-content; margin-left: auto; margin-right: auto; justify-content: center;
    }
    /* v2.12.23 — ZIG-ZAG on mobile (Figma 266:1607): right column (Mark --2, Jean --4) up,
       left column flat. Scaled to the 120px photos (−28px ≈ the desktop −48px ÷ size ratio). */
    .ai-approach__photo--2,
    .ai-approach__photo--4 { margin-top: -28px !important; }
    .ai-approach__photo--1,
    .ai-approach__photo--3 { margin-top: 0 !important; }

    /* Static page (no scroll highlight) → make ALL step numbers the same black. */
    .ai-howit__step-num { background: #000; border-color: #000; color: #fff; }

    /* Section-title emphasis → site blue #1566E0 (was the orange accent). */
    .ai-hero__title em, .ai-services__title em, .ai-howit__title em,
    .ai-compare__title em, .ai-bottom-cta__title em, .ai-approach__title em { color: #1566e0; }

    /* v2.12.37 — comparison table SLIDES sideways when text is long (CSS scroll), instead
       of stacking. The header row shows again and the stacked per-cell labels are dropped. */
    .ai-compare__table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .ai-compare__cell--col1::before,
    .ai-compare__cell--col2::before { content: none; }
}

/* =========================================================
   v2.6.33 — Homepage CTA portraits staggered (Figma 22:1076).
   Column 2 (Mark + Jean) sits HIGHER than column 1 — same
   bias as the AI page approach section. Achieved by pushing
   column 1 (Kelvin + Syafiq) DOWN by 80px.
   ========================================================= */
.cta__portrait:nth-child(1),
.cta__portrait:nth-child(3) {
    transform: translateY(80px);
}
.cta__portraits {
    /* Reserve the bottom space the translated col-1 portraits occupy. */
    padding-bottom: 80px;
}
@media (max-width: 768px) {
    /* v2.12.23 — zig-zag ON mobile too (Figma 266:1607): left column (Kelvin 1, Syafiq 3)
       drops so the right column reads higher. Scaled to the 120×146 mobile photos
       (28px ≈ the desktop 80px offset ÷ the size ratio). padding-bottom reserves it. */
    .cta__portrait:nth-child(1),
    .cta__portrait:nth-child(3) { transform: translateY(28px); }
    .cta__portraits { padding-bottom: 28px; }
}

/* =========================================================
   SERVICES PAGE (page-services.php) — Figma 279:1504
   Reuses .clients / .portfolio__card / .faq / .testimonials /
   .work-detail__cta from elsewhere; the .svc-* rules below are
   the service-specific sections.
   ========================================================= */
/* Full-width page with even gutters that match the navbar
   (clamp(20px,3.3vw,63px)) — no 1280 cap, so wide monitors don't leave a big
   empty right margin. All svc sections pad with --svc-gutter for equal sides. */
.site-main--services {
    padding-bottom: 0;
    max-width: none;
    width: 100%;
    --svc-gutter: clamp(20px, 3.3vw, 63px);
}
.svc-section-title {
    font-size: 44px; font-weight: 500; text-align: center;
    letter-spacing: -0.01em; margin: 0 0 48px; color: var(--color-text);
}

/* ---- 1. Hero ---- */
.svc-hero { padding: 56px var(--svc-gutter) 0; }
/* H1 hugs the LEFT gutter; the aside (lede + buttons) hugs the RIGHT gutter so
   both sides touch their margins evenly — no trapped space that makes the right
   margin look bigger. The left 1fr absorbs the slack between them. */
.svc-hero__top {
    /* feedback — per Figma: headline left, aside (body + buttons) top-aligned
       to the headline. Wider aside column + smaller gap pulls the body/buttons
       in from the far-right edge so they don't look stranded. */
    display: grid; grid-template-columns: 1fr minmax(0, 540px); gap: clamp(28px, 3vw, 56px);
    align-items: start; margin-bottom: 40px;
}
.svc-hero__title {
    font-size: 44px; font-weight: 500; line-height: 1.1;
    /* feedback — "2D/3D Animation Studio in Singapore" must sit on ONE line.
       The old max-width:560 capped the title narrower than its column; removed
       so it uses the full left column. (The longer Immersive/Video titles may
       still wrap — they're too long for one line at this size.) */
    letter-spacing: -0.01em; margin: 0 0 14px; max-width: none; color: var(--color-text);
}
.svc-hero__oneliner { font-size: 21px; color: var(--color-muted); margin: 0; } /* feedback S1 — sub-headline +2pt (18→21) */
/* v2.12.168 — aside is a flex column that STRETCHES to the hero-top row height (=
   the taller of the two columns). The lede stays at the top; the buttons get
   margin-top:auto so they drop to the BOTTOM of the row → level with the end of the
   left sub-headline (oneliner) when the left column is taller (2D/3D/Video). When the
   lede is long enough that the aside is the taller column (Immersive), the row = aside
   height, auto-margin collapses to 0, and the buttons sit naturally right after the
   lede. Stacked layout (<=1100) resets align-self:start below, so no effect there. */
.svc-hero__aside { align-self: stretch; justify-self: end; width: 100%; max-width: 540px; display: flex; flex-direction: column; }
/* feedback S1 — bigger hero buttons (were standard 148×36 / 132px). */
.svc-hero__actions .btn { height: 44px; font-size: 14px; width: auto; padding: 0 26px; min-width: 150px; }
.svc-hero__lede { font-size: 18px; line-height: 1.5; color: var(--color-text); margin: 0 0 22px; } /* feedback — body lede 18px */
.svc-hero__actions { display: flex; gap: 16px; flex-wrap: wrap; justify-content: flex-start; margin-top: auto; } /* v2.12.168 — margin-top:auto drops the buttons to the bottom of the stretched aside → level with the sub-headline end */
.svc-hero__media {
    border-radius: 0; overflow: hidden; aspect-ratio: 1200 / 390; background: #1a1a1a;
}
.svc-hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: center bottom; }
/* v2.12.172 — Immersive banner: show the head AND the TV/screen (the "project") in
   front of the woman, which sits just below the head. center-top cut the screen off
   the bottom; center 40% drops the crop window so the head + full screen stay in
   frame. Immersive only. Tune the % (lower = more headroom, higher = more of the TV). */
.svc-hero--immersive .svc-hero__media img { object-position: center 40%; }
/* ---- Hero foot: stats (left) + Trusted-by logos (right) on one row ---- */
.svc-hero__foot {
    display: flex; align-items: center; gap: 40px; margin-top: 26px;
}
.svc-hero__stats {
    display: flex; align-items: center; gap: 20px; list-style: none;
    margin: 0; padding: 0; font-size: 18px; color: var(--color-text); flex: 0 0 auto; /* feedback — stats 18 */
}
.svc-hero__stats-sep { width: 1px; height: 16px; background: rgba(0,0,0,.25); }
/* label ON TOP, sliding logos BELOW it (logos start under the "T"). */
.svc-hero__trusted {
    flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
    position: static; width: auto; max-width: none; margin: 0; padding: 0;
    background: transparent;
}
.svc-trusted__label {
    flex: 0 0 auto; font-size: 16px; letter-spacing: .04em; /* feedback — Trusted by 12→16 */
    color: var(--color-muted-2); margin: 0; text-transform: none; white-space: nowrap;
}
.svc-hero__trusted .clients__marquee { width: 100%; min-width: 0; margin: 0; overflow: hidden; }
.svc-hero__trusted .clients__logo { width: 145px; height: 50px; object-fit: contain; } /* feedback — uniform 145×50 logo box across all sliders */

/* ---- 3. Selected work (16:9 cells, sharp corners) ---- */
.svc-work { padding: 90px var(--svc-gutter) 0; }
.svc-work__grid { display: grid; grid-template-columns: 1fr 1fr; column-gap: 40px; row-gap: clamp(40px, 5vw, 80px); }
.svc-work .portfolio__thumb {
    display: block; aspect-ratio: 16 / 9; height: auto; border-radius: 0; overflow: hidden;
}
.svc-work .portfolio__thumb-img { width: 100%; height: 100%; object-fit: cover; border-radius: 0; }

/* v2.11.87 — Selected Work SHOW MORE (Video Production has 6 cards). Collapsed,
   the grid is clipped (max-height set by main.js to show ~4 cards + a peek of the
   next row) under a white gradient fade with a centred SHOW MORE button; clicking
   reveals the rest. Pages with <=4 cards never get the wrapper. */
.svc-work__reveal { position: relative; }
.svc-work__reveal.is-collapsed { overflow: hidden; }
.svc-work__fade {
    position: absolute; left: 0; right: 0; bottom: 0; height: 300px;
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, #fff 70%);
    pointer-events: none; z-index: 2;
}
.svc-work__more {
    position: absolute; left: 50%; bottom: 6px; transform: translateX(-50%);
    z-index: 3; background: none; border: 0; cursor: pointer; padding: 8px 16px;
    display: inline-flex; flex-direction: column-reverse; align-items: center; gap: 10px;
    font-family: inherit; font-size: 14px; font-weight: 600; letter-spacing: 0.04em;
    text-transform: uppercase; color: #000; line-height: 1; transition: color .2s ease;
}
.svc-work__more:hover { color: var(--color-primary); }
.svc-work__more-chevron {
    width: 12px; height: 12px;
    border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
    transform: rotate(45deg) translate(-1px, -1px);
    transition: transform .2s ease;
}
/* Expanded: hide the fade, keep the button as a SHOW LESS toggle below the grid,
   and flip the chevron to point up. */
.svc-work__reveal:not(.is-collapsed) .svc-work__fade { display: none; }
.svc-work__reveal:not(.is-collapsed) .svc-work__more {
    position: static; left: auto; bottom: auto; transform: none;
    display: flex; width: fit-content; margin: 28px auto 0;
}
.svc-work__reveal:not(.is-collapsed) .svc-work__more-chevron {
    transform: rotate(225deg) translate(-1px, -1px);
}

/* v2.11.89 — Selected Work as 3 cards per row. Live on the Video Production page
   in ALL environments (.svc-video-production body class), and on every service page
   on staging only (.spx-staging) so 3-col can still be previewed there.
   Above 700px only — mobile stays single column. */
@media (min-width: 701px) {
    .spx-staging .svc-work .ai-porto__grid,
    .svc-video-production .svc-work .ai-porto__grid { grid-template-columns: repeat(3, 1fr); }
}

/* ---- 4. Why it works ---- */
.svc-why { padding: 110px var(--svc-gutter) 0; }
/* feedback — Why frame is a 16:9 (= Selected Work thumbnail) that FILLS the right
   column (no blank space), content not cropped. The left text column stretches to
   the frame height with the checks pinned to the bottom, so the copy lines up with
   the frame top and bottom. (Each section's copy is 2 paragraphs.) */
.svc-why__inner { display: grid; grid-template-columns: 548px 1fr; gap: 52px; align-items: stretch; }
.svc-why__text { display: flex; flex-direction: column; }
.svc-why__title { font-size: 44px; font-weight: 500; line-height: 1.25; letter-spacing: -0.01em; margin: 0 0 26px; }
.svc-why__para { font-size: 18px; line-height: 1.5; color: var(--color-text); margin: 0 0 30px; }
.svc-why__checks { display: flex; flex-wrap: wrap; gap: 14px 18px; list-style: none; margin: 30px 0 0; padding: 0; margin-top: auto; } /* feedback — wrap + pinned to the bottom so it lines up with the frame bottom */
.svc-why__checks li { display: inline-flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 400; white-space: nowrap; }
/* checkmarks are STROKE (outlined circle), not a filled disc */
.svc-why__check {
    width: 16px; height: 16px; border-radius: 50%; background: transparent;
    border: 1.5px solid var(--color-accent); flex: 0 0 16px; position: relative;
}
.svc-why__check::after {
    content: ""; position: absolute; left: 4.5px; top: 3px; width: 3.5px; height: 6.5px;
    border: solid var(--color-accent); border-width: 0 1.5px 1.5px 0; transform: rotate(45deg);
}
.svc-why__media {
    /* feedback — frame height ALWAYS equals the left text (align-items:stretch on
       the grid drives it; the media's own content is absolutely-positioned so it
       has no intrinsic height). So it stays level with the copy at every width and
       NEVER balloons taller on a wide/zoomed-out screen. Fills the column width. */
    position: relative; min-height: 320px; border-radius: 0;
    overflow: hidden; background: #d9d9d9;
}
.svc-why__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* numbered process buttons — grey glassmorphism, blue when active */
.svc-why__dots { position: absolute; left: 24px; bottom: 22px; display: flex; gap: 15px; }
.svc-why__dot {
    width: 30px; height: 30px; border-radius: 50%; border: 1px solid rgba(255,255,255,.5);
    background: rgba(255,255,255,.18); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    color: #fff; font-size: 14px; font-weight: 500; font-family: inherit; cursor: pointer;
    display: flex; align-items: center; justify-content: center; transition: background .2s ease, border-color .2s ease;
}
.svc-why__dot.is-on { background: var(--color-accent); border-color: var(--color-accent); }
.svc-why__media-label {
    position: absolute; right: 20px; bottom: 24px; font-size: 20px; font-weight: 500; color: #fff;
}

/* ---- 5. What we offer (accordion) ---- */
.svc-offer { position: relative; padding: 120px var(--svc-gutter) 90px; margin-top: 100px; overflow: visible; }
/* Green glow: RIGHT side only, low opacity. Extends UP (top:-220px) to reach the
   bottom of the Why-2D photo; soft radial that fades out (no hard crop edge). */
.svc-offer__bg {
    position: absolute; z-index: 0; pointer-events: none;
    top: -220px; bottom: 60px; right: calc(50% - 50vw); width: 58vw;
    background: radial-gradient(70% 55% at 100% 38%, rgba(120, 205, 160, 0.26), rgba(120, 205, 160, 0) 72%);
}
.svc-offer__head, .svc-offer__list { position: relative; z-index: 1; }
.svc-offer__head { text-align: center; max-width: 980px; margin: 0 auto 44px; } /* feedback — wider so the offer sub reads as 2 lines (was 720) */
.svc-offer__title { font-size: 44px; font-weight: 500; letter-spacing: -0.01em; margin: 0 0 16px; }
/* feedback — the sub must read as exactly 2 lines (the <br> split). The 720px
   head was too narrow so each half wrapped again → 3-4 lines. Give the sub its
   own wider track so each half stays on one line on desktop. */
.svc-offer__sub { font-size: 17px; line-height: 1.5; color: var(--color-muted); margin: 0 auto; max-width: 980px; }
.svc-offer__list { list-style: none; margin: 0 auto; padding: 0; max-width: 1055px; }
.svc-offer__item { border-top: 1px solid rgba(0,0,0,.16); }
.svc-offer__item:last-child { border-bottom: 1px solid rgba(0,0,0,.16); }
.svc-offer__row {
    display: flex; align-items: center; gap: 40px; width: 100%; padding: 22px 4px;
    background: none; border: 0; cursor: pointer; text-align: left; font-family: inherit;
    color: var(--color-text); transition: color .2s ease;
}
.svc-offer__num { font-size: 21px; font-weight: 400; width: 40px; flex: 0 0 40px; }
.svc-offer__name { font-size: 21px; font-weight: 500; text-transform: capitalize; }
.svc-offer__item:hover .svc-offer__row,
.svc-offer__item.is-open .svc-offer__row,
.svc-offer__row:hover { color: var(--color-accent); }
/* Closed = TITLE ONLY (panel fully collapsed). Opens on HOVER (like .faq);
   click toggles .is-open to persist. max-height collapse is bulletproof here —
   the grid-rows trick leaked because the aspect-ratio video resisted it. */
.svc-offer__panel {
    overflow: hidden; max-height: 0;
    transition: max-height .45s cubic-bezier(.2,.7,.2,1);
}
.svc-offer__item:hover .svc-offer__panel,
.svc-offer__item.is-open .svc-offer__panel { max-height: 560px; }
.svc-offer__panel-inner {
    display: grid; grid-template-columns: 345px 1fr; gap: 56px; align-items: start;
    padding: 8px 4px 36px 80px;
}
.svc-offer__media {
    position: relative; overflow: hidden; aspect-ratio: 345 / 200; border-radius: 0; background: #585858;
    display: flex; align-items: center; justify-content: center; color: #fff; font-size: 16px;
}
/* feedback — offer thumbnail NOT darkened: full-brightness image (the .55 dim
   was only there to keep the now-removed "VIDEO PLAYBACK" label readable). */
.svc-offer__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 1; }
.svc-offer__media span { position: relative; z-index: 1; font-weight: 500; }
/* When an offer has a video, the media is a button that opens the modal. */
.svc-offer__media--play { width: 100%; padding: 0; border: 0; font: inherit; cursor: pointer; }
.svc-offer__media--play::after {
    content: ""; position: absolute; z-index: 1; left: 50%; top: 50%;
    width: 0; height: 0; transform: translate(-40%, -50%);
    border-style: solid; border-width: 11px 0 11px 18px; border-color: transparent transparent transparent #fff;
    opacity: 0; transition: opacity .2s ease;
    filter: drop-shadow(0 1px 3px rgba(0,0,0,.5));
}
/* Only a slight dim on hover so the white play triangle stays visible. */
.svc-offer__media--play:hover img,
.svc-offer__media--play:focus-visible img { opacity: .82; }
.svc-offer__media--play:hover::after,
.svc-offer__media--play:focus-visible::after { opacity: 1; }
.svc-offer__desc { font-size: 17px; line-height: 1.5; margin: 0 0 18px; max-width: 360px; }
.svc-offer__best-label { font-size: 14px; color: var(--color-muted); margin: 0 0 2px; }
.svc-offer__best { font-size: 14px; color: var(--color-muted); margin: 0 0 26px; max-width: 360px; line-height: 1.45; }
.svc-offer__cta { min-width: 0; }

/* ---- 4b. Why media as a live slideshow (Figma 296:2679 stages) ----
   Keeps the original Why layout (text | single media frame); the blue 1/2/3/4
   buttons now cross-fade between the production-stage images. */
.svc-why__media--slides .svc-why__slide {
    position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
    opacity: 0; transition: opacity .5s ease; z-index: 0;
}
.svc-why__media--slides .svc-why__slide.is-on { opacity: 1; }
/* darken the bottom so the dots + label stay legible over any frame */
.svc-why__media--slides::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 130px;
    background: linear-gradient(to top, rgba(30, 30, 30, .5), rgba(30, 30, 30, 0));
    pointer-events: none; z-index: 1;
}
.svc-why__media--slides .svc-why__dots,
.svc-why__media--slides .svc-why__media-label { z-index: 2; }
/* slides are clickable → open the full-size popup viewer */
.svc-why__media--slides { cursor: zoom-in; }
.svc-why__expand {
    position: absolute; top: 16px; right: 16px; z-index: 2;
    width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;
    border: 0; background: rgba(0, 0, 0, .45); color: #fff; font-size: 20px; line-height: 1;
    cursor: zoom-in; opacity: .9; transition: background-color .2s ease, opacity .2s ease;
}
.svc-why__expand:hover { background: rgba(0, 0, 0, .65); opacity: 1; }

/* ---- Why-process popup viewer (lightbox with prev/next) ---- */
.svc-why-lb {
    position: fixed; inset: 0; z-index: 1000;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
    padding: 4vmin; background: rgba(10, 10, 12, .92);
    opacity: 0; visibility: hidden; transition: opacity .28s ease, visibility .28s ease;
    cursor: zoom-out;
}
.svc-why-lb.is-open { opacity: 1; visibility: visible; }
.svc-why-lb__stage { position: relative; display: flex; align-items: center; justify-content: center; max-width: 100%; max-height: 100%; }
.svc-why-lb__img,
.svc-why-lb__video {
    max-width: 90vw; max-height: 80vh; object-fit: contain; cursor: default;
    box-shadow: 0 24px 80px -20px rgba(0, 0, 0, .7);
}
.svc-why-lb__close {
    position: absolute; top: 18px; right: 24px; width: 44px; height: 44px;
    border: 0; background: transparent; color: #fff; font-size: 34px; line-height: 1;
    cursor: pointer; opacity: .85; z-index: 2;
}
.svc-why-lb__close:hover { opacity: 1; }
.svc-why-lb__nav {
    position: absolute; top: 50%; transform: translateY(-50%);
    width: 56px; height: 56px; border: 0; background: rgba(255, 255, 255, .12);
    color: #fff; font-size: 40px; line-height: 1; cursor: pointer;
    display: flex; align-items: center; justify-content: center; border-radius: 50%;
    opacity: .85; transition: background-color .2s ease, opacity .2s ease; z-index: 2;
}
.svc-why-lb__nav:hover { background: rgba(255, 255, 255, .25); opacity: 1; }
.svc-why-lb__nav--prev { left: 24px; }
.svc-why-lb__nav--next { right: 24px; }
/* title chip sits BELOW the photo/video, centered as part of the column; the
   centered column keeps it clear of the very bottom of the screen */
.svc-why-lb__label {
    position: relative; flex: 0 0 auto;
    padding: 6px 16px; color: #fff; font-size: 14px; font-weight: 500; white-space: nowrap;
    background: rgba(255, 255, 255, .14);
    -webkit-backdrop-filter: blur(14px) saturate(150%);
    backdrop-filter: blur(14px) saturate(150%);
    border: 1px solid rgba(255, 255, 255, .22);
    border-radius: 9px;
    box-shadow: 0 8px 30px -10px rgba(0, 0, 0, .5);
    pointer-events: none; z-index: 2;
}
@media (max-width: 768px) {
    /* v2.12.26 — responsive popup: the media fits the screen and stays centred. */
    .svc-why-lb { padding: 14px; gap: 16px; justify-content: center; }
    .svc-why-lb__stage { width: 100%; }
    /* v2.12.54 — min-width:0 is REQUIRED: a <video> flex item defaults to
       min-width:auto = its intrinsic 1920px, which beats max-width (min wins),
       so slide-4's video rendered huge and slid right. Forcing min-width:0 lets
       max-width:92vw apply so the video centres like the image slides. */
    .svc-why-lb__img,
    .svc-why-lb__video { max-width: 92vw; max-height: 58vh; margin: 0 auto; min-width: 0; }
    /* v2.12.54 — arrows back on the LEFT/RIGHT of the media (like the portfolio
       popup), vertically centred, instead of a bottom pair. */
    .svc-why-lb__nav {
        top: 50%; bottom: auto; transform: translateY(-50%);
        width: 44px; height: 44px; font-size: 26px; background: rgba(255, 255, 255, .16);
    }
    .svc-why-lb__nav--prev { left: 6px; right: auto; }
    .svc-why-lb__nav--next { right: 6px; left: auto; }
    .svc-why-lb__close { top: 12px; right: 14px; }
    /* v2.12.54 — caption sits at the bottom centre (arrows are on the sides now). */
    .svc-why-lb__label { position: absolute; left: 50%; transform: translateX(-50%); bottom: 24px; margin: 0; }
}

/* ---- 6. How we work ---- */
.svc-how { padding: 100px var(--svc-gutter) 0; text-align: center; }
.svc-how__title { font-size: 44px; font-weight: 500; letter-spacing: -0.01em; margin: 0 0 14px; }
.svc-how__lede { font-size: 18px; color: var(--color-muted); margin: 0 0 60px; }
.svc-how__steps {
    list-style: none; margin: 0; padding: 0; display: flex; justify-content: center; gap: 45px;
}
.svc-how__step {
    position: relative; flex: 0 0 187px; max-width: 187px; display: flex; flex-direction: column; align-items: center;
}
.svc-how__step:not(:last-child)::after {
    content: ""; position: absolute; top: 20px; right: -33px; width: 22px; height: 1px; background: rgba(0,0,0,.4);
}
.svc-how__num {
    width: 40px; height: 40px; border-radius: 50%; border: 0; background: #000; color: #fff;
    display: flex; align-items: center; justify-content: center; font-size: 18px; margin-bottom: 16px;
}
.svc-how__step-name { font-size: 20px; font-weight: 500; margin: 0 0 8px; }
.svc-how__step-note { font-size: 16px; line-height: 1.4; color: var(--color-muted); margin: 0; }

/* ---- 9. CTA related services (rest reuses .work-detail__cta / .ai-bottom-cta) ---- */
.svc-cta { text-align: center; }
/* v2.11.87 — services CTA italic accent stays BLUE (the .work-detail__cta em rule
   forces it black; this equal-specificity rule, later in source, wins back blue). */
.svc-cta .ai-bottom-cta__title em { color: var(--color-accent); }
.svc-cta__actions { display: inline-flex; gap: 18px; flex-wrap: wrap; justify-content: center; margin-top: 8px; }
.svc-cta .btn--outline-dark.svc-cta__call {
    display: inline-flex; align-items: center; justify-content: center; height: 56px; padding: 0 36px; font-size: 18px;
}
.svc-cta__related { margin-top: 70px; }
.svc-cta__related-label { font-size: 22px; font-weight: 500; margin: 0 0 18px; }
.svc-cta__related-list {
    list-style: none; margin: 0; padding: 0; display: inline-flex; gap: 56px; flex-wrap: wrap; justify-content: center;
}
.svc-cta__related-list a { font-size: 18px; font-weight: 500; color: var(--color-text); transition: color .2s ease; }
.svc-cta__related-list a:hover { color: var(--color-accent); }

/* feedback — on 2K/4K monitors widen the hero aside so the body lede reads as
   exactly 2 lines (it stays 3-4 lines on normal screens, which the user is fine
   with). The headline column (1fr) still has ample room at these widths. */
@media (min-width: 2000px) {
    .svc-hero__top { grid-template-columns: 1fr minmax(0, 1180px); }
    .svc-hero__aside { max-width: 1180px; }
}

/* ---- Services responsive ---- */
@media (max-width: 1100px) {
    .svc-hero__top { grid-template-columns: 1fr; gap: 24px; align-items: start; }
    .svc-hero__aside { align-self: start; justify-self: start; max-width: none; }
    .svc-hero__actions { justify-content: flex-start; }
    .svc-why__inner { grid-template-columns: 1fr; gap: 32px; align-items: start; }
    .svc-why__media { aspect-ratio: 16 / 9; min-height: 0; max-width: none; } /* stacked: own 16:9 height */
    .svc-offer__panel-inner { grid-template-columns: 300px 1fr; gap: 36px; padding-left: 40px; }
    .svc-how__steps { flex-wrap: wrap; gap: 40px 24px; }
    .svc-how__step:not(:last-child)::after { display: none; }
    .svc-hero__foot { flex-direction: column; align-items: flex-start; gap: 18px; }
    .svc-hero__trusted { width: 100%; }
}
@media (max-width: 700px) {
    .svc-hero__title { font-size: 34px; }
    .svc-section-title, .svc-why__title, .svc-offer__title, .svc-how__title { font-size: 30px; }
    .svc-work__grid { grid-template-columns: 1fr; row-gap: 32px; }
    .svc-why__checks { flex-wrap: wrap; }
    .svc-offer__panel-inner { grid-template-columns: 1fr; gap: 20px; padding-left: 0; }
    .svc-offer__item:hover .svc-offer__panel,
    .svc-offer__item.is-open .svc-offer__panel { max-height: 820px; }
    .svc-offer__row { gap: 20px; }
    .svc-offer__num, .svc-offer__name { font-size: 19px; }
    .svc-how__step { flex-basis: 130px; }
    .svc-cta__related-list { gap: 22px 32px; }
}
@media (max-width: 480px) {
    .svc-hero, .svc-work, .svc-why, .svc-how { padding-left: 20px; padding-right: 20px; }
    .svc-offer { padding-left: 20px; padding-right: 20px; }
    .svc-hero__stats { flex-wrap: wrap; gap: 8px 14px; }
}

/* =========================================================
   MOBILE — ALL INNER PAGES (v2.11.20)
   The homepage mobile pass lives in main.css; this block tidies every
   other template at <=768px: collapse the remaining fixed-width desktop
   columns to 1 column and normalise side padding to 20px so no page
   overflows sideways (the "space di kiri" reports).
   ========================================================= */
@media (max-width: 768px) {
    /* ---- Portfolio listing (/portfolios/) ---- */
    /* v2.12.67 — title size + body matched to About.
       v2.12.68 — title top aligned to About's blue "ABOUT US" eyebrow (~124px from
       top), NOT the About title. 60 padding + 64 header offset = 124. */
    .works { padding: 60px 20px 80px; }
    .works__head { grid-template-columns: 1fr; gap: 28px; }
    .works__title { font-size: 48px; }
    .works__intro { font-size: 16px; max-width: calc(100vw - 60px); }

    /* v2.12.70 — Contact page matched to the other pages: top 60px, L/R 20px, title 48px
       (bottom padding left as-is via the base shorthand). */
    .contact { padding-top: 60px; padding-left: 20px; padding-right: 20px; }
    .contact__title { font-size: 48px; }
    /* v2.12.71 — gap before the form trimmed 130 → 60 (mobile only; desktop kept). */
    .contact__head { margin-bottom: 60px; }

    /* v2.12.84 — right-edge CROP fix on the /contact/ PAGE only (NOT the pop-up, which
       keeps its own rules). Global box-sizing is OFF (content-box), so two things spilled
       past the right gutter and triggered horizontal scroll that ate the right margin:
       (1) the intl-tel-input flag padding on the phone input, and (2) the full-width
       "Not Sure Yet…" pill (flex-basis:100% + padding + nowrap). border-box keeps the
       100%-width elements inside their box; wrapping keeps the long pill text in-bounds.
       Scoped with :not(.contact--modal) so the pop-up is untouched. */
    .contact:not(.contact--modal) .contact__form .iti,
    .contact:not(.contact--modal) .contact__form .iti > input[type="tel"],
    .contact:not(.contact--modal) .contact__pill { box-sizing: border-box; }
    /* v2.12.95 — "Not Sure Yet…" matches the other pills at 15px now (uniform).
       white-space:normal stays as a safety so the long label wraps instead of
       cropping past the right gutter on very narrow phones. */
    .contact:not(.contact--modal) .contact__field[data-quote-type-field] .contact__pill:last-child { white-space: normal; font-size: 15px; }

    /* ---- Blog single + portfolio article column ---- */
    /* v2.12.61 — header→title gap matched to the blog LISTING page ("page awal blog").
       v2.12.69 — padding-top set to 60 to match .works/.news/.work-detail. */
    .article { padding: 60px 20px 64px; }
    .article__title { font-size: 32px; }
    .article__hero { margin-bottom: 48px; }
    /* v2.12.81 — blog body rhythm at ≤768 (tablet), per supplied scale. */
    .article__body { font-size: 17px; line-height: 1.65; }
    .article__body p { font-size: 17px; line-height: 1.65; margin: 0 0 18px; }
    .article__body h1 { font-size: 32px; margin: 44px 0 20px; }
    .article__body h2 { font-size: 26px; margin: 38px 0 16px !important; }
    .article__body h3 { font-size: 21px; margin: 32px 0 14px !important; }
    .article__body h4 { font-size: 18px; margin: 26px 0 12px; }
    .article__body p:empty,
    .article__body h2:empty,
    .article__body h3:empty { display: none !important; margin: 0 !important; }
    .article__body ul,
    .article__body ol { margin-bottom: 18px; }
    /* v2.12.59 — much smaller image/embed margins (were 36 and not collapsing with the
       adjacent paragraph). !important beats `.article__body .wp-block-embed{margin:36px}`. */
    .article__body .wp-block-image,
    .article__body figure,
    .article__body .wp-block-embed,
    .article__body .yt-facade,
    .article__body > img,
    .article__body p > img { margin-top: 22px !important; margin-bottom: 22px !important; }
    /* v2.12.82 — equal breathing room above AND below an in-article banner/video.
       A heading right after one would otherwise add its big top-margin on top of
       the banner's bottom-margin → the gap below looked bigger than above. When a
       heading directly follows a banner, drop its top-margin so both sides match. */
    .article__body .wp-block-image + h2,
    .article__body .wp-block-image + h3,
    .article__body figure + h2,
    .article__body figure + h3,
    .article__body .wp-block-embed + h2,
    .article__body .wp-block-embed + h3,
    .article__body .yt-facade + h2,
    .article__body .yt-facade + h3 { margin-top: 0 !important; }

    /* Writer + Recent posts (same content/settings, phone layout) */
    .article-extra { margin-top: 56px; }
    .article-recent { margin-top: 64px; }
    .article-recent__title { font-size: 24px; }

    /* ---- Services landing + 4 service pages ---- */
    .svc-hero__top { grid-template-columns: 1fr; gap: 24px; }
    .svc-hero__aside { max-width: 100%; justify-self: stretch; }
    .svc-hero__title { font-size: 32px; }
    .svc-hero__oneliner { font-size: 18px; }
    .svc-hero__foot { flex-direction: column; align-items: flex-start; gap: 22px; }
    .svc-why__inner { grid-template-columns: 1fr; gap: 28px; }
    .svc-why__title { font-size: 32px; }

    /* ---- About: How-we-work 2-col (380px sidebar) stacks ---- */
    .about-work__inner { grid-template-columns: 1fr; gap: 28px; }

    /* About people/culture marquee: photos sized for a phone (were min 340px) */
    .about-marquee__item { width: clamp(220px, 64vw, 300px); }
}

/* =========================================================
   v2.12.7 — SERVICES mobile revisions
   ========================================================= */
@media (max-width: 768px) {
    /* Image to the very TOP for context, and 16:9 (was 1200/390 = too long).
       v2.12.19 — top gap from the header −25% (56 → 42); image→headline gap a bit
       MORE (10 → 16). */
    /* v2.12.28 — gap header→image trimmed right down (21→8) so the image sits just under
       the header and the header bar reads as a clean, centred strip. */
    .svc-hero { display: flex; flex-direction: column; padding-top: 8px; }
    /* v2.12.57 — more air between the hero image and the headline below it. */
    .svc-hero__media {
        order: -1; aspect-ratio: 16 / 9; margin-bottom: 28px; border-radius: 0;
        width: 100vw; max-width: 100vw; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw);
    }

    /* Body text: ONE uniform style. v2.12.27 — both paragraphs EXACTLY the same (16px,
       same colour); !important guards any stale/specific size so the lede no longer
       reads bigger than the oneliner above it. */
    .svc-hero__oneliner,
    .svc-hero__lede { font-size: 16px !important; line-height: 1.5; color: var(--color-text); margin: 0 0 10px;
        /* v2.12.57 — keep the right edge clear, aligned to where the header "GET A QUOTE"
           ends (≈79px gap). 99 = 20px left inset + 79px right gap. */
        max-width: calc(100vw - 60px); }
    /* v2.12.20 — gap from the last paragraph (lede) to the buttons = the image→headline
       gap (16px). Inter-paragraph gap stays tight at 10px. */
    .svc-hero__lede { margin-bottom: 16px; }

    /* v2.12.27 — gap testimonials→CTA matched to the FAQ→testimonials rhythm (the CTA had
       margin-top:150 + padding-top:90 = a huge gap; testimonials uses margin-top:80).
       v2.12.111 — trimmed further (was 50+50=100) to the ~40px section rhythm. */
    .svc-cta { margin-top: 0 !important; padding-top: 40px !important; }

    /* v2.12.31 — user paste: ALL services body text uniform (16px / 1.5 / color-text /
       30px gap). Hero oneliner+lede already handled above (tuned margins kept). */
    .svc-why__para,
    .svc-offer__sub,
    .svc-offer__desc,
    .svc-how__lede {
        font-size: 16px;
        line-height: 1.5;
        color: var(--color-text);
        margin: 0 0 30px;
        /* v2.12.57 — right edge aligned to where "GET A QUOTE" ends (≈79px gap). */
        max-width: calc(100vw - 60px);
    }

    /* v2.12.123 — ALL body text widened by ~1 word: the GET-A-QUOTE-boundary reserve
       was 99px (clears the full GET A QUOTE) which wrapped the column too early →
       "mundur ke kiri". Now 60px (right reserve 79→40) so lines may cross the GET A
       QUOTE boundary by about one word, no further. Matches the portfolio fix that
       was already good. (103px ledes → 64px, same 40px right reserve.) */
    .article__body p,
    .article__body li {
        max-width: calc(100vw - 60px);
    }
    .work-detail__overview-body p {
        max-width: calc(100vw - 60px);
    }

    /* v2.12.19 — extra right margin for the hero text (was too close to the edge). */
    .svc-hero__top { padding-right: 16px; }

    /* v2.12.19 — the hero CTA buttons were data-reveal-hidden until scroll, so on entry
       they were invisible on phones. Force them visible immediately. */
    .svc-hero__actions[data-reveal] { opacity: 1; transform: none; }

    /* Hero buttons side-by-side, EQUAL size: Start a Project LEFT, See Works RIGHT.
       DOM order is [See Works, Start a Project]; row-reverse flips it visually. */
    .svc-hero__actions { flex-direction: row-reverse; flex-wrap: nowrap; gap: 12px; }
    .svc-hero__actions .btn { flex: 1 1 0; min-width: 0; padding: 0 12px; }

    /* Section + "What We Offer" titles AND the offer sub/body text left-aligned
       (.svc-offer__head was text-align:center, so the sub inherited centred). */
    .svc-section-title,
    .svc-offer__head,
    .svc-offer__title,
    .svc-offer__sub { text-align: left; }

    /* Trusted-by logos = same size as the homepage clients marquee (64×26). */
    .svc-hero__trusted .clients__logo { width: 64px; height: 26px; }

    /* v2.12.10 — Why-section body text + title left-aligned (like the other titles). */
    .svc-why__text, .svc-why__title, .svc-why__para { text-align: left; }
    /* v2.12.111 — services section-to-section gaps trimmed to a consistent ~40px on
       mobile (were Why 110, Offer 84, How 84). Each transition = ~40px:
         above Why     = svc-why padding-top 40
         Why → Offer   = svc-offer padding-top 40 (svc-why padding-bottom 0, margin 0)
         Offer → How   = svc-offer padding-bottom 40 + svc-how padding-top 0 */
    .svc-why { padding-top: 40px; }
    .svc-offer { margin-top: 0; padding-top: 40px; padding-bottom: 40px; }
    .svc-how { padding-top: 0; }
}

/* =========================================================
   v2.12.9 — BLOG (listing) mobile revisions
   ========================================================= */
@media (max-width: 768px) {
    /* L/R + top/bottom margins match the portfolio listing. */
    /* v2.12.67 — size + body matched. v2.12.68 — title top aligned to About's blue eyebrow (~124px). */
    .news { padding: 60px 20px 80px; }
    .news__head { margin-bottom: 36px; }
    .news__intro { font-size: 16px; color: rgba(35, 31, 32, 0.85); max-width: calc(100vw - 60px); }
    .news__featured { margin-bottom: 36px; gap: 28px; }
    .news__grid { gap: 28px; }
    /* Title: fix the ultra-tight line-height (0.905) that made the wrapped line
       overlap ("error"), and size it to fit phones. */
    .news__title { font-size: 48px; line-height: 1.08; }
    /* Featured (top 2) = same size as the cards below: 16:9 thumb + matching text
       (on phones the featured no longer need to stand out). */
    .news__featured-thumb { aspect-ratio: 16 / 9; margin-bottom: 14px; }
    .news__featured-title { font-size: 18px; line-height: 1.5; margin: 0 0 6px; }
    .news__featured-meta { font-size: 15px; }
}

/* =========================================================
   v2.12.9 — CONTACT / quote form mobile revisions
   ========================================================= */
/* Hide the floating FREE QUOTE button whenever the quote modal is open
   (it opens the very same form, so it shouldn't sit on top of it). */
body[data-quote-active] .floating-quote { display: none !important; }
@media (max-width: 768px) {
    /* Animation + budget pickers: tidy 2-column grid instead of a ragged wrap. */
    /* v2.12.79 — pills flow left→right hugging text with a fixed gap; .contact__pill-break
       forces 2 per row (right pill sits just after the left one, different x per row). */
    .contact__pills {
        display: flex;
        flex-wrap: wrap;
        /* v2.12.100 — row-gap handled by pill margin-bottom (below), NOT gap. The
           zero-height .contact__pill-break sits on its own flex line, so a row-gap
           would apply above AND below it = double gap on break-separated rows (the
           uneven-last-row bug). With row-gap 0 + pill margin-bottom, every row gap
           is exactly equal regardless of breaks. */
        gap: 0 20px;
        justify-content: flex-start;
        flex-direction: row;
        /* v2.12.102 — pills use margin-bottom for row spacing (12px, matching the
           desktop row-gap). It leaks below the LAST row, so absorb it here so the
           section gaps stay equal top & bottom. */
        margin-bottom: -12px;
    }
    .contact__pill {
        display: flex; align-items: center; justify-content: center;
        text-align: center; white-space: nowrap; padding: 11px 18px;
        /* v2.12.102 — row spacing lives here (12px = same as the desktop row-gap,
           per user), not in .contact__pills gap, so break-separated rows and
           break-less rows get the SAME gap. */
        margin-bottom: 12px;
        /* v2.12.95 — uniform 15px for ALL mobile pills (the 16px default looked
           inconsistent next to the shrunk "Not sure" pill). */
        font-size: 15px;
    }
    /* The long "Not Sure Yet…" option.
       v2.12.106 — HUG its text (no flex-basis:100% full-width) so the pill's right
       edge comes in right after the text instead of leaving a long empty gap
       ("panjang sebelah"). Text stays left-aligned with symmetric 12px padding both
       sides. At 15px the label (~315px) + 24px padding ≈ 339px fits the ~350px row,
       so it still sits on its own line on phones; white-space:normal (set elsewhere)
       lets it wrap rather than overflow on very narrow screens. */
    .contact__field[data-quote-type-field] .contact__pill:last-child {
        justify-content: flex-start; text-align: left; padding: 11px 12px;
    }
    /* v2.12.96 — pop-up pills also 15px on mobile (were 13px) so page + pop-up
       match; wrap-safety on its long "Not sure" pill so it never crops either. */
    .contact--modal .contact__pill { font-size: 15px; }
    .contact--modal .contact__field[data-quote-type-field] .contact__pill:last-child { white-space: normal; }
    /* v2.12.103 — pop-up gets the SAME uniform row spacing as the /contact/ page:
       row-gap handled by pill margin-bottom (12px), NOT .contact__pills gap, so the
       .contact__pill-break lines don't double the gap. The base
       `.contact--modal .contact__pills{gap:8px 20px}` (higher specificity) is
       overridden here. -12px on the container absorbs the last row's leak. */
    .contact--modal .contact__pills { gap: 0 20px; margin-bottom: -12px; }
    .contact--modal .contact__pill { margin-bottom: 12px; }
    /* v2.12.93 — MOBILE pill order per the user's mockup:
         row1: 2D | 3D
         row2: Motion Graphic | Interactive VR/AR
         row3: Immersive Experience (alone)
         row4: Not sure yet… (full-width)
       The DOM is in Figma-DESKTOP order (2D,3D,Immersive,Interactive,Motion,Not
       sure); the only difference on mobile is Immersive↔Motion are swapped. We do
       that with flex `order` (mobile-only) so desktop stays untouched. The two
       .contact__pill-break spans keep their 2-per-row wraps in the right places.
       nth-of-type counts labels (pills) and spans (breaks) separately. */
    .contact__field[data-quote-type-field] .contact__pill:nth-of-type(1) { order: 1; } /* 2D */
    .contact__field[data-quote-type-field] .contact__pill:nth-of-type(2) { order: 2; } /* 3D */
    .contact__field[data-quote-type-field] .contact__pill-break:nth-of-type(1) { order: 3; }
    .contact__field[data-quote-type-field] .contact__pill:nth-of-type(5) { order: 4; } /* Motion */
    .contact__field[data-quote-type-field] .contact__pill:nth-of-type(4) { order: 5; } /* Interactive */
    .contact__field[data-quote-type-field] .contact__pill-break:nth-of-type(2) { order: 6; }
    .contact__field[data-quote-type-field] .contact__pill:nth-of-type(3) { order: 7; } /* Immersive */
    .contact__field[data-quote-type-field] .contact__pill:nth-of-type(6) { order: 8; } /* Not sure */
    /* "Share a link" hint was clipped — smaller so the full placeholder fits. */
    .contact__share-row input { font-size: 13px; }
}

/* =========================================================
   v2.12.11 — PORTFOLIO SINGLE (work-detail) mobile gap tightening
   ========================================================= */
@media (max-width: 768px) {
    /* Hero top gap −50% (100 → 50). */
    /* v2.12.35 — side margins = home (40px → 20px; was the "thick margin"). */
    .work-detail { padding-top: 60px; padding-left: 20px; padding-right: 20px; }
    /* v2.12.35 — ALL videos full-bleed edge-to-edge (hero + result videos). */
    .work-detail__hero,
    .work-detail__videos {
        width: 100vw; max-width: 100vw;
        margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw);
        border-radius: 0;
    }
    /* result videos stack 1-per-row when full-bleed so each is full width. */
    .work-detail__videos { grid-template-columns: 1fr; gap: 0; }
    /* Video → "The Overview" headline gap −50% (100 → 50). */
    .work-detail__hero { margin-bottom: 50px; }
    /* v2.12.43 — porto body text = services body text (16px). */
    .work-detail__overview-body p {
        font-size: 16px;
        line-height: 1.5;
        color: var(--color-text);
        margin: 0 0 20px;
    }
    /* v2.12.58 — list spacing after bullets = paragraph spacing (was larger/uneven). */
    .work-detail__overview-body ul,
    .work-detail__overview-body ol { margin: 0 0 20px; }
    /* v2.12.60 — bullet text = 16px like the paragraphs (was inheriting 14px). */
    .work-detail__overview-body li { margin-bottom: 4px; line-height: 1.5; font-size: 16px; }
    /* v2.12.44 — galleries 1 COLUMN on phones (too small in multi-col), EXCEPT storyboard
       (kept multi-col so the frame sequence reads). */
    .work-detail__balgrid,
    .work-detail__phones { grid-template-columns: 1fr !important; }
    .work-detail__section--storyboard .work-detail__balgrid { grid-template-columns: repeat(2, 1fr) !important; }
    /* v2.12.46 — the hero gallery had margin-bottom:80 (every other gallery→heading gap is
       50), so the gap above the next heading read bigger. Match it to 50. */
    .work-detail__phones { margin-bottom: 50px; }
    /* "The Overview" heading → body text: tighter + consistent with other section
       headings (the stacked grid gap was 28 = the odd "jaraknya beda").
       v2.12.44 — margin-bottom 40→50 so the overview→next-heading gap matches the
       hero→overview (and the section→section) gap.
       v2.12.85 — heading→content gap unified to 18px so "The Overview"→body matches
       every "Storyboard/Styleframes"→image gap (was 14 vs 18 = the uneven jarak). */
    .work-detail__overview { gap: 18px; margin-bottom: 50px; }
    .work-detail__section-h { margin-bottom: 18px; }
    .work-detail__section { margin-bottom: 50px; }
}

/* v2.12.81 — blog body rhythm at ≤480 (phone), per supplied scale. Smaller
   type + tighter heading gaps than the ≤768 tablet block above. */
@media (max-width: 480px) {
    .article__body { font-size: 16px; line-height: 1.6; }
    .article__body p { font-size: 16px; line-height: 1.6; margin: 0 0 16px; }
    .article__body h1 { font-size: 26px; line-height: 1.3; margin: 36px 0 16px; }
    .article__body h2 { font-size: 22px; margin: 32px 0 14px !important; }
    .article__body h3 { font-size: 19px; margin: 28px 0 12px !important; }
    .article__body h4 { font-size: 17px; margin: 22px 0 10px; }
    .article__body ul,
    .article__body ol { margin-bottom: 16px; }
}

/* =========================================================
   v2.12.142 — TABLET AI ".ai-approach" photo CTA (director portraits +
   "AI-Enhanced Production" copy) = photos LEFT + headline/body RIGHT, like
   desktop & the homepage/About .cta pattern. It stacks to 1-col at ≤1000
   (v240.css ~L3889), so iPad PORTRAIT (769–834) showed photos on top. Scope
   769–1000 only: 1001–1240 (landscape) already renders the base 2-col that
   the user approved at 1174; phones ≤768 keep the mobile stack; desktop
   untouched. Photos capped so the copy column keeps enough room. Placed LAST
   so it beats the ≤1000 stack. (feedback: "CTA yang ada fotonya di kiri,
   headline & sub di kanan — about + ai juga. TABLET".) */
@media (min-width: 769px) and (max-width: 1000px) {
    .ai-approach__inner {
        grid-template-columns: clamp(220px, 34vw, 380px) minmax(0, 1fr);
        gap: clamp(28px, 4vw, 60px);
        align-items: center;
    }
}
