/* ================================================================
   Service Detail — Industrial Precision (1:1 port of the
   "service-details final" Pencil frame). Uses the live --ip-*
   tokens + fonts from shell.css (Bricolage Grotesque / Inter /
   IBM Plex Mono / Space Grotesk) — same family as the services
   index page. Replaces the old DM Sans + coral "Circuit Noir".
================================================================ */

/* ----------------------------------------------------------------
   Local tokens (page-scoped; --ip-* come from shell.css)
---------------------------------------------------------------- */
.services-redesign.service-detail {
    /* surfaces */
    --sd-paper: var(--ip-paper);          /* unified pure white via shell token */
    --sd-white: #FFFFFF;
    --sd-band: #FFFFFF;

    /* ink + lines */
    --sd-ink: #20160F;
    --sd-ink-2: #14171C;
    --sd-muted: #6E665D;
    --sd-muted-2: #6B7280;
    --sd-line: #E2DED6;
    --sd-line-2: #E4DFD5;
    --sd-line-strong: #CBC6BB;

    /* accents */
    --sd-orange: #FF5A1F;
    --sd-orange-2: #E8521E;
    --sd-coral: #E85C45;          /* hero button / infra feature */
    --sd-coral-press: #C2502A;    /* CTA primary / nav cta */
    --sd-tint: #FBE9DF;           /* badge tint behind why-icons */
    --sd-amber: #F4A24E;          /* process ribbon + rings */

    /* maroon family (shared with shell footer) */
    --sd-cream: #F5ECDD;

    /* radii (iOS-soft) */
    --sd-r-sm: 8px;
    --sd-r-md: 14px;
    --sd-r-lg: 16px;
    --sd-r-img: 32px;
    --sd-r-pill: 999px;

    /* shadows (soft, multi-layer — not shadow-on-everything) */
    --sd-shadow-card: 0 2px 6px rgba(42, 20, 15, 0.05), 0 10px 24px -8px rgba(42, 20, 15, 0.12);
    --sd-shadow-node: 0 8px 18px -6px rgba(42, 20, 15, 0.10);

    --sd-ease: cubic-bezier(0.2, 0, 0, 1);

    --container-max: 1328px;
    --container-pad: 56px;

    background: var(--sd-white);
    color: var(--sd-ink);
    font-family: var(--ip-font-body);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    line-height: 1.6;
    overflow-x: hidden;
}

.body-inner:has(.services-redesign.service-detail) { background: var(--sd-white); }

/* Neutralize the legacy global `section { padding: 80px 0 }` (in style.css) —
   every <section> here manages its own vertical rhythm via its `-inner` wrapper,
   so the bare-element padding only injected unwanted gaps (e.g. above the hero
   image and between sections). */
.service-detail section { padding: 0; }

.service-detail img { display: block; }

/* shared image outline — pure black, low opacity */
.service-detail .overview-main img,
.service-detail .overview-thumb img {
    outline: 1px solid rgba(0, 0, 0, 0.08);
    outline-offset: -1px;
}

/* ---------- Primary button (hero) ---------- */
.service-detail .service-btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 15px 26px;
    background: var(--sd-coral);
    color: #FFFFFF;
    font-family: var(--ip-font-body);
    font-size: 15px;
    font-weight: 600;
    text-decoration: none;
    border-radius: var(--sd-r-md);
    transition: background-color 0.2s var(--sd-ease), transform 0.1s var(--sd-ease);
}
.service-detail .service-btn-primary:hover { background: var(--sd-coral-press); }
.service-detail .service-btn-primary:active { transform: scale(0.97); }
.service-detail .service-btn-primary i { font-size: 0.85em; transition: transform 0.2s var(--sd-ease); }
.service-detail .service-btn-primary:hover i { transform: translateX(3px); }

/* ================================================================
   SERVICE-DETAIL HERO — MAGAZINE layout.
   Breadcrumb pinned top; a big faded GHOST title TOP-LEFT (max 2 lines, in flow);
   the render FLOATS RIGHT (vertically centered) and the OVERVIEW flows below the
   title as a left column whose right edge wraps the render silhouette
   (shape-outside). Clamp + "Read more" keep the slide exactly one screen on load.
   The slide box keeps round-1's one-screen sizing (reuses --ip-header-h live-measure).
================================================================ */
.service-detail .sd-hero-slide {
    position: relative;
    /* override services-index.css's `.ip-slide { display:flex }` — the magazine hero is
       normal block flow (breadcrumb block, then the stage with a float inside), not a
       flex row (which would lay breadcrumb + stage side-by-side and squash the overview). */
    display: block;
    background: var(--sd-white);
    min-height: calc(100dvh - var(--ip-header-h, 72px));
    padding: 0;                               /* reset the global section{padding:80px 0} */
    scroll-margin-top: var(--ip-header-h, 72px);
    overflow: hidden;                         /* one screen on load */
}
/* When the overview is expanded ("Read more"), release the band so nothing clips. */
.service-detail .sd-hero-slide.is-expanded {
    min-height: auto;
    overflow: visible;
}

/* Real H1 kept for SEO/a11y but visually hidden (the ghost is the visible title). */
.service-detail .sd-hero-slide__sr-title {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0; border: 0;
    overflow: hidden; clip: rect(0 0 0 0);
    white-space: nowrap;
}

/* Breadcrumb near the top of the slide. */
.service-detail .sd-hero-slide__crumb {
    position: relative;
    z-index: 2;
    max-width: var(--container-max);
    width: 100%;
    margin: 0 auto;
    padding: 28px var(--container-pad) 0;
    font-family: var(--ip-font-mono);
    font-size: 12px;
    letter-spacing: 0.6px;
    text-transform: uppercase;
}
.service-detail .sd-hero-slide__crumb-link {
    color: var(--sd-muted);
    text-decoration: none;
    transition: color 0.2s var(--sd-ease);
}
.service-detail .sd-hero-slide__crumb-link:hover { color: var(--sd-orange); }
.service-detail .sd-hero-slide__crumb-sep { margin: 0 8px; color: var(--sd-line-strong); }
.service-detail .sd-hero-slide__crumb-current { color: var(--sd-ink); }

/* Stage: fills the hero below the breadcrumb and VERTICALLY CENTERS the inner magazine
   block, so the composition reads centered on both 1- and 2-line titles (no per-page
   margin tuning). Flex is on the stage (centering one child); the inner stays block flow. */
.service-detail .sd-hero-slide__stage {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    /* fill the leftover height under the sticky header + breadcrumb so centering has room */
    min-height: calc(100dvh - var(--ip-header-h, 72px) - 90px);
    max-width: var(--container-max);
    width: 100%;
    margin: 0 auto;
    padding: 16px var(--container-pad) 32px;
}
/* Inner: NORMAL block flow so the overview wraps the floated render (shape-outside). */
.service-detail .sd-hero-slide__inner { position: relative; width: 100%; }
.service-detail .sd-hero-slide__inner::after { content: ""; display: block; clear: both; }

/* Big faded GHOST title, TOP-LEFT, in flow. Max 2 lines (clip a 3rd). Fixed display size
   (consistent across services); short names = 1 line, longer = 2. */
.service-detail .sd-hero-slide__ghost {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;                    /* max 2 lines; clip beyond */
    overflow: hidden;
    margin: 0 0 18px;
    font-family: var(--ip-font-display);
    font-weight: 800;
    font-size: clamp(54px, 8.5vw, 132px);
    line-height: 0.92;
    letter-spacing: -2px;
    text-transform: uppercase;
    color: rgba(20, 23, 28, 0.20);
    pointer-events: none;
    overflow-wrap: break-word;
}

/* Floated render: text wraps its silhouette. Pulled UP so it reads vertically centered
   beside the overview. shape-outside reads the transparent cutout's alpha. */
.service-detail .sd-hero-slide__render {
    float: right;
    /* Sized larger so it balances the big ghost title (the title shouldn't dwarf the
       product). */
    width: clamp(340px, 50vw, 720px);
    height: auto;
    /* Lift the render up into the space beside the (1–2 line) title so it reads
       vertically centered. Capped in height so a tall render can't overflow one screen
       (cap only bites on short viewports; full-size on normal screens). */
    max-height: calc(100dvh - var(--ip-header-h, 72px) - 80px);
    object-fit: contain;
    margin: -170px -1.5% 12px 48px;
    shape-outside: var(--sd-shape);
    shape-image-threshold: 0.5;
    shape-margin: 24px;
    filter: drop-shadow(0 44px 64px rgba(20, 16, 9, 0.22));
}
.service-detail .sd-hero-slide__render.is-placeholder {
    shape-outside: none;
    opacity: 0.6;
    filter: none;
}

/* OVERVIEW body — flows around the floated render (straight left edge, wrapped right edge).
   CLAMP via max-height + overflow (NOT -webkit-line-clamp: that forces display:-webkit-box
   which ignores floats and would KILL the shape-outside wrap). A soft fade hints at more. */
.service-detail .sd-hero-slide__overview {
    position: relative;
    max-height: 9.6em;                        /* ~6 lines at 1.6 line-height; tune to fit */
    overflow: hidden;
    font-size: 16px;
    line-height: 1.6;
    color: var(--sd-muted);
}
.service-detail .sd-hero-slide__overview::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 2.4em;
    background: linear-gradient(to bottom, rgba(255,255,255,0), var(--sd-white));
    pointer-events: none;
}
.service-detail .sd-hero-slide__overview.is-expanded {
    max-height: none;
    overflow: visible;
}
.service-detail .sd-hero-slide__overview.is-expanded::after { content: none; }
.service-detail .sd-hero-slide__overview p { margin: 0 0 0.7em; text-wrap: pretty; }
.service-detail .sd-hero-slide__overview p:last-child { margin-bottom: 0; }
.service-detail .sd-hero-slide__overview strong { color: var(--sd-ink); font-weight: 600; }

/* "Read more" / "Show less" — quiet inline mono button; clears the float so it sits below. */
.service-detail .overview-readmore {
    clear: both;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-top: 14px;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    font-family: var(--ip-font-mono);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    color: var(--sd-orange-2);
    transition: color 0.2s var(--sd-ease);
}
.service-detail .overview-readmore:hover { color: var(--sd-orange); }
.service-detail .overview-readmore .overview-readmore-icon {
    font-size: 10px;
    transition: transform 0.2s var(--sd-ease);
}
.service-detail .sd-hero-slide__overview.is-expanded ~ .overview-readmore .overview-readmore-icon {
    transform: rotate(180deg);
}

/* ================================================================
   WHY TEAMS CHOOSE — staggered editorial text blocks (zig-zag L/R)
   Reference: Vertex "M100" long-read. Each feature is a ~40%-wide
   text block; odd blocks hug the left column, even blocks the right,
   each flowing below the previous so they descend diagonally.
   No icons, no rules, no boxes — pure typography.
================================================================ */
.service-detail .service-why { background: var(--sd-paper); }
.service-detail .service-why-eyebrow {
    display: block;
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 120px var(--container-pad) 0;
    font-family: var(--ip-font-mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    color: var(--sd-orange-2);
}
.service-detail .service-why-eyebrow + .service-why-inner { padding-top: 40px; }
.service-detail .service-why-inner {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 120px var(--container-pad) 140px;
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 96px;
    /* Each block sits on its OWN row, alternating column, so they descend in a
       diagonal staircase (one active block per vertical band) — matching the
       reference where each block begins below the previous one's bottom. The
       row-gap is the vertical breathing space between consecutive blocks. */
    grid-auto-flow: row;
    row-gap: 64px;
    align-items: start;
}
.service-detail .why-block {
    max-width: 460px;
    grid-row: var(--why-row);
}
.service-detail .why-block--left  { grid-column: 1; }
.service-detail .why-block--right { grid-column: 2; }

.service-detail .why-block__title {
    font-family: var(--ip-font-display); /* Bricolage Grotesque — same as the hero ghost title */
    font-style: italic;                   /* the reference heading is a bold oblique */
    font-size: 30px;
    font-weight: 800;
    line-height: 1.12;
    letter-spacing: -0.5px;
    text-transform: uppercase;
    color: var(--sd-ink);
    margin: 0 0 22px;
    text-wrap: balance;
}
.service-detail .why-block__body {
    font-family: var(--ip-font-body);
    font-size: 14px;
    line-height: 1.75;
    color: var(--sd-ink-2);
    margin: 0;
    text-wrap: pretty;
}

/* ================================================================
   PROCESS TIMELINE — wavy ribbon + ringed nodes
================================================================ */
.service-detail .service-process { background: var(--sd-paper); }
.service-detail .service-process-inner {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 24px var(--container-pad) 96px;
}
/* The timeline is a vertical stack of "rows". Each row holds an SVG ribbon
   that zig-zags through that row's nodes, plus the nodes themselves. The ribbon
   and the node centers are derived from the same geometry (see the
   `process_ribbon` template tag), so the wave always threads the circles. */
.service-detail .process-track {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 56px;
}

/* --- one row ---
   Vertical model (per step), top → bottom:
     [ --label-space ][ --band (the ribbon's 200u viewBox) ][ --label-space ]
   High nodes sit at band-y 50 and label in the TOP space; low nodes sit at
   band-y 150 and label in the BOTTOM space. The band offset (--label-space)
   is identical for every step, so the ribbon stays straight across the row. */
.service-detail .process-row {
    position: relative;
    --band: 200px;
    /* label zone above/below the band — must clear the tallest label (number +
       title + up to ~3 desc lines ≈ 155px) plus the circle-to-label gap, or the
       high-row numbers clip out the top of the section. */
    --label-space: 178px;
    --badge: 132px;
    --ring: 15px;
    --gap: 16px;   /* circle-to-label gap */
}
/* the ribbon SVG covers exactly the band, offset below the top label zone */
.service-detail .process-ribbon {
    position: absolute;
    left: 0;
    right: 0;
    top: var(--label-space);
    width: 100%;
    height: var(--band);
    color: var(--sd-amber);   /* stroke uses currentColor */
    pointer-events: none;
    z-index: 0;
    overflow: visible;
}

/* --- the node row --- */
.service-detail .process-nodes {
    list-style: none;
    margin: 0;
    padding: 0;
    position: relative;
    z-index: 1;
    display: flex;
}
.service-detail .process-step {
    position: relative;
    flex: 1 1 0;
    min-width: 0;
    /* top label zone + band + bottom label zone */
    min-height: calc(var(--label-space) + var(--band) + var(--label-space));
    display: flex;
    justify-content: center;
}
/* node circle — centered on the high (band-y 50) or low (band-y 150) line. */
.service-detail .process-badge {
    position: absolute;
    left: 50%;
    width: var(--badge);
    height: var(--badge);
    margin-left: calc(var(--badge) / -2);
    border-radius: 50%;
    background: #FFFFFF;
    border: var(--ring) solid var(--sd-amber);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--sd-ink);
    box-shadow: var(--sd-shadow-node);
    z-index: 1;
}
.service-detail .process-step.is-low .process-badge {
    top: calc(var(--label-space) + 150px - var(--badge) / 2);
}
.service-detail .process-step.is-high .process-badge {
    top: calc(var(--label-space) + 50px - var(--badge) / 2);
}
.service-detail .process-badge svg { width: 52px; height: 52px; }
.service-detail .process-badge i { font-size: 44px; color: var(--sd-ink); }

/* label sits opposite the circle: high circle -> label above; low -> below */
.service-detail .process-label {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    width: 196px;
    max-width: 92%;
    display: flex;
    flex-direction: column;
    gap: 7px;
    text-align: center;
}
.service-detail .process-step.is-low .process-label {
    /* just below the low circle (low center = label-space + 150) */
    top: calc(var(--label-space) + 150px + var(--badge) / 2 + var(--gap));
}
.service-detail .process-step.is-high .process-label {
    /* just above the high circle (high circle top = label-space + 50 - badge/2) */
    top: auto;
    bottom: calc(var(--band) + var(--label-space) - 50px + var(--badge) / 2 + var(--gap));
}
.service-detail .process-num {
    font-family: var(--ip-font-card);
    font-size: 30px;
    font-weight: 700;
    line-height: 1;
    color: var(--sd-ink);
    font-variant-numeric: tabular-nums;
}
.service-detail .process-title {
    font-family: var(--ip-font-card);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.6px;
    line-height: 1.2;
    text-transform: uppercase;
    color: var(--sd-ink);
}
.service-detail .process-desc {
    font-size: 12px;
    line-height: 1.45;
    color: var(--sd-muted);
    text-wrap: pretty;
}

/* ================================================================
   WHAT WE BUILD — one continuous, image-led editorial index.
   Every Wagtail entry is a borderless row: ghost number → project
   image → title and description. No card containers or rounded UI.
================================================================ */
.service-detail .service-build {
    background: var(--sd-white);
    scroll-margin-top: var(--ip-header-h, 72px);
}
.service-detail .service-build-inner {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 96px var(--container-pad) 112px;
}
.service-detail .service-build--before-tech .service-build-inner {
    padding-bottom: 56px;
}
.service-detail .service-build-head {
    max-width: 760px;
    margin-bottom: 56px;
}
.service-detail .service-build-eyebrow {
    display: block;
    margin-bottom: 14px;
    font-family: var(--ip-font-mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    color: var(--sd-orange-2);
}
.service-detail .service-build-heading {
    max-width: 720px;
    margin: 0;
    font-family: var(--ip-font-display);
    font-size: clamp(36px, 3.5vw, 48px);
    font-weight: 700;
    line-height: 1.08;
    letter-spacing: -0.7px;
    color: var(--sd-ink);
    text-wrap: balance;
}
.service-detail .service-build-intro {
    max-width: 680px;
    margin: 22px 0 0;
    font-size: 14px;
    line-height: 1.75;
    color: var(--sd-muted);
    text-wrap: pretty;
}
.service-detail .service-build-list {
    margin: 0;
    padding: 0;
    list-style: none;
}
.service-detail .service-build-item {
    display: grid;
    grid-template-columns: 88px minmax(360px, 540px) minmax(270px, 1fr);
    gap: 32px;
    align-items: center;
    min-height: 0;
    padding: 36px 0;
    border-top: 1px solid var(--sd-line);
}
.service-detail .service-build-number {
    align-self: start;
    margin-top: -8px;
    font-family: var(--ip-font-display);
    font-size: clamp(68px, 6.5vw, 96px);
    font-weight: 800;
    line-height: 0.85;
    letter-spacing: -4px;
    color: rgba(32, 22, 15, 0.13);
    font-variant-numeric: tabular-nums;
}
.service-detail .service-build-media {
    position: relative;
    width: 100%;
    /* 16/9 = the laptop-screen shape the project screenshots are captured at
       (1366x768). The box matches the image shape so `contain` fills it with
       NO crop and NO letterbox — the old gray "card" (backdrop + rounded
       corners) is gone. Kept as a fixed ratio so every row stays equal height. */
    aspect-ratio: 16 / 9;
    margin: 0;
    overflow: hidden;
}
.service-detail .service-build-media img {
    width: 100%;
    height: 100%;
    /* contain so the WHOLE laptop screenshot shows, never cropped. With the
       16/9 frame matching the capture ratio there's no visible letterbox; a
       differently-proportioned image just shows white page (no card) in the gap. */
    object-fit: contain;
}
/* Mobile-project images are portrait (~2/3). `contain` keeps the whole screen
   visible, never cropped. The rounded "phone screen" card was removed 2026-07-29
   (per user, matching the web rows) — the image sits clean on white with no
   backdrop or radius. Frame ratio: see the media rule below. */
.service-detail .service-build--mobile .service-build-item {
    grid-template-columns: 88px minmax(220px, 260px) minmax(270px, 1fr);
    column-gap: clamp(32px, 4vw, 64px);
    padding-top: 48px;
    padding-bottom: 48px;
}
.service-detail .service-build--mobile .service-build-media {
    width: min(100%, 250px);
    /* 2/3 = the ratio the current mobile app images actually are (portrait, but
       not the extreme 9/19.5 full-bleed-screenshot shape). Matching the frame to
       the images lets `contain` fill it with minimal gap — 9/19.5 left 150–230px
       of empty white above/below each. Optimal single frame for the 6-image set
       (~11% avg gap vs 29% at 9/19.5). Was 9/19.5 (2026-07-29). */
    aspect-ratio: 2 / 3;
    justify-self: center;
}
.service-detail .service-build-placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(32, 22, 15, 0.10);
    background:
        linear-gradient(135deg, rgba(255, 90, 31, 0.08), transparent 46%),
        #F3F0EA;
}
.service-detail .service-build-placeholder span {
    font-family: var(--ip-font-display);
    font-size: clamp(92px, 12vw, 180px);
    font-weight: 800;
    line-height: 1;
    letter-spacing: -8px;
}
.service-detail .service-build-placeholder small {
    position: absolute;
    left: 20px;
    bottom: 16px;
    font-family: var(--ip-font-mono);
    font-size: 10px;
    letter-spacing: 1.4px;
    color: var(--sd-muted);
}
.service-detail .service-build-copy {
    max-width: 370px;
}
.service-detail .service-build-title {
    margin: 0 0 20px;
    font-family: var(--ip-font-display);
    font-size: 30px;
    font-style: italic;
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: -0.5px;
    text-transform: uppercase;
    color: var(--sd-ink);
    text-wrap: balance;
}
.service-detail .service-build-description {
    margin: 0;
    font-size: 14px;
    line-height: 1.75;
    color: var(--sd-ink-2);
    text-wrap: pretty;
}

/* ================================================================
   ENTERPRISE TECHNOLOGY STACK — compact floating brand-tile wall.
   Hardcoded for Web Application Development and intentionally copy-free.
================================================================ */
.service-detail .service-tech-cloud {
    padding: 96px 0 104px;
    background: var(--sd-white);
}
.service-detail .service-tech-cloud__inner {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 0 var(--container-pad);
}
.service-detail .service-tech-cloud__head {
    margin-bottom: 20px;
    text-align: center;
}
.service-detail .tech-cloud-eyebrow {
    display: block;
    font-family: var(--ip-font-mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    color: var(--sd-orange-2);
    margin-bottom: 12px;
}
.service-detail .tech-cloud-heading {
    font-family: var(--ip-font-display);
    font-size: 34px;
    font-weight: 700;
    letter-spacing: -0.5px;
    line-height: 1.15;
    color: var(--sd-ink);
    margin: 0;
    text-wrap: balance;
}
.service-detail .tech-cloud-list {
    display: grid;
    grid-template-rows: repeat(2, 88px);
    grid-auto-flow: column;
    grid-auto-columns: minmax(78px, 1fr);
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 0;
    margin: 0;
    padding: 24px 0;
    list-style: none;
}
.service-detail .tech-cloud-item {
    position: relative;
    display: flex;
    justify-content: center;
    transform: translateY(-18px);
    outline: none;
}
.service-detail .tech-cloud-item:nth-child(4n + 3),
.service-detail .tech-cloud-item:nth-child(4n + 4) {
    transform: translateY(18px);
}
.service-detail .tech-cloud-mark {
    display: grid;
    place-items: center;
    width: 76px;
    height: 76px;
    border: 1px solid rgba(31, 36, 48, 0.08);
    border-radius: 13px;
    background: #ffffff;
    box-shadow:
        0 12px 26px rgba(28, 34, 48, 0.12),
        0 3px 8px rgba(28, 34, 48, 0.08);
    font-size: 38px;
    line-height: 1;
    color: var(--tech-color, rgba(32, 22, 15, 0.46));
    opacity: 1;
    transition:
        transform 0.25s var(--sd-ease),
        box-shadow 0.25s var(--sd-ease);
}
.service-detail .tech-cloud-mark svg {
    width: 1em;
    height: 1em;
    fill: currentColor;
}
.service-detail .tech-cloud-wordmark {
    font-family: var(--ip-font-display);
    font-size: 15px;
    font-weight: 800;
    letter-spacing: -0.4px;
}
.service-detail .tech-cloud-item:hover .tech-cloud-mark,
.service-detail .tech-cloud-item:focus-visible .tech-cloud-mark {
    transform: translateY(-5px) scale(1.07);
    box-shadow:
        0 18px 34px rgba(28, 34, 48, 0.14),
        0 4px 10px rgba(28, 34, 48, 0.08);
}
/* ================================================================
   SELECTED WORK — auto-scrolling gallery (right → left marquee).
   Pauses on hover; the hovered image pops up + reveals its caption.
   Reference: dark portrait-strip gallery, recoloured to our white bg.
================================================================ */
.service-detail .service-gallery {
    background: var(--sd-white);
    padding: 96px 0 110px;
    overflow: hidden;                 /* clip the off-screen marquee tail */
}
.service-detail .service-tech-cloud + .service-gallery {
    padding-top: 40px;
}
.service-detail .service-gallery-head {
    max-width: var(--container-max);
    margin: 0 auto 44px;
    padding: 0 var(--container-pad);
    text-align: center;
}
.service-detail .gallery-eyebrow {
    display: block;
    font-family: var(--ip-font-mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    color: var(--sd-orange-2);
    margin-bottom: 14px;
}
.service-detail .gallery-heading {
    font-family: var(--ip-font-display);
    font-size: 42px;
    font-weight: 700;
    letter-spacing: -0.5px;
    line-height: 1.15;
    color: var(--sd-ink);
    margin: 0;
    text-wrap: balance;
}

/* Marquee viewport: extra vertical room so a popped image isn't clipped */
.service-detail .gallery-marquee {
    position: relative;
    width: 100%;
    padding: 40px 0;
}
.service-detail .gallery-track {
    display: flex;
    align-items: center;
    gap: 18px;
    width: max-content;
    margin: 0;
    padding: 0 18px;
    list-style: none;
    animation: gallery-scroll 48s linear infinite;
}
/* Pause the conveyor while the pointer is anywhere over the strip */
.service-detail .gallery-marquee:hover .gallery-track { animation-play-state: paused; }

@keyframes gallery-scroll {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }   /* track is duplicated → seamless loop */
}

.service-detail .gallery-item { flex: 0 0 auto; margin: 0; }
.service-detail .gallery-figure {
    position: relative;
    margin: 0;
    width: 220px;
    height: 310px;
    overflow: visible;                /* allow caption to sit outside the frame */
    transition: transform 0.4s var(--sd-ease);
    transform-origin: center center;
}
.service-detail .gallery-figure img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 0;                 /* sharp corners — no curve */
    display: block;
    filter: grayscale(0.15);
    transition: filter 0.4s var(--sd-ease), box-shadow 0.4s var(--sd-ease);
}
/* Hovered image pops up larger + sharpens + lifts */
.service-detail .gallery-figure:hover {
    transform: scale(1.18);
    z-index: 2;
}
.service-detail .gallery-figure:hover img {
    filter: grayscale(0);
    box-shadow: 0 24px 60px -18px rgba(20, 16, 12, 0.45);
}
/* Caption — hidden until its image is hovered, then fades in below */
.service-detail .gallery-caption {
    position: absolute;
    left: 50%;
    bottom: -30px;
    transform: translateX(-50%);
    white-space: nowrap;
    font-family: var(--ip-font-mono);
    font-size: 10.5px;
    font-weight: 500;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--sd-muted);
    opacity: 0;
    transition: opacity 0.3s var(--sd-ease) 0.05s;
    pointer-events: none;
}
.service-detail .gallery-figure:hover .gallery-caption { opacity: 1; }

/* ================================================================
   CTA SECTION — white, centered, two pills
================================================================ */
.service-detail .services-cta-band,
.services-cta-band {
    background: var(--ip-card, #FFFFFF);
    color: var(--ip-ink-2, #14171C);
}
.service-detail .services-cta-band .cta-band-inner,
.services-cta-band .cta-band-inner {
    max-width: 880px;
    margin: 0 auto;
    padding: 88px var(--container-pad);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    text-align: center;
}
.service-detail .service-tech-cloud + .services-cta-band .cta-band-inner {
    padding-top: 40px;
}
.services-cta-band .cta-band-eyebrow {
    font-family: var(--ip-font-mono);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 1.4px;
    text-transform: uppercase;
    color: var(--ip-accent-2, #E8521E);
}
.services-cta-band .cta-band-heading {
    font-family: var(--ip-font-card);
    font-size: 42px;
    font-weight: 600;
    letter-spacing: -0.5px;
    line-height: 1.1;
    color: var(--ip-ink-2, #14171C);
    margin: 0;
    text-wrap: balance;
}
.services-cta-band .cta-band-text {
    font-family: var(--ip-font-body);
    font-size: 17px;
    line-height: 1.55;
    color: var(--ip-muted, #6B7280);
    margin: 0;
    max-width: 540px;
    text-wrap: pretty;
}
.services-cta-band .cta-band-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 14px;
    margin-top: 12px;
}
.services-cta-band .cta-band-btn {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 16px 26px;
    border-radius: var(--ip-r-pill, 999px);
    font-family: var(--ip-font-card);
    font-size: 16px;
    font-weight: 600;
    text-decoration: none;
    transition: background-color 0.2s var(--sd-ease), transform 0.1s var(--sd-ease), box-shadow 0.2s var(--sd-ease);
}
.services-cta-band .cta-band-btn:active { transform: scale(0.97); }
.services-cta-band .cta-band-btn--primary {
    background: var(--sd-coral-press, #C2502A);
    color: #FFFFFF;
}
.services-cta-band .cta-band-btn--primary:hover {
    background: #A8431F;
    box-shadow: 0 10px 24px -8px rgba(194, 80, 42, 0.5);
}
.services-cta-band .cta-band-btn--primary i { font-size: 0.85em; transition: transform 0.2s var(--sd-ease); }
.services-cta-band .cta-band-btn--primary:hover i { transform: translateX(3px); }
.services-cta-band .cta-band-btn--secondary {
    background: #FFFFFF;
    color: var(--ip-ink-2, #14171C);
    border: 1px solid var(--ip-line, #E2DED6);
}
.services-cta-band .cta-band-btn--secondary:hover { border-color: var(--sd-line-strong, #CBC6BB); }

/* ================================================================
   RESPONSIVE
================================================================ */
@media (max-width: 1280px) {
    .service-detail { --container-pad: 32px; }
    .service-detail .process-row { --badge: 112px; --ring: 13px; }
    .service-detail .process-badge svg { width: 44px; height: 44px; }
    .service-detail .process-badge i { font-size: 38px; }
}

@media (max-width: 1100px) {
    /* fewer per row keeps circles from crowding before the mobile stack */
    .service-detail .process-row { --badge: 96px; --ring: 11px; }
    .service-detail .process-badge svg { width: 38px; height: 38px; }
    .service-detail .process-badge i { font-size: 32px; }
    .service-detail .process-title { font-size: 12px; }
    .service-detail .service-build-item {
        grid-template-columns: 76px minmax(320px, 460px) minmax(230px, 1fr);
        gap: 24px;
    }
    .service-detail .service-build--mobile .service-build-item {
        grid-template-columns: 76px minmax(210px, 250px) minmax(230px, 1fr);
    }
}

@media (max-width: 1024px) {
    /* Hero stacks: title, then render (centered, no float/wrap), then overview full-width.
       One-screen lock already released; ghost stays (it's the title now), becomes
       unclamped so every service name is visible, and scales down for narrow screens. */
    .service-detail .sd-hero-slide { min-height: auto; overflow: visible; }
    .service-detail .sd-hero-slide__stage { padding: 20px var(--container-pad) 48px; }
    .service-detail .sd-hero-slide__ghost {
        display: block;
        -webkit-line-clamp: unset;
        overflow: visible;
        font-size: clamp(38px, 8vw, 72px);
        line-height: 0.96;
        letter-spacing: -1.2px;
        margin-bottom: 18px;
        overflow-wrap: normal;
        word-break: normal;
    }
    .service-detail .sd-hero-slide__render {
        float: none;
        display: block;
        width: min(78%, 420px);
        margin: 8px auto 24px;
        shape-outside: none;
    }
    .service-detail .sd-hero-slide__overview { font-size: 15px; }
}

@media (max-width: 900px) {
    /* Why blocks: the two-column zig-zag needs width — collapse to a single
       left-aligned column so the headings + body stay readable. */
    .service-detail .service-why-inner {
        grid-template-columns: 1fr;
        row-gap: 56px;
    }
    .service-detail .why-block--left,
    .service-detail .why-block--right { grid-column: 1; }
    .service-detail .why-block { max-width: 560px; }

    .service-detail .service-build--mobile .service-build-item {
        grid-template-columns: 74px minmax(200px, 240px) minmax(0, 1fr);
    }
    .service-detail .service-build--mobile .service-build-number {
        grid-row: 1;
    }
    .service-detail .service-build--mobile .service-build-media {
        grid-column: 2;
        grid-row: 1;
    }
    .service-detail .service-build--mobile .service-build-copy {
        grid-column: 3;
        grid-row: 1;
        align-self: center;
    }

    /* Timeline → simple vertical list. The horizontal zig-zag ribbon can't
       follow a vertical stack, so hide it and draw a straight connector line
       down the badge column instead. */
    .service-detail .process-track { gap: 0; }
    .service-detail .process-ribbon { display: none; }
    .service-detail .process-row { --badge: 64px; --ring: 8px; }
    .service-detail .process-nodes {
        flex-direction: column;
        max-width: 520px;
        margin: 0 auto;
    }
    .service-detail .process-step,
    .service-detail .process-step.is-low,
    .service-detail .process-step.is-high {
        flex: none;
        min-height: 0;
        justify-content: flex-start;
        align-items: flex-start;
        gap: 18px;
        padding-bottom: 28px;
    }
    /* badge back into normal flow, with a vertical connector behind it */
    .service-detail .process-badge,
    .service-detail .process-step.is-low .process-badge,
    .service-detail .process-step.is-high .process-badge {
        position: relative;
        left: auto;
        top: auto;
        margin-left: 0;
        flex: 0 0 auto;
    }
    /* One connector per step spans from the current circle's centre to the next
       circle's centre, so varying description heights cannot leave broken gaps. */
    .service-detail .process-step:not(:last-child)::after {
        content: "";
        position: absolute;
        top: calc(var(--badge) / 2);
        left: calc(var(--badge) / 2 - 2px);
        width: 4px;
        height: 100%;
        background: var(--sd-amber);
        border-radius: 2px;
        z-index: 0;
    }
    .service-detail .process-badge svg { width: 26px; height: 26px; }
    .service-detail .process-badge i { font-size: 24px; }
    /* label sits to the right of the badge, top-aligned */
    .service-detail .process-label,
    .service-detail .process-step.is-low .process-label,
    .service-detail .process-step.is-high .process-label {
        position: relative;
        left: auto;
        top: auto;
        bottom: auto;
        transform: none;
        width: auto;
        max-width: none;
        flex: 1 1 auto;
        text-align: left;
        padding-top: 6px;
    }

    .service-detail .service-build-item {
        grid-template-columns: 74px minmax(0, 1fr);
        gap: 24px;
        align-items: start;
    }
    .service-detail .service-build-number {
        grid-column: 1;
        grid-row: 1 / span 2;
        font-size: 76px;
        letter-spacing: -4px;
    }
    .service-detail .service-build-media {
        grid-column: 2;
        grid-row: 1;
    }
    .service-detail .service-build-copy {
        grid-column: 2;
        grid-row: 2;
        max-width: 620px;
    }

    .service-detail .tech-cloud-list {
        grid-template-columns: repeat(7, 78px);
        grid-template-rows: none;
        grid-auto-flow: row;
        grid-auto-columns: auto;
        gap: 10px;
        min-height: 0;
        padding: 24px 0;
    }
}

@media (max-width: 720px) {
    .service-detail { --container-pad: 20px; }
    .service-detail .sd-hero-slide__ghost {
        font-size: clamp(34px, 10vw, 42px);
        letter-spacing: -0.8px;
    }
    .service-detail .service-overview-inner { padding: 40px var(--container-pad) 56px; }
    .service-detail .service-why-inner { padding: 64px var(--container-pad); }
    .service-detail .service-process-inner { padding: 0 var(--container-pad) 64px; }
    .service-detail .service-build-inner { padding: 76px var(--container-pad) 88px; }
    .service-detail .service-build-head { margin-bottom: 44px; }
    .service-detail .service-build-heading {
        font-size: clamp(34px, 9vw, 42px);
        letter-spacing: -0.6px;
    }
    .service-detail .service-build-intro { font-size: 15px; margin-top: 20px; }
    .service-detail .service-build-item {
        display: block;
        min-height: 0;
        padding: 34px 0 42px;
    }
    .service-detail .service-build--mobile .service-build-item {
        display: block;
    }
    .service-detail .service-build-number {
        display: block;
        margin: 0 0 20px;
        font-size: 72px;
    }
    .service-detail .service-build-media { margin-bottom: 26px; }
    .service-detail .service-build--mobile .service-build-media {
        width: min(72vw, 220px);
        margin: 0 auto 28px;
    }
    .service-detail .service-build-copy { max-width: none; }
    .service-detail .service-build-title { font-size: 28px; margin-bottom: 14px; }
    .service-detail .service-tech-cloud {
        padding: 64px 0;
    }
    .service-detail .tech-cloud-heading { font-size: 26px; }
    .service-detail .tech-cloud-list {
        grid-template-columns: repeat(4, 64px);
        grid-template-rows: none;
        grid-auto-flow: row;
        grid-auto-columns: auto;
        justify-content: center;
        gap: 10px;
        min-height: 0;
        padding: 28px 0;
    }
    /* The width-filling duplicate set is desktop-only — phones show each
       technology once. Hiding these also re-bases the :nth-child offsets
       below onto the 14 remaining tiles. */
    .service-detail .tech-cloud-item--fill {
        display: none;
    }
    .service-detail .tech-cloud-item,
    .service-detail .tech-cloud-item:nth-child(4n + 3),
    .service-detail .tech-cloud-item:nth-child(4n + 4) {
        transform: translateY(0);
    }
    .service-detail .tech-cloud-item:nth-child(4n + 1),
    .service-detail .tech-cloud-item:nth-child(4n + 3) {
        transform: translateY(-10px);
    }
    .service-detail .tech-cloud-item:nth-child(4n + 2),
    .service-detail .tech-cloud-item:nth-child(4n + 4) {
        transform: translateY(10px);
    }
    .service-detail .tech-cloud-mark {
        width: 62px;
        height: 62px;
        border-radius: 11px;
        font-size: 31px;
    }
    .service-detail .gallery-heading { font-size: 28px; }
    .service-detail .why-block__title { font-size: 24px; }
    .service-detail .service-why-eyebrow { padding-top: 72px; }
    .service-detail .service-why-inner { padding-top: 72px; padding-bottom: 72px; }
    .service-detail .service-why-eyebrow + .service-why-inner { padding-top: 28px; }
    .service-detail .overview-thumb { width: 80px; height: 60px; }
    .services-cta-band .cta-band-heading { font-size: 30px; }
    .services-cta-band .cta-band-actions { flex-direction: column; align-items: stretch; width: 100%; }
    .services-cta-band .cta-band-btn { justify-content: center; }
}

/* ================================================================
   SCROLL REVEAL — sections fade + rise into view (IntersectionObserver
   adds .is-revealed). Hidden initial state only applies once JS has
   marked the root with .reveal-ready, so no-JS users see everything.
================================================================ */
.service-detail.reveal-ready [data-reveal] {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity 0.7s var(--sd-ease), transform 0.7s var(--sd-ease);
    will-change: opacity, transform;
}
.service-detail.reveal-ready [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
}

@media (prefers-reduced-motion: reduce) {
    .service-detail *,
    .services-cta-band * { transition: none !important; }
    /* never hide content when motion is reduced */
    .service-detail.reveal-ready [data-reveal] { opacity: 1; transform: none; }
    /* stop the auto-scroll; let users scroll the strip manually instead */
    .service-detail .gallery-track { animation: none; }
    .service-detail .gallery-marquee { overflow-x: auto; }
}
