/* Site stylesheet. Bootstrap (vendored, see base.html) supplies components
 * (buttons, cards, grid, forms, navbar, breadcrumb, pagination, modal) --
 * this file holds design tokens, brand overrides of Bootstrap's own CSS
 * variables (no Sass build step, so this is how a vendored, pre-built
 * Bootstrap gets re-themed), and the handful of pieces Bootstrap doesn't
 * provide (hero, site header/footer skeleton, htmx progress bar). No
 * third-party CDN fonts (the CSP allows only same-origin assets) --
 * Inter and DM Sans are self-hosted below. No inline style="" anywhere in
 * templates: put utilities here instead. */

/* Inter, variable weight 100-900 in one file (how Google serves it) -- the
 * heading typeface, as in the home hero. */
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url("../fonts/inter-variable.260c81a4759b.woff2") format("woff2-variations"), url("../fonts/inter-variable.260c81a4759b.woff2") format("woff2");
}

/* Source Serif 4 (OFL, see fonts/Source-Serif-4-OFL.txt), variable weight
 * 200-900, latin subset -- section headings on the Data & Marketing page
 * (body.dm-page, see "dm-page serif headings"). */
@font-face {
    font-family: "Source Serif 4";
    font-style: normal;
    font-weight: 200 900;
    font-display: swap;
    src: url("../fonts/source-serif-4-variable.c1c9c07dd7b6.woff2") format("woff2-variations"), url("../fonts/source-serif-4-variable.c1c9c07dd7b6.woff2") format("woff2");
}

/* DM Sans (OFL, see fonts/DM-Sans-OFL.txt), variable weight 100-1000, latin
 * subset -- body text, on trial. */
@font-face {
    font-family: "DM Sans";
    font-style: normal;
    font-weight: 100 1000;
    font-display: swap;
    src: url("../fonts/dm-sans-variable.3ccd9ab2050b.woff2") format("woff2-variations"), url("../fonts/dm-sans-variable.3ccd9ab2050b.woff2") format("woff2");
}

:root {
    /* Type: Inter for headings, --font-text for body text. To go back to
     * Inter everywhere, point --font-text at var(--font-inter).
     * --font-heading / --font-display are kept as aliases older rules use. */
    --font-inter: "Inter", "Aptos", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-text: "DM Sans", var(--font-inter);
    --font-sans: var(--font-text);
    --font-heading: var(--font-inter);
    --font-sans-new: var(--font-text);
    --font-heading-new: var(--font-inter);
    --font-display: var(--font-inter);
    --font-serif: "Source Serif 4", Georgia, "Times New Roman", serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

    /* One type scale for the whole site (UI/UX review): every heading reads
       one of these, nothing is set below --fs-small. Fluid between phone
       and desktop with whole-pixel ends; the phone values are the clamp
       minimums. */
    --fs-display: clamp(40px, 5.6vw, 72px);
    --fs-h1: clamp(36px, 4.4vw, 56px);
    --fs-h2: clamp(30px, 3.2vw, 40px);
    --fs-h3: clamp(22px, 2.2vw, 28px);
    --fs-h4: 20px;
    --fs-body: 17px;
    --fs-small: 14px;

    /* Spacing tokens: section top/bottom, narrower bands, and the gap
       between a heading block and its content. */
    --space-section: 120px;
    --space-section-sm: 80px;
    --space-block: 48px;
    --color-text: #1f2933;
    --color-muted: #52606d;
    --color-bg: #ffffff;
    --color-bg-alt: #f5f7fa;
    --color-border: #d9e2ec;
    --color-primary: #1e3a5f;
    --color-primary-contrast: #ffffff;
    --color-accent: #ff650b;
    --color-accent-dark: #cc4e08;
    --color-accent-light: #ffc08a;
    --color-primary-soft: #274873;
    --color-ink: #091e30;
    --radius: 10px;
    --radius-lg: 18px;
    --container-narrow: 46rem;
    --space: 1rem;
    --shadow-sm: 0 1px 2px rgba(15, 30, 55, 0.06), 0 1px 3px rgba(15, 30, 55, 0.08);
    --shadow-md: 0 8px 24px rgba(15, 30, 55, 0.1), 0 2px 6px rgba(15, 30, 55, 0.06);
    --shadow-lg: 0 24px 48px -12px rgba(15, 30, 55, 0.28);
    --ease: cubic-bezier(0.22, 1, 0.36, 1);

    /* --- Bootstrap re-theme: the brand orange as Bootstrap's "primary",
       the navy as "dark". Bootstrap 5.3's per-component CSS uses its own
       --bs-btn-*/--bs-*-rgb variables rather than always reading --bs-primary
       at runtime, so both the root token AND the component-level variables
       need overriding -- there's no Sass build here to recompile from. */
    --bs-primary: var(--color-accent);
    --bs-primary-rgb: 255, 101, 11;
    --bs-link-color: var(--color-primary);
    --bs-link-color-rgb: 30, 58, 95;
    --bs-link-hover-color: var(--color-accent);
    --bs-link-hover-color-rgb: 255, 101, 11;
    --bs-body-font-family: var(--font-sans);
    --bs-body-color: var(--color-text);
    --bs-border-radius: var(--radius);
    --bs-border-radius-lg: var(--radius-lg);
    --bs-box-shadow: var(--shadow-md);
    --bs-box-shadow-sm: var(--shadow-sm);
}
@media (max-width: 768px) {
    :root {
        --fs-display: 40px;
        --fs-h1: 36px;
        --fs-h2: 30px;
        --fs-h3: 22px;
        --fs-body: 16px;
        --space-section: 72px;
        --space-section-sm: 56px;
        --space-block: 32px;
    }
}
/* Base type: the scale above on the bare elements, all in Inter (700 for
   headings); three weights site-wide (700 / 600 / 400). */
body { --bs-body-font-size: var(--fs-body); font-size: var(--fs-body); }
h1, .h1 { font-size: var(--fs-h1); }
h2, .h2 { font-size: var(--fs-h2); }
h3, .h3 { font-size: var(--fs-h3); }
h4, .h4 { font-size: var(--fs-h4); font-family: var(--font-sans-new); }
h1, h2, h3, .h1, .h2, .h3 { font-family: var(--font-display); }
h1, h2, h3, h4, .h1, .h2, .h3, .h4 { font-weight: 700; }

.btn {
    --bs-btn-padding-x: 1.5rem;
    --bs-btn-padding-y: 0.7rem;
    --bs-btn-font-weight: 600;
    --bs-btn-border-radius: 999px;
    transition: transform 0.15s var(--ease), box-shadow 0.15s var(--ease), background-color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.btn-lg { --bs-btn-padding-x: 1.85rem; --bs-btn-padding-y: 0.85rem; --bs-btn-border-radius: 999px; }
.btn-sm { --bs-btn-border-radius: 999px; }
.btn-primary {
    --bs-btn-bg: var(--color-accent);
    --bs-btn-border-color: var(--color-accent);
    --bs-btn-hover-bg: var(--color-accent-dark);
    --bs-btn-hover-border-color: var(--color-accent-dark);
    --bs-btn-active-bg: var(--color-accent-dark);
    --bs-btn-active-border-color: var(--color-accent-dark);
    --bs-btn-disabled-bg: var(--color-accent);
    --bs-btn-disabled-border-color: var(--color-accent);
    --bs-btn-focus-shadow-rgb: 255, 101, 11;
    box-shadow: 0 6px 16px -4px rgba(255, 101, 11, 0.45);
}
.btn-outline-primary {
    --bs-btn-color: var(--color-accent);
    --bs-btn-border-color: var(--color-accent);
    --bs-btn-hover-bg: var(--color-accent);
    --bs-btn-hover-border-color: var(--color-accent);
    --bs-btn-active-bg: var(--color-accent);
    --bs-btn-active-border-color: var(--color-accent);
    --bs-btn-focus-shadow-rgb: 255, 101, 11;
}
/* hover:hover + pointer:fine (same guard already used elsewhere in this
   file, e.g. .svc-capability) so the lift only ever engages for a real
   mouse/trackpad -- on touch, tapping a button would otherwise leave it
   stuck "lifted" until something else is tapped, since touch UAs simulate
   :hover on tap with no real pointer-leave to clear it. */
@media (hover: hover) and (pointer: fine) {
    .btn-primary:hover { transform: translateY(-2px); box-shadow: 0 10px 22px -4px rgba(255, 101, 11, 0.55); }
    .btn-outline-primary:hover, .btn-outline-light:hover { transform: translateY(-2px); }
}
/* Bootstrap's own .btn-outline-light defaults to a solid near-white hover
   background with dark text -- the reference's is a faint ~8% white wash,
   border and text staying white throughout. Only used on home.html (the
   AI section's "Learn More", Contact's "Talk to Valin"). */
.btn-outline-light {
    --bs-btn-color: #fff;
    --bs-btn-border-color: rgba(255, 255, 255, 0.5);
    --bs-btn-hover-color: #fff;
    --bs-btn-hover-bg: rgba(255, 255, 255, 0.08);
    --bs-btn-hover-border-color: rgba(255, 255, 255, 0.5);
    --bs-btn-active-color: #fff;
    --bs-btn-active-bg: rgba(255, 255, 255, 0.08);
    --bs-btn-active-border-color: rgba(255, 255, 255, 0.5);
}
.navbar-dark, .bg-dark {
    --bs-navbar-color: rgba(255, 255, 255, 0.85);
    --bs-navbar-hover-color: #fff;
    --bs-navbar-active-color: #fff;
    --bs-bg-opacity: 1;
    background-color: var(--color-primary) !important;
}
.dropdown-item.active, .dropdown-item:active {
    background-color: var(--color-accent);
}
.dropdown-menu { --bs-dropdown-border-radius: var(--radius); box-shadow: var(--shadow-md); border: 0; padding: 0.625rem; }
/* Compact, reference/dropdown.png-matched sizing: smaller type and tighter
   horizontal padding than Bootstrap's 1rem/16px default, with a bit more
   vertical breathing room per row -- used only by the Services nav menu
   (the one dropdown on this site), so changed directly here rather than a
   narrower-but-redundant selector. */
.dropdown-item { border-radius: calc(var(--radius) - 4px); padding: 0.55rem 0.9rem; font-size: 15px; }
.navbar .dropdown-item:hover, .navbar .dropdown-item:focus {
    background-color: #FFF0E5;
    color: var(--color-accent);
}

*, *::before, *::after { box-sizing: border-box; }
/* The adaptive header nav (see syncNavFit() in app.js) correctly falls back
   to Bootstrap's stock offcanvas drawer -- parked just off the right edge
   of the viewport via position:fixed + translateX(100%) -- whenever the
   inline nav genuinely doesn't fit (narrow widths, or non-100% browser/OS
   zoom). Nothing clips that off-screen geometry by default, so it was
   widening the page's own horizontal scrollable area and surfacing a
   scrollbar, e.g. at 125% zoom.
   `clip`, not `hidden`: per the CSS Overflow spec, an axis explicitly set to
   anything but `visible` forces the *other*, unset axis to compute as
   `auto` rather than staying `visible` -- so plain `overflow-x: hidden`
   here was silently making html/body's own overflow-y `auto` too, turning
   them into scroll containers in their own right. That breaks
   `position: sticky` on direct children (e.g. .site-header): its nearest
   scrolling ancestor becomes body/html's own box instead of the real
   viewport, so it never actually sticks on scroll. `clip` suppresses the
   overflow without establishing a scroll container, so it fixes that
   without changing what this rule is actually here for. */
html, body { overflow-x: clip; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 100px; }
/* Keeps sticky-header-covered in-page anchors (#training, #why, #contact,
   #work, etc.) landing fully visible -- tracks the header's own logo
   breakpoints (.site-brand img, below) with a buffer, matching the
   reference's own scroll-padding-top/nav-height buffer pattern. */
@media (max-width: 900px) {
    html { scroll-padding-top: 90px; }
}
@media (max-width: 600px) {
    html { scroll-padding-top: 84px; }
}
/* Crisper text rendering: without this, Firefox on macOS in particular uses
   noticeably heavier default anti-aliasing than Chrome/Safari, making the
   same font-weight look thicker/less sharp there. Purely a rendering hint
   (no layout/color change), safe site-wide. */
body { background: var(--color-bg); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
img, svg, video { max-width: 100%; height: auto; }
h1, h2, h3, h4, h5, h6 { font-family: var(--font-heading); font-weight: 700; letter-spacing: -0.01em; }
h1, .h1 { font-size: var(--fs-h1); line-height: 1.08; letter-spacing: -0.02em; }
h2, .h2 { font-size: var(--fs-h2); line-height: 1.15; }
h3, .h3 { font-size: var(--fs-h3); }

/* --- new design system (Inter, new palette) -- scoped to the homepage and
   the designed service pages. */
body.home, body.service-page { font-family: var(--font-sans-new); background: #fcfbf9; }
body.service-page h1, body.service-page h2, body.service-page h3 { font-family: var(--font-display); }
/* Headings use the same Inter as the home hero. */
body.home h1, body.home h2, body.home h3 { font-family: var(--font-display); }
body.home h1, body.home .h1 { font-size: var(--fs-display); font-weight: 700; letter-spacing: -0.03em; line-height: 1.05; }
body.service-page h1, body.service-page .h1 { font-size: var(--fs-h1); font-weight: 700; letter-spacing: -0.03em; line-height: 1.08; }
body.home h2, body.home .h2, body.service-page h2, body.service-page .h2 { font-size: var(--fs-h2); font-weight: 700; letter-spacing: -0.02em; }
body.home .btn, body.service-page .btn { font-family: var(--font-sans-new); }
body.home section .eyebrow, body.service-page section .eyebrow { font-size: var(--fs-small); font-weight: 600; letter-spacing: 0.12em; }
/* Home's own eyebrow weight/tracking -- the reference's .eyebrow is 650/
   .15em, heavier-tracked than the site-wide 700/.1em used elsewhere
   (including the service page, left untouched). */
body.home .eyebrow { font-weight: 600; letter-spacing: 0.12em; }
code { font-family: var(--font-mono); font-size: 0.92em; background: var(--color-bg-alt); padding: 0.1em 0.35em; border-radius: 3px; }
.lead { color: var(--color-muted); font-size: 18px; }
#solutions .lead, #approach .lead, #challenge .lead { font-size: 22px; max-width: 40rem; }
.meta, .muted { color: var(--color-muted); font-size: 15px; }
.text-accent { color: var(--color-accent); }
.text-ink { color: var(--color-ink); }
.text-link { display: inline-flex; align-items: center; gap: 0.35rem; font-weight: 600; color: var(--color-accent); text-decoration: none; }
.text-link:hover { color: var(--color-accent-dark); }
.eyebrow { display: inline-block; color: var(--color-accent); font-weight: 600; font-size: var(--fs-small); letter-spacing: 0.12em; text-transform: uppercase; margin-bottom: 0.5rem; }
.eyebrow--rule { display: inline-flex; align-items: center; gap: 0.6rem; }
.eyebrow--rule::before { content: ""; display: inline-block; width: 1.5rem; height: 2px; background: var(--color-accent); }

/* --- extra breathing room between eyebrow/heading/paragraph/CTA, home page
   only. body.home (not the shared .eyebrow/h2/.lead rules above, which are
   also used -- h2's font-size rule even by the service detail page) so
   this can't affect any other page. :not(.hero-lead) excludes the one
   paragraph that already has its own exact, previously-specified margin
   (25px/29px, fixed, not clamped) -- this rule's higher specificity would
   otherwise silently win over that shorthand's bottom value. Sibling block
   margins collapse, so this plays correctly with sections whose CTA
   already carries its own mt-* utility (AI, Why Valin, Training): the
   larger of the two wins rather than the two stacking. Responsive via
   clamp() rather than a fixed px value, per section/viewport, not a hard
   breakpoint jump. */
body.home .eyebrow { margin-bottom: clamp(0.875rem, 0.625rem + 1vw, 1.25rem); }
body.home h2 { margin-bottom: clamp(1.125rem, 0.625rem + 2vw, 1.75rem); }
body.home .lead:not(.hero-lead) { margin-bottom: clamp(1.125rem, 0.625rem + 2vw, 1.75rem); }

/* --- Home page refinement pass, matching reference/Valin-Solutions-Homepage.html
   as closely as possible -- every rule in this block is body.home-scoped so
   the service detail page (body.service-page, which shares the same
   .container/.section/colour tokens) keeps its current appearance exactly.

   Muted text / hairline colour: the reference's own tokens are a shade off
   the site-wide --color-muted/--color-border, redeclared here (CSS custom
   properties cascade to descendants) rather than changed at :root, so only
   elements rendered while on Home pick up the new shade. */
body.home { --color-muted: #586C7D; --color-border: #DCE2E6; }

/* Content width: one container for every page (UI/UX review) -- 1240px wide
   including its 24px side padding, set once in the shared .container rule
   above; Home and the service pages no longer carry their own formulas. */
/* The hero uses the full home grid, so its copy lines up with the header's
   logo. */
body.home .hero-centered .container { max-width: none; }


/* Section vertical rhythm: every section uses --space-section (120px, 72px
   on phones); bands use --space-section-sm. */
body.home #solutions,
body.home #why,
body.home #approach,
body.home #challenge,
body.home #training {
    padding-block: var(--space-section);
}

/* Two-column row gaps: every section below shares the same underlying bug --
   the row markup only carries Bootstrap's generic g-4 utility (24px gutter,
   confirmed via --bs-gutter-x), while the reference specifies a much wider,
   section-specific gap between its text and image/form columns (its own
   .approach-heading/.ai-top/.challenge-grid/.contact-grid/.training .split
   rules). The 24px gutter is why text and images throughout the page read as
   noticeably more cramped than the reference. Each override only changes
   --bs-gutter-x (not -y), and only at >=992px -- the same breakpoint where
   these columns actually go side-by-side; below that they stack to 100%
   width already and the vertical gap between stacked blocks is untouched.
   #approach/#ai/#challenge/#training are home-only ids, safe to target
   directly; #contact also exists on the service page, so that one is
   body.home-scoped. Second-tier values (<=1150px) match the reference's own
   tablet reduction exactly where it was confirmed (35px, shared by several
   of its sections at that breakpoint). */
@media (min-width: 992px) {
    #approach .row { --bs-gutter-x: 65px; }
    #ai .row { --bs-gutter-x: 40px; }
    #challenge .row { --bs-gutter-x: 70px; }
    body.home #contact .row { --bs-gutter-x: 58px; }
}
@media (min-width: 992px) and (max-width: 1150px) {
    #approach .row,
    #challenge .row { --bs-gutter-x: 35px; }
    body.home #contact .row { --bs-gutter-x: 35px; }
}
/* #training's own two columns are split 1.08fr/1fr (the text column
   slightly wider), not Bootstrap's rigid 50/50 col-lg-6/col-lg-6 -- left
   as-is, the text column was narrower than the reference's, which is why
   its heading (a fixed two-line break, not a reflow) left more unfilled
   space on the right at some widths than the reference ever shows. Also
   extended down to 901px (not Bootstrap's 992px lg breakpoint): the
   reference keeps this row two-column until it actually stacks at 900px,
   so 901-991px needs forcing back to side-by-side, same reasoning as
   .why-valin-row's own extension below. */
@media (min-width: 901px) {
    #training .row { --bs-gutter-x: 58px; }
    #training .row > .col-lg-6 { flex: 0 0 auto; width: 51.9231%; }
    #training .row > .col-lg-6:not(.training-content) { width: 48.0769%; }
}
@media (min-width: 901px) and (max-width: 1150px) {
    /* Matches the reference's own exact value for this tier (42px, not
       45px -- the figure the other sections' shared 35px happened to be
       closest to, but #training's own tablet value is 7px tighter again). */
    #training .row { --bs-gutter-x: 42px; }
}
/* The reference's .contact-grid also uses align-items:start (its form is
   taller than its text column, and the reference keeps both flush at the
   top) where every other two-column section here uses center. !important is
   needed to beat the row's own .align-items-center utility class
   (templates/web/home.html), which is itself !important (all Bootstrap
   alignment utilities are). body.home-scoped like the gap override above. */
body.home #contact .row { align-items: start !important; }
/* Matches the reference's own industry-layout gap (40px) -- this row has no
   gap at all at the default (desktop) tier, only at its own narrower
   breakpoints below. */
.industries-band__inner { gap: 40px; }

/* Header/footer: the reference's own nav is more compact (14px links, a
   smaller logo) than this site's original shared header. Applied to both
   body.home and body.service-page (at the user's explicit request, so the
   service page's chrome matches Home) -- every other body.home-scoped rule
   in this file (hero, section spacing, colours, etc.) is untouched and
   still Home-only; only this header/footer block is shared across both. */
body.home .navbar .nav-link,
body.service-page .navbar .nav-link {
    font-size: 14px;
    color: #091E30;
    letter-spacing: normal;
}
/* Matches the reference's own 84-85px header height. !important is needed
   here specifically because the markup's own .py-2 utility (header.html)
   is itself !important (Bootstrap's spacing utilities all are), so nothing
   at ordinary specificity can override it. */
body.home .navbar,
body.service-page .navbar {
    padding-block: 0.75rem !important;
}
/* #primary-nav's own clamp (below, up to 16px) otherwise wins on specificity
   (id beats this rule's three classes) -- restated against that same id so
   the CTA is a flat 14px like the reference, in both the inline and
   offcanvas layouts. */
body.home #primary-nav .btn-cta,
body.service-page #primary-nav .btn-cta {
    font-size: 14px;
}
body.home .site-brand img,
body.service-page .site-brand img {
    width: 166px;
    height: auto;
    max-height: 58px;
}
@media (max-width: 900px) {
    body.home .site-brand img,
    body.service-page .site-brand img {
        width: 148px;
        max-height: 50px;
    }
}
@media (max-width: 600px) {
    body.home .site-brand img,
    body.service-page .site-brand img {
        width: 122px;
        max-height: 43px;
    }
}
/* Section CTA buttons the reference keeps at its one uniform 14px, where
   they'd otherwise fall back to Bootstrap's 16px default. */
body.home #training .btn-primary,
body.home #challenge .btn-outline-primary,
body.home .cta-band__form button[type="submit"] {
    font-size: 14px;
}
/* Every reference button is a uniform 50px tall with a 28px gap between its
   label and arrow span -- the hero's own CTA already has a bespoke override
   doing this (see #home .hero-cta), but it was never applied to
   the base .btn, so every *other* button on the page (outline buttons on
   Challenge/AI, the training CTA, etc.) fell back to Bootstrap's shorter
   0.7rem vertical padding and had no gap at all -- the label and arrow sat
   flush against each other instead of the reference's deliberately spacious
   28px apart. Setting it once here, scoped to body.home, means every home
   button gets it except where a higher-specificity rule already overrides
   padding/gap on purpose (none currently do). */
body.home .btn {
    --bs-btn-padding-y: 0.9375rem;
    gap: 28px;
    min-height: 50px;
}
/* The reference also nudges the arrow span up and to the right on hover
   (its own .button:hover span{transform:translate(2px,-2px)}), on top of
   the whole button lifting -- entirely missing here before. Guarded the
   same way as the button lift itself, for the same stuck-on-touch reason. */
body.home .btn > span[aria-hidden="true"] {
    display: inline-block;
    transition: transform 0.3s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
    body.home .btn:hover > span[aria-hidden="true"] {
        transform: translate(2px, -2px);
    }
}
/* The reference's outline buttons use the same darker orange as the
   eyebrows, not the brighter default accent. */
body.home .btn-outline-primary {
    --bs-btn-color: #CF4B00;
    --bs-btn-border-color: #CF4B00;
    --bs-btn-hover-bg: #CF4B00;
    --bs-btn-hover-border-color: #CF4B00;
    --bs-btn-active-bg: #CF4B00;
    --bs-btn-active-border-color: #CF4B00;
}

/* --- layout ----------------------------------------------------------------
   .container--narrow: Bootstrap has no "prose width" container; used for
   text-heavy pages (About, Contact, legal, FAQs).

   Site-wide .container width: a centred, moderately narrow column (close to
   Bootstrap's own stock 1140/1320px caps) with generous horizontal padding,
   so content stays well clear of the browser edges on wide desktop screens
   instead of stretching edge-to-edge. Every section on the site already
   follows the same structure -- a full-bleed <section> (which carries any
   background colour) wrapping a <div class="container"> for the constrained
   content -- so this affects every section's content width uniformly
   without touching any template.

   One fluid rule instead of Bootstrap's per-breakpoint max-width steps: the
   side padding scales continuously with viewport width (clamp, not a fixed
   1rem) so a small laptop isn't stuck with the same tight edge padding as a
   phone, and a single max-width means there's no hard jump in margin size
   between adjacent screen sizes -- it grows smoothly right up to the cap.

   The 1.25rem floor is below a Bootstrap .row's largest-used gutter (.g-5,
   3rem -- half of that, 1.5rem, is the row's own negative outer margin) --
   home.html's .row.g-5 instances were eased to .g-4 (1.5rem gutter, needs
   only 0.75rem) specifically so they don't bleed past this tighter padding
   on narrow screens. A new .row.g-5 placed directly in a .container would
   need the same treatment, or a wider floor here. */
.container--narrow { max-width: var(--container-narrow); margin-inline: auto; }
.container--narrow-lg { max-width: 62rem; margin-inline: auto; }
.container, .container-sm, .container-md, .container-lg, .container-xl, .container-xxl {
    width: 100%;
    max-width: 1240px;
    margin-inline: auto;
    padding-inline: 24px;
}
.section { padding-block: var(--space-section); }
.section--alt { background: var(--color-bg-alt); }
/* #approach shares .section--alt's pale background; #solutions alone goes
   white, so this overrides just that one section rather than touching the
   shared class. */
#solutions.section--alt { background: var(--color-bg); }
/* Every home-page eyebrow shares this colour except #ai ("Digital
   Intelligence"), which stays on its own .feature-band .eyebrow rule
   (white, for contrast on the orange band) -- deliberately not listed
   here. #industries is also excluded: its own dark navy band needs the
   lighter tint .industries-band .eyebrow already sets (#FF8B37, matching
   the reference), not this darker one -- this used to be ID-scoped
   specifically to override that rule, which was the bug. #contact stays
   here (used by both Home and the Service page's own contact section, and
   the Service page's isn't part of this fix) but gets a brighter,
   home-only override just below for the same reason as #industries. */
#solutions .eyebrow,
#why .eyebrow,
#approach .eyebrow,
#challenge .eyebrow,
#training .eyebrow,
#contact .eyebrow { color: #CF4B00; }
/* Matches the reference's own lighter tint for this eyebrow specifically --
   its dark navy band needs more contrast than the shared #CF4B00 above
   provides. Home-scoped so the Service page's own #contact section (same
   ID, shared component) is unaffected. */
body.home #contact .eyebrow { color: #FF963F; }
/* Heading/intro-paragraph spec for this section only, exact client values.
   #solutions h2 (ID beats the shared body.home h2 rule's specificity) and
   #solutions .lead (one of the three selectors in the shared #solutions
   .lead, #approach .lead, #challenge .lead rule above -- repeating it here,
   later in the file, overrides font-size/line-height/colour for #solutions
   only; #approach and #challenge keep that rule's original values, and its
   max-width keeps applying here too since this doesn't redeclare it). */
#solutions h2 {
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1.13;
    letter-spacing: -0.045em;
    color: #091E30;
    /* Zeroes the shared body.home h2 margin-bottom (a clamp, ~28px at
       desktop): in the reference this h2 sits inline inside .section-heading
       with no margin of its own -- the 40px gap down to the card grid comes
       entirely from .section-heading's own margin-bottom (set on the row
       below), not from the heading's. Left unreset, this used to add on
       top of it, and the eyebrow (fixed just below, now a sibling above the
       row instead of nested inside its first column) used to inflate the
       row's own height further still -- together they were the "card grid
       sits further from the heading than the reference" gap. */
    margin-bottom: 0;
}
/* Reference's own eyebrow margin-bottom and rule width for this section
   specifically (not the shared clamp/default-1.5rem rule width, which
   landed close but not exact). */
#solutions > .container > .eyebrow { margin-bottom: 22px; }
#solutions > .container > .eyebrow.eyebrow--rule::before { width: 34px; }
#solutions .lead {
    font-family: var(--font-text);
    /* The reference's own .section-heading p is 16px -- its other sections'
       intro paragraphs (approach/challenge/training below) are the base 17px,
       this one alone differs. */
    font-size: 16px;
    font-weight: 400;
    line-height: 1.7;
    color: #586C7D;
    /* Resets the shared "#solutions .lead, #approach .lead, #challenge
       .lead { max-width: 40rem }" rule above: that cap is for desktop only
       (re-applied, narrower, inside the >=992px block below) -- below lg
       this paragraph is a full-width stacked block and should use all of
       its available column width, not a leftover desktop cap. */
    max-width: none;
}
/* Below lg, the heading and this paragraph are already full-width stacked
   blocks (Bootstrap's `.row > *` default -- col-lg-6/col-lg-5 only apply at
   >=992px), so the paragraph should just use that full column width with no
   cap and no push. The desktop-only cap + right-push live here, scoped to
   the same breakpoint as the two-column layout itself. */
@media (min-width: 992px) {
    #solutions .lead {
        /* Controls line-wrap width only (not font-size) so the paragraph
           reads like the reference's ~3-line block instead of stretching
           edge-to-edge across its much wider column. */
        max-width: 28rem;
        /* Pins the capped block flush to the column's right edge, which
           lines up exactly with the solution-card grid's right edge below
           (both sit directly inside the same .container, no extra padding). */
        margin-left: auto;
        margin-right: 0;
    }
}
@media (max-width: 991.98px) {
    #solutions h2 { font-size: var(--fs-h2); }
}
/* Matches the reference's own exact .section-heading gap (50px between the
   heading and intro-paragraph columns, 35px <=1150px) and margin-bottom
   (40px down to the card grid below, 28px <=600px) -- this row was still
   carrying Bootstrap's generic .g-4 (24px) gutter and .mb-5 (48px) margin,
   both noticeably tighter/looser than the reference respectively, which is
   exactly the "more space" feel reported for this section. .mb-5 is a
   Bootstrap utility class and carries !important, so the override needs it
   too (same reason the navbar/footer padding fixes elsewhere in this file
   do). */
#solutions .row.justify-content-between { --bs-gutter-x: 50px; margin-bottom: 40px !important; }
@media (max-width: 1150px) { #solutions .row.justify-content-between { --bs-gutter-x: 35px; } }
@media (max-width: 600px) { #solutions .row.justify-content-between { margin-bottom: 28px !important; } }
/* Same pattern as #solutions above: #approach.section--alt overrides just
   this section's background instead of the shared .section--alt rule, and
   #approach h2/.lead override the shared body.home h2 rule and the shared
   #solutions .lead, #approach .lead, #challenge .lead rule respectively,
   for #approach only. */
#approach.section--alt { background: linear-gradient(120deg, #FAF8F3, #FDFBF7); }
#approach h2 {
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1.13;
    letter-spacing: -0.045em;
    color: #091E30;
}
#approach .lead {
    /* 16px, not 17px -- #challenge's own lead genuinely is 17px (the
       pattern this was copied from), but the reference's #approach is a
       size smaller. */
    font-size: 16px;
    /* Bootstrap's own .lead sets font-weight:300. */
    font-weight: 400;
    line-height: 1.7;
    color: #586C7D;
    /* Resets both the 28rem cap this used to carry and the shared
       "#solutions .lead, #approach .lead, #challenge .lead { max-width:
       40rem }" rule above -- either one wrapped the text well before the
       edge of its actual col-lg-6 column, which is wider than both at most
       desktop widths. No cap: the paragraph now wraps against its real
       container width instead of an artificially narrow one. */
    max-width: none;
}
@media (max-width: 991.98px) {
    #approach h2 { font-size: var(--fs-h2); }
}
/* #challenge is a plain .section (not .section--alt), so its background
   needs no shared-class scoping; its h2/.lead follow the same pattern as
   #solutions/#approach above (the latter is the third and last selector in
   the shared #solutions .lead, #approach .lead, #challenge .lead rule). */
#challenge { background: #FFFFFF; }
#challenge h2 {
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1.13;
    letter-spacing: -0.045em;
    color: #091E30;
}
#challenge .lead {
    font-size: 17px;
    /* Bootstrap's own .lead sets font-weight:300. */
    font-weight: 400;
    line-height: 1.7;
    color: #586C7D;
    /* No cap, matching #approach .lead: wraps against the real col-lg-5
       column width instead of an artificially narrow fixed value. */
    max-width: none;
}
@media (max-width: 991.98px) {
    #challenge h2 { font-size: var(--fs-h2); }
}
.section--tight { padding-block: clamp(2rem, 4vw, 3rem); }
.flow { overflow-wrap: break-word; }
.flow > * + * { margin-top: 1em; }
.flow h2, .flow h3 { margin-top: 1.6em; }
.flow img { border-radius: var(--radius); }
.flow blockquote { margin: 1.5em 0; padding-left: 1em; border-left: 4px solid var(--color-border); color: var(--color-muted); }
/* Editor-authored content can include a table wider than the column; scope
   the overflow to the table itself (its own scrollbar) rather than the page. */
.flow table { display: block; max-width: 100%; overflow-x: auto; }

/* --- accessibility helpers ------------------------------------------------ */
.screen-reader-text {
    position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.skip-link:focus {
    position: fixed !important; top: 0.5rem; left: 0.5rem; width: auto; height: auto; margin: 0;
    padding: 0.5rem 1rem; clip: auto; background: var(--color-primary); color: #fff; z-index: 1000;
}
:focus-visible { outline: 3px solid var(--color-accent); outline-offset: 2px; }
.u-hidden { display: none !important; }

/* --- header ----------------------------------------------------------------
   Bootstrap's navbar/dropdown/collapse classes handle structure and the
   mobile toggle; this just sets the brand's own look on top of them.
   Sticky with a shadow that fades in once the page scrolls (app.js toggles
   .site-header--scrolled; see there for why this can't be a scroll-linked
   CSS-only effect without more browser support than we want to assume).
   No resting border/hairline under it -- only the scrolled-in shadow. */
.site-header { position: sticky; top: 0; z-index: 1030; background: var(--color-bg); box-shadow: none; transition: box-shadow 0.2s var(--ease), transform 0.45s var(--ease); }
/* Hidden while scrolling down (app.js), back on the first scroll up. Only
   ever set while the drawer and dropdowns are closed: a transform makes the
   header the containing block for the fixed-position drawer inside it. */
.site-header--hidden { transform: translateY(-100%); }
.site-header--scrolled { box-shadow: var(--shadow-sm); }
.site-brand { display: inline-flex; align-items: center; gap: 0.6rem; }
.site-brand img { height: 4rem; width: auto; }
.navbar .nav-link { position: relative; font-weight: 600; font-size: 17px; letter-spacing: 0.01em; white-space: nowrap; color: var(--color-text); opacity: 0.85; transition: opacity 0.15s var(--ease); }
.navbar .navbar-nav .nav-link { padding-inline: 0.85rem; }
.navbar .nav-link:hover { opacity: 1; }
.navbar .dropdown-item.is-current { color: var(--color-accent) !important; font-weight: 700; opacity: 1; background-color: #FFF0E5; }
.navbar .nav-link.is-current {
    color: var(--color-text);
    opacity: 1;
}
/* :not(.dropdown-toggle) -- Services' toggle shares this same ::after
   pseudo-element with Bootstrap's own dropdown caret (immediately below),
   so without this exclusion, "Services" being the current section on an
   inner page replaced its arrow with this underline bar instead of showing
   both; excluded here so Services keeps its arrow and looks identical to
   every other page, matching the other .is-current::after rules below. */
.navbar .nav-link.is-current:not(.dropdown-toggle)::after {
    content: "";
    position: absolute;
    left: 0.85rem;
    right: 0.85rem;
    bottom: -0.4rem;
    height: 2px;
    background: var(--color-accent);
}
/* Services is the current section on every /services/ page (the template marks the toggle .is-current),
   but its ::after is Bootstrap's caret, so it never showed the underline. Draw the same bar on its ::before
   instead -- identical geometry/colour as the other links' underline, always on, caret untouched. */
.navbar .nav-link.dropdown-toggle.is-current::before {
    content: "";
    position: absolute;
    left: 0.85rem;
    right: 0.85rem;
    bottom: -0.4rem;
    height: 2px;
    background: var(--color-accent);
}
/* The open dropdown (z-index 1031) starts 2px below the toggle and would cover that bar; lift the open toggle above it. */
.navbar .nav-link.dropdown-toggle.show { z-index: 1032; }
.navbar-nav .dropdown-toggle::after { margin-left: 0.3rem; }
/* A frosted, translucent bar (matching the reference) instead of the
   original shared solid one -- applied to both pages, per the header/footer
   unification comment above. The blur lives on a ::before layer, not the
   header element itself: backdrop-filter establishes a containing block
   for position:fixed descendants (same as transform/filter), and the
   mobile nav drawer (#primary-nav, a fixed-position Bootstrap offcanvas)
   is nested inside this header -- directly on the header, that collapsed
   the drawer to the header's own ~72px height instead of the full
   viewport. The pseudo-element gives the identical visual result (it fills
   the header exactly and sits behind its content) without the header
   itself picking up a filter. */
body.home .site-header,
body.service-page .site-header {
    border-bottom: 1px solid rgba(18, 45, 58, 0.035);
}
body.home .site-header::before,
body.service-page .site-header::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: rgba(255, 255, 255, 0.95);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border-radius: 0;
    transition:
        opacity 0.25s var(--ease),
        top 0.5s var(--ease), right 0.5s var(--ease), bottom 0.5s var(--ease), left 0.5s var(--ease),
        border-radius 0.5s var(--ease), box-shadow 0.4s ease;
}
/* Scrolled: the frosted layer condenses into a floating bar the width of
   the content (the home grid's 1280px plus 24px each side), inset from the
   window and the header's own top/bottom, and the logo eases down a step.
   The header box keeps its height, so nothing below it moves. */
body.home .site-header,
body.service-page .site-header {
    --bar-x: max(12px, calc((100% - 1240px) / 2));
}
body.home .site-header.site-header--scrolled,
body.service-page .site-header.site-header--scrolled {
    background: transparent;
    border-bottom-color: transparent;
    box-shadow: none;
}
body.home .site-header--scrolled::before,
body.service-page .site-header--scrolled::before {
    top: 8px;
    right: var(--bar-x);
    bottom: 8px;
    left: var(--bar-x);
    border-radius: 12px;
    box-shadow: 0 0 0 1px #091E3012, 0 16px 36px -22px #091E3073;
}
body.home .site-brand img,
body.service-page .site-brand img {
    transform-origin: left center;
    transition: transform 0.45s var(--ease);
}
body.home .site-header--scrolled .site-brand img,
body.service-page .site-header--scrolled .site-brand img { transform: scale(0.88); }
@media (max-width: 1150px) {
    body.home .site-header,
    body.service-page .site-header { --bar-x: 12px; }
}
@media (max-width: 600px) {
    body.home .site-header,
    body.service-page .site-header { --bar-x: 8px; }
    body.home .site-header--scrolled::before,
    body.service-page .site-header--scrolled::before { top: 6px; bottom: 6px; border-radius: 10px; }
}
@media (prefers-reduced-motion: reduce) {
    .site-header,
    body.home .site-header::before,
    body.service-page .site-header::before,
    body.home .site-brand img,
    body.service-page .site-brand img { transition: none; }
}
/* Home only: transparent over the dark hero until the page scrolls
   (.site-header--scrolled, app.js), then the frosted white bar above fades
   back in. White links/logo apply only to the inline nav (.nav-fits) --
   the mobile drawer keeps its white panel and dark links. The header's
   second logo (.site-brand__light, header.html) is the white PNG. */
.site-brand__light { display: none; }
body.home .site-header:not(.site-header--scrolled) {
    background: transparent;
    border-bottom-color: transparent;
}
body.home .site-header:not(.site-header--scrolled)::before { opacity: 0; }
body.home .site-header:not(.site-header--scrolled) .site-brand img:not(.site-brand__light) { display: none; }
body.home .site-header:not(.site-header--scrolled) .site-brand__light { display: block; }
body.home .site-header:not(.site-header--scrolled) .navbar.nav-fits .nav-link,
body.home .site-header:not(.site-header--scrolled) .navbar.nav-fits .nav-link.is-current {
    color: #FFFFFF;
}
body.home .site-header:not(.site-header--scrolled) .navbar-toggler-icon { filter: invert(1) brightness(2); }
/* Nav underline: grows in on hover, not just a static bar on the current
   link (:not(.dropdown-toggle) leaves Services' caret icon alone -- both
   share the ::after pseudo-element, and the dropdown's own is-current
   styling is left exactly as it already was). */
body.home .navbar .nav-link:not(.dropdown-toggle)::after,
body.service-page .navbar .nav-link:not(.dropdown-toggle)::after {
    content: "";
    position: absolute;
    left: 0.85rem;
    right: 0.85rem;
    bottom: -0.4rem;
    height: 2px;
    background: var(--color-accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.25s;
}
/* The active section's underline must always show, on every input type --
   unconditional. */
body.home .navbar .nav-link.is-current:not(.dropdown-toggle)::after,
body.service-page .navbar .nav-link.is-current:not(.dropdown-toggle)::after {
    transform: scaleX(1);
}
/* The hover-only reveal is guarded (same stuck-on-touch reason as the
   button/card lifts above) -- without it, tapping a non-current link on a
   touch device would leave its underline visible until something else is
   tapped, which could misleadingly look like it became the active section. */
@media (hover: hover) and (pointer: fine) {
    body.home .navbar .nav-link:not(.dropdown-toggle):hover::after,
    body.service-page .navbar .nav-link:not(.dropdown-toggle):hover::after {
        transform: scaleX(1);
    }
}

/* --- adaptive nav ------------------------------------------------------------
   app.js's syncNavFit() measures whether the logo, links and CTA actually
   fit the header's available width (container.scrollWidth vs clientWidth,
   both already in the browser's real zoomed/scaled CSS-pixel space) and
   toggles .nav-fits on <nav> accordingly -- not a guessed viewport
   breakpoint, so this tracks any window width, monitor, zoom level or OS
   display-scaling setting. These declarations are what Bootstrap's own
   .navbar-expand-xxl/.offcanvas-xxl apply at their fixed 1400px breakpoint;
   here they're gated on the measured class instead. No class present (JS
   hasn't run yet, or never does) falls back to the plain offcanvas drawer,
   which is the safe default. */
.navbar.nav-fits { flex-wrap: nowrap; justify-content: flex-start; }
/* flex-shrink: 0 on both children is what makes the fit check meaningful --
   without it, the flexbox default (shrink to fit) would silently compress
   the logo and links instead of overflowing, so a genuine lack of space
   would go undetected instead of being measurable. The margin is the
   layout's real minimum breathing room between the logo and the nav group
   (part of what "fits" means), not a JS-estimated guess. */
.navbar.nav-fits .site-brand { flex-shrink: 0; margin-right: 1.5rem; }
.navbar.nav-fits .navbar-nav { flex-direction: row; margin-bottom: 0; align-items: center; }
/* The base .navbar-nav .dropdown-menu rule below (no .nav-fits) makes the
   submenu render inline in the narrow offcanvas drawer -- transparent, no
   shadow/border, indented. In the floating desktop layout it needs to be a
   normal solid popover instead, so every one of those is reset back here,
   not just position. */
.navbar.nav-fits .navbar-nav .dropdown-menu {
    position: absolute;
    z-index: 1031;
    background-color: var(--color-bg);
    box-shadow: var(--shadow-md);
    border: 0;
    padding: 0.625rem;
}
/* Hover reveals the desktop dropdown instead of requiring a click, same as
   a conventional site nav -- guarded to real pointers only (a touch tap has
   no true hover, so this leaves tap-to-open, the existing Bootstrap JS
   behaviour, as the only interaction there; same guard already used for the
   nav-link underline hover above). Click/keyboard open still works exactly
   as before via Bootstrap's own .show class -- this just adds another way
   to reveal the same menu, it doesn't replace that. */
@media (hover: hover) and (pointer: fine) {
    .navbar.nav-fits .nav-item.dropdown:hover > .dropdown-menu {
        display: block;
    }
}
.navbar.nav-fits .navbar-toggler { display: none; }
.navbar.nav-fits .offcanvas {
    position: static;
    z-index: auto;
    flex-grow: 1;
    flex-shrink: 0;
    width: auto !important;
    height: auto !important;
    visibility: visible !important;
    background-color: transparent !important;
    border: 0 !important;
    transform: none !important;
    transition: none;
}
.navbar.nav-fits .offcanvas .offcanvas-header { display: none; }
/* Grid instead of Bootstrap's default flex row: the nav sits flush next to
   the CTA button (1fr / auto columns, nav justify-self: end), with the free
   space pushed to the left between the logo and the nav -- menu grouped
   with "Discuss Your Project", not centred in the navbar. */
.navbar.nav-fits .offcanvas .offcanvas-body {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    column-gap: 2rem;
    flex-grow: 0;
    padding: 0;
    overflow-y: visible;
    background-color: transparent !important;
}
.navbar.nav-fits .navbar-nav { justify-self: end; }

/* --- mobile nav drawer (Bootstrap Offcanvas, right side) --------------------
   Default state (no .nav-fits): a real off-canvas drawer. Dropdown menus (if
   any are added later) render inline in the drawer instead of as a floating
   popup, which wouldn't make sense inside a narrow, scrollable panel; .nav-fits
   above restores the floating popup once the inline layout is active. ------- */
#primary-nav { --bs-offcanvas-width: min(22rem, 85vw); }
/* The "Discuss Your Project" CTA was the one piece of text in the whole
   header that never scaled down -- a flat 16px (Bootstrap's .btn default)
   at every viewport, unlike nearly everything else on the site, which uses
   clamp(). Inside the narrow offcanvas drawer specifically that reads as
   oversized next to the smaller nav links around it. */
#primary-nav .btn-cta { font-size: clamp(14px, 3.5vw, 16px); }
.navbar-nav .dropdown-menu {
    position: static;
    box-shadow: none;
    border: 0;
    background: transparent;
    padding-left: 1rem;
}
.navbar-nav .dropdown-header { padding-left: 0; }

/* --- boosted navigation progress bar ------------------------------------- */
#page-progress { position: fixed; top: 0; left: 0; height: 3px; width: 0; background: var(--color-accent); z-index: 1001; transition: width 0.3s ease; }
html.is-navigating #page-progress { width: 80%; }


/* --- stat band -------------------------------------------------------------- */
.stat-band { background: var(--color-primary-soft); color: #fff; }
.stat-band__number { font-family: var(--font-heading); font-weight: 700; font-size: clamp(1.8rem, 1.4rem + 1.6vw, 2.75rem); line-height: 1; color: #fff; }
.stat-band__label { color: rgba(255, 255, 255, 0.75); font-size: 14px; margin-top: 0.35rem; }

/* --- scroll reveal -----------------------------------------------------------
   [data-reveal] fades/slides up once it enters the viewport (app.js, via
   IntersectionObserver). Respects prefers-reduced-motion, and elements are
   already visible if JS never runs (progressive enhancement, not a gate). */
@media (prefers-reduced-motion: no-preference) {
    [data-reveal] { opacity: 0; transform: translateY(28px); transition: opacity 0.6s var(--ease), transform 0.6s var(--ease); }
    [data-reveal].is-visible { opacity: 1; transform: translateY(0); }
    [data-reveal-group] > * { opacity: 0; transform: translateY(28px); transition: opacity 0.6s var(--ease), transform 0.6s var(--ease); }
    [data-reveal-group].is-visible > * { opacity: 1; transform: translateY(0); }
    [data-reveal-group].is-visible > *:nth-child(2) { transition-delay: 0.08s; }
    [data-reveal-group].is-visible > *:nth-child(3) { transition-delay: 0.16s; }
    [data-reveal-group].is-visible > *:nth-child(4) { transition-delay: 0.24s; }
    [data-reveal-group].is-visible > *:nth-child(5) { transition-delay: 0.32s; }
}

/* --- pre-footer CTA band ("you will like it here", WAC-style closer) -------- */
.cta-band {
    position: relative;
    overflow: hidden;
    background:
        radial-gradient(46rem 26rem at 15% 120%, rgba(242, 124, 24, 0.3), transparent 55%),
        linear-gradient(165deg, var(--color-primary) 0%, var(--color-ink) 100%);
    color: #fff;
    text-align: center;
}
.cta-band h2 { color: #fff; }
.cta-band p { color: rgba(255, 255, 255, 0.8); }
.cta-band__lead { max-width: 34rem; font-size: 22px; }

/* --- editorial cards (case studies, big list-style entries) ----------------- */
/* No `display` here on purpose: this is combined with Bootstrap's `.row`
   (display: flex) on case study entries -- setting block would fight it. */
.editorial-card { text-decoration: none; color: inherit; padding-block: 1.75rem; border-top: 1px solid var(--color-border); transition: opacity 0.2s var(--ease); }
.editorial-card:hover { opacity: 0.7; }
.editorial-card:last-child { border-bottom: 1px solid var(--color-border); }
.editorial-card__tag { color: var(--color-accent); font-weight: 700; font-size: 14px; letter-spacing: 0.1em; text-transform: uppercase; }
.editorial-card__title { font-size: clamp(1.3rem, 1.15rem + 0.6vw, 1.7rem); margin: 0.35rem 0; color: var(--color-text); }
.editorial-card__desc { color: var(--color-muted); margin: 0; }

/* --- content cards (services/products/courses/case studies/team/jobs) ----- */
.content-card { border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease); }
.content-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.content-card .card-body { padding: 1.5rem; }
.content-card__icon { height: 2.75rem; width: 2.75rem; margin-bottom: 0.9rem; padding: 0.5rem; border-radius: 999px; background: rgba(242, 124, 24, 0.12); }
.content-card .card-img-top { aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--radius-lg) var(--radius-lg) 0 0; }

/* --- forms ------------------------------------------------------------------
   Bootstrap's .form-control/.form-label/.row/.g-3 handle layout; these are
   the bits it doesn't have. */
.form-notice { padding: 0.75rem 1rem; border-radius: var(--radius); border: 1px solid; }
.form-notice--success { color: #15803d; border-color: currentColor; background: #f0fdf4; }
.form-notice--error { color: #b91c1c; border-color: currentColor; background: #fef2f2; }
/* Draws attention to a field a "Discuss ..." CTA scrolled the visitor to
   (e.g. the cybersecurity page's "Discuss Your Cybersecurity Needs" CTA, and
   the equivalent CTAs on the web development and managed IT & cloud service
   pages); cleared by app.js on focus/input or after a short timeout, so it
   only ever greets the visitor, never traps them. Dark red (not Bootstrap's
   validation red) so it doesn't read as a form error. !important on both
   properties: each service page re-skins .form-control with its own
   border colour at a selector this one class can't out-specificity on every
   page (e.g. .cta-band--contact .contact-form .form-control's three classes
   on the web development page) -- this is a transient visual cue that must
   read the same regardless of which page's form it lands on. */
.field-highlight.form-control,
.field-highlight.form-select { border-color: #8b0000 !important; box-shadow: 0 0 0 0.2rem rgba(139, 0, 0, 0.25) !important; }

/* --- faqs ------------------------------------------------------------------- */
.faq-item { border-bottom: 1px solid var(--color-border); padding-block: 0.9rem; }
.faq-item summary { cursor: pointer; font-weight: 600; }
.faq-item__answer { margin-top: 0.6rem; color: var(--color-muted); }

/* --- footer -------------------------------------------------------------------
   No gap and a hairline (not a block) border between this and the section
   above it, so the two read as one continuous dark area rather than
   visibly separate blocks. Column headings reuse .eyebrow--rule (the same
   dash-accent component used everywhere else) instead of their own custom
   styling, for the same size/colour/spacing site-wide. */
/* Muted blue-grey instead of near-white -- matches the reference's softer
   body/link tone on this same dark-navy background (same token already used
   for the Industries carousel's text on an equally dark backdrop). */
.site-footer {
    position: relative;
    overflow: hidden;
    margin-top: 0;
    background:
        radial-gradient(44rem 30rem at 100% 100%, rgba(255, 139, 55, 0.22), transparent 60%),
        linear-gradient(135deg, var(--color-ink) 55%, #123349 100%);
    color: #D1DCE2;
    border-top: 1px solid var(--color-accent);
}
.site-footer a { color: inherit; text-decoration: none; }
.site-footer a:hover { color: var(--color-accent); }
.site-footer__logo { display: inline-block; margin-bottom: 1rem; }
.site-footer__logo img { display: block; }
.site-footer__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: 2rem; padding-block: 2rem; position: relative; z-index: 1; }
.site-footer__heading { display: inline-flex; margin-bottom: 0.75rem; color: #fff; }
.site-footer__links { list-style: none; margin: 0; padding: 0; }
.site-footer__links li { padding-block: 0.2rem; font-size: 14px; line-height: 1.55; }
/* social icons (partials/social.html) under the footer tagline: round
   outlined buttons that fill with the accent on hover */
.site-footer .social { display: flex; gap: 10px; list-style: none; margin: 1.25rem 0 0; padding: 0; }
.site-footer .social a { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, 0.22); color: #fff; transition: background-color 0.25s var(--ease), border-color 0.25s var(--ease), color 0.25s var(--ease); }
.site-footer .social a:hover, .site-footer .social a:focus-visible { background: var(--color-accent); border-color: var(--color-accent); color: #fff; }
.site-footer .social svg { width: 17px; height: 17px; }
.site-footer__bottom { border-top: 1px solid rgba(255, 255, 255, 0.12); padding-block: 1.25rem; font-size: 14px; }
.site-footer__bottom p { margin: 0; }
/* Plain-text buttons (not links, since they open a modal rather than
   navigate) styled to read exactly like the footer's other text. */
.site-footer__legal-link { background: transparent; border: 0; padding: 0; margin: 0; font: inherit; color: inherit; text-decoration: none; }
.site-footer__legal-link:hover { color: var(--color-accent); }

/* Legal pages (Privacy, Cookie, Terms): long policy text in the narrow
   prose column. Section headings are a step smaller than page h2s (scoped
   to body.legal-page to win over body.service-page h2), and in-page anchors
   clear the sticky header. */
.legal h1 { margin-bottom: 0.6em; }
body.legal-page .legal h2 { font-size: var(--fs-h3); letter-spacing: -0.01em; margin-top: 2em; scroll-margin-top: 7rem; }
body.legal-page .legal h3 { font-size: 1.1rem; }
.legal ul, .legal ol { padding-left: 1.4em; }
.legal li + li { margin-top: 0.35em; }
.legal a { color: var(--color-accent); overflow-wrap: anywhere; }
.legal__toc { columns: 2 22rem; column-gap: 2.5rem; }

/* Footer text sizing/colour, matching the reference -- applied to both
   pages (the user asked for the service page's footer to match Home's). */
/* A faint warm hairline (matching the reference) instead of the original
   shared solid bright-orange top border. */
body.home .site-footer,
body.service-page .site-footer {
    color: #C9D4DC;
    border-top: 1px solid rgba(168, 124, 73, 0.19);
}
body.home .site-footer__grid p,
body.service-page .site-footer__grid p {
    color: #A8BAC6;
    font-size: 15px;
}
body.home .site-footer__links a,
body.service-page .site-footer__links a {
    font-size: 14px;
}
/* Smaller than the eyebrow it's built from (.eyebrow/.eyebrow--rule,
   shared with every other section heading) -- the reference's own footer
   column headings are notably more compact. */
body.home .site-footer__heading,
body.service-page .site-footer__heading {
    font-size: 14px;
    line-height: 1.2;
    letter-spacing: 0.18em;
}
body.home .site-footer__bottom,
body.service-page .site-footer__bottom {
    font-size: 14px;
    color: #94A9B7;
}

/* ==============================================================================
   Home page (screenshot-driven redesign). Every class below is used on
   exactly one page (templates/web/home.html) and built from the tokens
   already declared in :root above -- no new colours. */

/* --- centred hero, exact client specification --------------------------------
   Every value below is pinned to a specific brief (colours, sizes, spacing)
   rather than derived from the site's usual tokens/clamp formulas, so this
   whole block is deliberately self-contained. Three places need their own
   override here instead of editing the shared rule directly, because that
   shared rule is also used elsewhere:
     - h1: body.home h1 (site.css above) is shared with body.service-page's
       own hero. #home h1 (ID beats that rule's specificity) overrides it
       for this hero only.
     - .btn: shared by every button on the site. The hero's CTA is its own
       .hero-cta (no .btn-primary), styled under #home below.
     - .hero-geo/.hero-lead/.hero-trust-*: already hero-only (not reused
       anywhere else), so these are edited directly. */
/* Dark banner pulled up under the transparent home header: --home-header-h
   is the header's measured height per logo breakpoint (86/81/74px, rounded
   up -- overshooting only tucks a few px of navy under the header).
   Layers, back to front: .hero-geo (the animated geometric background,
   below), then ::after darkening the centre so the white copy keeps its
   contrast whatever the background does behind it. */
.hero-centered {
    --home-header-h: 86px;
    position: relative;
    z-index: 0;
    overflow: hidden;
    display: flex;
    align-items: center;
    --hero-pad-top: clamp(32px, 6vh, 72px);
    --hero-pad-bottom: clamp(24px, 4.5vh, 48px);
    /* At least the viewport below the header, never under 640px of content. */
    min-height: max(100svh, calc(640px + var(--home-header-h)));
    margin-top: calc(-1 * var(--home-header-h));
    padding-top: calc(var(--home-header-h) + var(--hero-pad-top));
    padding-bottom: var(--hero-pad-bottom);
    background: #091E30;
}
/* The geometric background is one flat image (static/img/hero/hero_geo_*.webp,
   1024x572 source), so nothing in it can move on its own. What moves:
     - the stage: always the image's own aspect ratio, covering the hero
       (aspect-ratio + both min sizes, which the browser transfers across
       the ratio, i.e. CSS's own background-size:cover), 4% oversized so the
       parallax never shows an edge, with a very slow push-in;
     - ten blocks (.hero-geo__block--N, clip-path % of the stage = % of the
       image, each the outline of one block's top face plus its side): a tile
       (copy of the image) rises by --lift (2-5% of the stage height),
       holds, and settles back, each on its own 5-9s cycle. Under it a dark pit of the same shape covers the
       original, so the strip it uncovers while up reads as a taller side
       wall: the block is pushed up out of the surface. A light wash on the
       tile (::after) brightens it as it nears the light;
     - eight orange seams: SVG lines on the image's own orange edges (same
       1024x572 coordinates), a short bright dash travelling along each one
       and fading, on staggered cycles so only a few are ever lit. They sit
       above the tiles, so a raised block shows its seam glowing at the floor;
     - parallax: app.js sets --geo-x/--geo-y (-1..1) from the mouse, and the
       tile layer follows further than the base, for depth.
   Transform, opacity and stroke-dashoffset only: no animated filters or
   shadows, no layout. */
.hero-geo {
    position: absolute;
    inset: 0;
    z-index: -2;
    overflow: hidden;
    pointer-events: none;
}
.hero-geo__stage {
    position: absolute;
    top: 50%;
    left: 50%;
    min-width: 104%;
    min-height: 104%;
    aspect-ratio: 1024 / 572;
    translate: -50% -50%;
    animation: geo-push 26s ease-in-out infinite alternate;
}
.hero-geo__layer {
    position: absolute;
    inset: 0;
    transform: translate3d(calc(var(--geo-x, 0) * 8px), calc(var(--geo-y, 0) * 6px), 0);
    transition: transform 1.1s cubic-bezier(0.22, 1, 0.36, 1);
}
.hero-geo__layer--tiles {
    transform: translate3d(calc(var(--geo-x, 0) * 18px), calc(var(--geo-y, 0) * 13px), 0);
}
.hero-geo__plate,
.hero-geo__pit,
.hero-geo__tile {
    position: absolute;
    inset: 0;
}
.hero-geo__plate,
.hero-geo__tile {
    background: url("/static/img/hero/hero_geo_1024.01ba225981ce.webp") 0 0 / 100% 100% no-repeat;
}
.hero-geo__pit { background: linear-gradient(to bottom, #0B1B2B, #02070D); }
.hero-geo__tile {
    will-change: translate;
    animation: geo-rise var(--rise-dur) var(--rise-delay) infinite;
}
.hero-geo__tile::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(160deg, #FFFFFF2E, #FFFFFF00 55%);
    opacity: 0;
    animation: geo-rise-light var(--rise-dur) var(--rise-delay) infinite;
}
.hero-geo__block--1 { clip-path: polygon(1.04% 0%, 10.68% 15.39%, 10.83% 18.66%, 2.34% 30.04%, 0% 27.99%, 0% 0%); --lift: 5%; --rise-dur: 6s; --rise-delay: -2s; }
.hero-geo__block--2 { clip-path: polygon(6.77% 7.93%, 16.77% 23.13%, 17.6% 27.99%, 33.33% 8.86%, 33.33% 3.73%, 30.73% 0%, 13.02% 0%); --lift: 4%; --rise-dur: 7s; --rise-delay: -7s; }
.hero-geo__block--3 { clip-path: polygon(25.42% 19.12%, 36.35% 35.91%, 36.56% 37.5%, 53.65% 15.67%, 53.65% 11.94%, 44.27% 0%, 41.15% 0%); --lift: 4.5%; --rise-dur: 6.5s; --rise-delay: -4s; }
.hero-geo__block--4 { clip-path: polygon(80.73% 8.86%, 95.31% 24.72%, 95.42% 27.05%, 100% 20.06%, 100% 0%, 86.72% 0%); --lift: 5%; --rise-dur: 7.5s; --rise-delay: -9s; }
.hero-geo__block--5 { clip-path: polygon(75% 53.36%, 88.28% 70.9%, 95.83% 56.9%, 82.55% 41.04%); --lift: 3.5%; --rise-dur: 5.5s; --rise-delay: -1s; }
.hero-geo__block--6 { clip-path: polygon(71.09% 59.24%, 71.09% 61.57%, 83.59% 77.89%, 88.02% 71.08%, 75% 53.64%); --lift: 4.5%; --rise-dur: 6s; --rise-delay: -6s; }
.hero-geo__block--7 { clip-path: polygon(63.02% 73.69%, 63.02% 76.03%, 76.04% 93.28%, 83.33% 80.22%, 71.35% 61.1%); --lift: 4%; --rise-dur: 7s; --rise-delay: -3s; }
.hero-geo__block--8 { clip-path: polygon(0% 29.38%, 10.94% 44.78%, 11.2% 46.64%, 4.43% 56.44%, 3.12% 54.1%, 0% 48.51%); --lift: 4.5%; --rise-dur: 6.5s; --rise-delay: -8s; }
.hero-geo__block--9 { clip-path: polygon(0% 58.77%, 9.64% 66.42%, 10.42% 69.5%, 0% 83.02%); --lift: 4%; --rise-dur: 5s; --rise-delay: -5s; }
.hero-geo__block--10 { clip-path: polygon(51.82% 20.06%, 70.05% 44.59%, 43.23% 85.63%, 24.9% 55.97%); --lift: 2%; --rise-dur: 9s; --rise-delay: -11s; }
@keyframes geo-push {
    from { scale: 1; }
    to { scale: 1.035; }
}
/* Rest, rise (eased out, like a piston slowing at the top), hold, settle. */
@keyframes geo-rise {
    0%, 8% { translate: 0 0; animation-timing-function: cubic-bezier(0.45, 0, 0.2, 1); }
    40%, 56% { translate: 0 calc(-1 * var(--lift)); animation-timing-function: cubic-bezier(0.55, 0, 0.35, 1); }
    92%, 100% { translate: 0 0; }
}
@keyframes geo-rise-light {
    0%, 8% { opacity: 0; animation-timing-function: cubic-bezier(0.45, 0, 0.2, 1); }
    40%, 56% { opacity: 1; animation-timing-function: cubic-bezier(0.55, 0, 0.35, 1); }
    92%, 100% { opacity: 0; }
}
.hero-geo__lights {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    overflow: visible;
}
/* Each seam: a soft wide glow under a thin bright core, the same short dash
   on both (pathLength=100 in the markup, so the numbers are % of the seam). */
.hero-geo__seam line {
    fill: none;
    stroke-linecap: round;
    stroke-dasharray: 16 200;
    stroke-dashoffset: 16;
    opacity: 0;
    animation: geo-seam var(--seam-dur, 10s) ease-in-out var(--seam-delay, 0s) infinite;
}
.hero-geo__seam line:first-child { stroke: #FF650B; stroke-width: 5; }
.hero-geo__seam line:last-child { stroke: #FFD2A8; stroke-width: 1.4; }
.hero-geo__seam--1 { --seam-dur: 9s; --seam-delay: -1s; }
.hero-geo__seam--2 { --seam-dur: 11s; --seam-delay: -6s; }
.hero-geo__seam--3 { --seam-dur: 10s; --seam-delay: -3s; }
.hero-geo__seam--4 { --seam-dur: 12s; --seam-delay: -8s; }
.hero-geo__seam--5 { --seam-dur: 8s; --seam-delay: -2s; }
.hero-geo__seam--6 { --seam-dur: 13s; --seam-delay: -10s; }
.hero-geo__seam--7 { --seam-dur: 9.5s; --seam-delay: -5s; }
.hero-geo__seam--8 { --seam-dur: 14s; --seam-delay: -12s; }
@keyframes geo-seam {
    0% { stroke-dashoffset: 16; opacity: 0; }
    8%, 30% { opacity: 1; }
    40% { stroke-dashoffset: -100; opacity: 0; }
    100% { stroke-dashoffset: -100; opacity: 0; }
}
.hero-geo__seam line:first-child { animation-name: geo-seam-glow; }
@keyframes geo-seam-glow {
    0% { stroke-dashoffset: 16; opacity: 0; }
    8%, 30% { opacity: 0.35; }
    40% { stroke-dashoffset: -100; opacity: 0; }
    100% { stroke-dashoffset: -100; opacity: 0; }
}
.hero-centered::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background:
        linear-gradient(90deg, #091E30E0 0%, #091E30B0 38%, #091E3040 70%, #091E3010 100%),
        linear-gradient(to bottom, #091E3080 0%, #091E3000 20%, #091E3000 65%, #091E30CC 100%);
    pointer-events: none;
}
@media (min-width: 1025px), (min-width: 600px) and (min-resolution: 1.5dppx) {
    .hero-geo__plate,
    .hero-geo__tile { background-image: url("/static/img/hero/hero_geo_1920.6995bc10627b.webp"); }
}
/* Still frame: the plain image, no moving blocks or lights. */
@media (prefers-reduced-motion: reduce) {
    .hero-geo__stage { animation: none; }
    .hero-geo__pit,
    .hero-geo__tile,
    .hero-geo__lights { display: none; }
}
@media (max-width: 900px) {
    .hero-centered { --home-header-h: 81px; }
}
/* --- hero content -------------------------------------------------------------
   Left-aligned on the same 1280px grid as the header, so the headline starts
   on the logo's edge. Two zones: the copy, vertically centred in the space
   above, and the trust points on a hairline along the bottom of the hero.
   Inter throughout, solid colours only. */
.hero-centered .container.hero-stage {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    min-height: calc(max(100svh, 640px + var(--home-header-h)) - var(--home-header-h) - var(--hero-pad-top) - var(--hero-pad-bottom));
    text-align: left;
}
.hero-copy {
    max-width: 64rem;
    margin-block: auto;
}
/* Reserved for the V-shaped zoom animation and its background image (not built
   yet); empty, so it takes no space and draws nothing. */
.hero-visual { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.hero-visual:empty { display: none; }

#home .hero-title {
    margin: 0;
    font-family: var(--font-sans-new);
    font-weight: 700;
    /* min(): on short, wide screens (laptops) the height decides, so the
       whole hero, trust rail included, still fits one screen. */
    font-size: var(--fs-display);
    line-height: 1.05;
    letter-spacing: -0.038em;
    color: #FFFFFF;
}
#home .hero-title .text-accent { color: #FF6A14; }

.hero-lead {
    max-width: 36rem;
    margin: clamp(16px, 2.8svh, 28px) 0 0;
    font-size: clamp(1.0625rem, 0.98rem + 0.32vw, 1.1875rem);
    /* Bootstrap's .lead is weight 300: too thin over a busy background. */
    font-weight: 400;
    line-height: 1.6;
    color: #BAC6D2;
    text-wrap: pretty;
}

#home .hero-cta { margin-top: clamp(24px, 4svh, 40px); }

/* Trust rail: the four points as one strip along the bottom of the hero,
   under a hairline, each label on a single line, separated by short
   vertical rules. A thin orange bar runs along the hairline above one point
   at a time, left to right, lighting its label while it passes (below). */
.hero-trust {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    margin: clamp(28px, 5svh, 56px) 0 0;
    padding: 0;
    border-top: 1px solid #FFFFFF24;
}
.hero-trust__item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: clamp(14px, 2.6svh, 22px) 24px 0;
}
.hero-trust__item:first-child { padding-left: 0; }
.hero-trust__item + .hero-trust__item::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 2px;
    height: 20px;
    width: 1px;
    background: #FFFFFF1F;
}
.hero-trust__item::before {
    content: "";
    position: absolute;
    top: -1px;
    left: 0;
    right: 24px;
    height: 2px;
    background: #FF6A14;
    transform: scaleX(0);
    transform-origin: left center;
}
.hero-trust__item + .hero-trust__item::before { left: 24px; right: 24px; }
.hero-trust__icon {
    display: flex;
    flex-shrink: 0;
    color: #FF6A14;
}
.hero-trust__icon svg { width: 20px; height: 20px; }
.hero-trust__icon svg * { stroke-width: 1.75; }
.hero-trust__label {
    font-size: 14px;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    color: #C3CEDA;
    transition: color 0.3s ease;
}
@media (hover: hover) and (pointer: fine) {
    .hero-trust__item:hover .hero-trust__label { color: #FFFFFF; }
}

/* The hero copy and trust row are visible from the first paint (no fade-in,
   UI/UX review); only the trust points' bars cycle, once .is-visible is set.
   .hero-stage keeps [data-reveal] only for that hook (opacity forced on). */
@media (prefers-reduced-motion: no-preference) {
    #home .hero-stage[data-reveal] { opacity: 1; transform: none; transition: none; }

    /* One 12s cycle, 3s per point: the bar draws across in ~2.4s, then fades
       as the next one starts. Begins once the copy has landed. */
    #home .hero-stage.is-visible .hero-trust__item::before { animation: trust-bar 12s linear infinite backwards; }
    #home .hero-stage.is-visible .hero-trust__label { animation: trust-label 12s ease infinite backwards; }
    #home .hero-stage.is-visible .hero-trust__item:nth-child(1)::before,
    #home .hero-stage.is-visible .hero-trust__item:nth-child(1) .hero-trust__label { animation-delay: 1.2s; }
    #home .hero-stage.is-visible .hero-trust__item:nth-child(2)::before,
    #home .hero-stage.is-visible .hero-trust__item:nth-child(2) .hero-trust__label { animation-delay: 4.2s; }
    #home .hero-stage.is-visible .hero-trust__item:nth-child(3)::before,
    #home .hero-stage.is-visible .hero-trust__item:nth-child(3) .hero-trust__label { animation-delay: 7.2s; }
    #home .hero-stage.is-visible .hero-trust__item:nth-child(4)::before,
    #home .hero-stage.is-visible .hero-trust__item:nth-child(4) .hero-trust__label { animation-delay: 10.2s; }
}
@keyframes trust-bar {
    0% { transform: scaleX(0); opacity: 1; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); }
    20% { transform: scaleX(1); opacity: 1; }
    25%, 100% { transform: scaleX(1); opacity: 0; }
}
@keyframes trust-label {
    0% { color: #C3CEDA; }
    4%, 21% { color: #FFFFFF; }
    27%, 100% { color: #C3CEDA; }
}

@media (max-width: 900px) {
    .hero-trust { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 24px; border-top: 0; }
    .hero-trust__item,
    .hero-trust__item:first-child { padding: 16px 0; border-top: 1px solid #FFFFFF24; }
    .hero-trust__item + .hero-trust__item::after { display: none; }
    .hero-trust__item::before,
    .hero-trust__item + .hero-trust__item::before { left: 0; right: 0; }
    /* Two lines in the narrower grid cells: one word per line. */
    .hero-trust__label > span { display: block; }
}
@media (max-width: 600px) {
    .hero-centered { --home-header-h: 74px; --hero-pad-top: 24px; --hero-pad-bottom: 16px; }
    #home .hero-title { font-size: var(--fs-display); line-height: 1.08; letter-spacing: -0.035em; }
    #home .hero-title br { display: none; }
    .hero-lead { font-size: 16px; }
    .hero-trust { column-gap: 16px; }
    .hero-trust__item,
    .hero-trust__item:first-child { gap: 10px; padding-block: 14px; }
    .hero-trust__icon svg { width: 18px; height: 18px; }
    .hero-trust__label { font-size: 14px; }
}

/* --- primary CTA (.btn-cta) -----------------------------------------------------
   The two calls to action that matter most: the hero's "Explore Our
   Solutions" and the header's "Discuss Your Project". A squared-off split
   button: the label, then the arrow in its own darker cell, so it reads as
   a control rather than a pill. On hover the label rolls up to a copy of
   itself (::after, from data-label, kept out of the accessible name with
   the "/ ''" alt text) and the arrow travels out to the right and back in
   from the left. Nothing moves while idle. */
body .btn.btn-cta {
    --cta-h: 52px;
    --cta-bg: #FF650B;
    --cta-cell: #E25706;
    --bs-btn-padding-y: 0;
    --bs-btn-padding-x: 0;
    position: relative;
    display: inline-flex;
    align-items: stretch;
    gap: 0;
    min-height: var(--cta-h);
    padding: 0;
    overflow: hidden;
    border: 0;
    border-radius: 6px;
    background: var(--cta-bg);
    color: #FFFFFF;
    font-family: var(--font-sans-new);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.005em;
    line-height: 1;
    box-shadow: none;
    transition: background-color 0.25s ease;
}
body .btn.btn-cta--sm { --cta-h: 46px; font-size: 14px; }
/* Button system (UI/UX review): one height, one radius, one weight.
     .btn-cta            primary, solid orange
     .btn-cta--ghost     secondary, navy outline (--ghost-light on dark bands)
     .text-link          tertiary, a plain link
   Only the three key actions carry the arrow cell (arrow=True in
   btn_cta_inner.html); without it the label gets even side padding. */
.btn-cta__label:only-child { padding-inline: 26px; }
body .btn.btn-cta { font-weight: 600; }
.text-link { display: inline-flex; align-items: center; min-height: 44px; color: var(--color-ink); font-weight: 600; text-decoration: underline; text-decoration-color: rgba(255, 101, 11, 0.55); text-underline-offset: 5px; text-decoration-thickness: 1.5px; }
.text-link:hover { color: #CC4D03; text-decoration-color: currentColor; }
@media (max-width: 768px) {
    body .btn.btn-cta, body .btn.btn-cta--sm { --cta-h: 48px; }
    .btn { min-height: 44px; }
}
/* Outline variants for the second action beside a primary one: --ghost on
   light backgrounds (navy hairline, fills navy on hover), --ghost-light on
   the orange and navy bands (white hairline, fills white on hover). The
   arrow cell keeps its own divider instead of a darker fill. */
body .btn.btn-cta--ghost { --cta-bg: transparent; --cta-cell: transparent; color: #0A1D2A; box-shadow: inset 0 0 0 1.5px rgba(10, 29, 42, 0.24); transition: background-color 0.25s ease, color 0.25s ease, box-shadow 0.25s ease; }
body .btn.btn-cta--ghost > span.btn-cta__icon[aria-hidden] { box-shadow: inset 1.5px 0 0 rgba(10, 29, 42, 0.18); }
body .btn.btn-cta--ghost-light { --cta-bg: transparent; --cta-cell: transparent; color: #FFFFFF; box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.6); transition: background-color 0.25s ease, color 0.25s ease, box-shadow 0.25s ease; }
body .btn.btn-cta--ghost-light > span.btn-cta__icon[aria-hidden] { box-shadow: inset 1.5px 0 0 rgba(255, 255, 255, 0.4); }
@media (hover: hover) and (pointer: fine) {
    body .btn.btn-cta.btn-cta--ghost:hover { --cta-bg: #0A1D2A; --cta-cell: #15304A; color: #FFFFFF; box-shadow: none; }
    body .btn.btn-cta.btn-cta--ghost-light:hover { --cta-bg: #FFFFFF; --cta-cell: #F3EEE8; color: #0A1D2A; box-shadow: none; }
}
.btn-cta__label {
    position: relative;
    display: grid;
    flex: 1 1 auto;
    align-items: center;
    justify-items: center;
    padding-inline: 22px 20px;
    overflow: hidden;
}
.btn-cta__label > span,
.btn-cta__label::after {
    grid-area: 1 / 1;
    transition: transform 0.45s cubic-bezier(0.65, 0, 0.35, 1);
}
.btn-cta__label::after {
    content: attr(data-label);
    content: attr(data-label) / "";
    transform: translateY(var(--cta-h));
}
/* span[aria-hidden] matches (and so outranks) the home-wide arrow-nudge
   rule on body.home .btn > span[aria-hidden="true"]. */
body .btn.btn-cta > span.btn-cta__icon[aria-hidden] {
    position: relative;
    display: grid;
    place-items: center;
    width: var(--cta-h);
    flex-shrink: 0;
    overflow: hidden;
    background: var(--cta-cell);
    transform: none;
    transition: background-color 0.25s ease;
}
.btn-cta__icon svg { width: 16px; height: 16px; }
body .btn.btn-cta:focus-visible { outline: 2px solid #FFFFFF; outline-offset: 3px; box-shadow: 0 0 0 5px #FF650B; }
body .btn.btn-cta:active { transform: translateY(1px); }
@media (hover: hover) and (pointer: fine) {
    body .btn.btn-cta:hover { --cta-bg: #F25C04; --cta-cell: #CC4D03; color: #FFFFFF; background: var(--cta-bg); transform: none; box-shadow: none; }
    body .btn.btn-cta:hover > span.btn-cta__icon[aria-hidden] { transform: none; }
    .btn-cta:hover .btn-cta__label > span { transform: translateY(calc(-1 * var(--cta-h))); }
    .btn-cta:hover .btn-cta__label::after { transform: translateY(0); }
    .btn-cta:hover .btn-cta__icon svg { animation: cta-arrow 0.5s cubic-bezier(0.65, 0, 0.35, 1); }
}
@keyframes cta-arrow {
    0% { transform: translateX(0); }
    45% { transform: translateX(28px); }
    46% { transform: translateX(-28px); }
    100% { transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
    .btn-cta:hover .btn-cta__label > span,
    .btn-cta:hover .btn-cta__label::after { transform: none; transition: none; }
    .btn-cta__label::after { display: none; }
    .btn-cta:hover .btn-cta__icon svg { animation: none; }
}
@media (max-width: 600px) {
    body .btn.btn-cta.hero-cta { --cta-h: 54px; }
}

/* --- homepage intro (V reveal) ------------------------------------------------
   Nothing here shows unless intro-gate.js put .intro-play on <html> before
   first paint (first visit this session, motion allowed); intro.js then
   draws the logo SVG into [data-intro] and drives it, adds .intro-released
   when the hero copy should come in, and removes both classes at the end.
   The page itself is fully rendered underneath the whole time. While it
   plays: scroll is held, the header logo is hidden (the intro's logo glides
   into its place), and the hero copy waits so it can arrive after the logo. */
.valin-intro,
.valin-intro__skip { display: none; }
html.intro-play { overflow: hidden; }
html.intro-play .valin-intro {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 1090;
    background: #091E30;
    transition: opacity 0.35s var(--ease);
}
/* At the hand-off the SVG's own navy veil (with the V-shaped hole) takes
   over from the plain background, so the veil can fade while the logo stays. */
html.intro-play .valin-intro.is-drawn { background: transparent; }
html.intro-play .valin-intro.is-leaving { opacity: 0; pointer-events: none; }
.valin-intro svg { position: absolute; inset: 0; display: block; width: 100%; height: 100%; color: #F5F8FA; }
html.intro-play .valin-intro__skip {
    display: inline-flex;
    align-items: center;
    position: fixed;
    z-index: 1091;
    right: 24px;
    bottom: 24px;
    min-height: 40px;
    padding: 0 18px;
    border: 1px solid #FFFFFF59;
    border-radius: 40px;
    background: #091E3099;
    color: #FFFFFF;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.02em;
    transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease), opacity 0.3s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
    html.intro-play .valin-intro__skip:hover { background: #FF650B; border-color: #FF650B; }
}
html.intro-play .valin-intro__skip.is-leaving { opacity: 0; pointer-events: none; }
html.intro-play .site-brand img { visibility: hidden; }
html.intro-play:not(.intro-released) #home [data-reveal]:not(.hero-stage),
html.intro-play:not(.intro-released) #home [data-reveal-group] > * {
    opacity: 0;
    transform: translateY(12px);
}
html.intro-play:not(.intro-released) #home .hero-trust__item::before,
html.intro-play:not(.intro-released) #home .hero-trust__label { animation: none; }
@media (max-width: 600px) {
    html.intro-play .valin-intro__skip { right: 16px; bottom: 16px; }
}

/* --- solutions: bento -------------------------------------------------------------
   One grid holding the four services and three photo tiles. The selected
   service (.is-active) is the tall navy panel on the left: its photo on top
   (duotoned into the navy), then number/tag, title, description and link.
   The other three are light tiles with their line schematic (partials/
   solution_art.html), title and "Explore solution +"; they auto-place into
   the cells the photos leave free, so selecting another service re-flows
   the grid and app.js animates the move (FLIP). Hovering a tile replays its
   schematic. Below 992px: the panel on top, tiles two to a row. */
.sol-bento {
    --sol-ease: cubic-bezier(0.65, 0, 0.35, 1);
    --sol-row: clamp(210px, 27svh, 280px);
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) repeat(3, minmax(0, 1fr));
    grid-template-rows: repeat(2, var(--sol-row));
    gap: 14px;
}
.sol-card.is-active { grid-column: 1; grid-row: 1 / span 2; }
.sol-photo--1 { grid-column: 2; grid-row: 1; }
.sol-photo--2 { grid-column: 3; grid-row: 1; }
.sol-photo--3 { grid-column: 4; grid-row: 2; }

/* Photo tiles: cool, near-monochrome, so the set reads as one series. */
.sol-photo {
    position: relative;
    overflow: hidden;
    border-radius: 4px;
    background: #091E30;
}
.sol-photo img,
.sol-card__media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: grayscale(0.85) contrast(1.05) brightness(0.8);
}
/* Framing for the Protect stand-in photo: its monitor sits at the right. */
.sol-card:nth-child(4) .sol-card__media img { object-position: 85% 50%; }
.sol-photo::after {
    content: "";
    position: absolute;
    inset: 0;
    background: #0A2A4733;
    mix-blend-mode: multiply;
}

/* --- service card: tile state (default) --- */
.sol-card {
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    overflow: hidden;
    border: 1px solid #DFE5EB;
    border-radius: 4px;
    background: #FFFFFF;
    transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.sol-card__media,
.sol-card__detail { display: none; }
.sol-card .svc-art {
    position: absolute;
    top: 14px;
    right: 14px;
    width: 42%;
    max-width: 150px;
    pointer-events: none;
}
/* Tiles narrower than 240px (smaller laptops) have no room for the drawing
   beside the icon and tag: the icon alone identifies the service there. */
.sol-card { container-type: inline-size; }
@container (max-width: 240px) {
    .sol-card .svc-art { display: none; }
}
.sol-card__trigger {
    position: relative;
    display: flex;
    flex: 1;
    flex-direction: column;
    align-items: flex-start;
    width: 100%;
    padding: 22px;
    border: 0;
    background: none;
    color: inherit;
    text-align: left;
    cursor: pointer;
}
.sol-card__trigger:focus-visible { outline: 2px solid #FF650B; outline-offset: -3px; }
.sol-card__meta {
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #536474;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* The service's icon (partials/solution_icon.html) leads the tag. */
.sol-card__meta { display: inline-flex; align-items: center; gap: 10px; }
.sol-icon {
    width: 20px;
    height: 20px;
    flex-shrink: 0;
    overflow: visible;
    color: #CF4B00;
}
.sol-card.is-active .sol-icon { color: #FF7A2E; }
.sol-icon * {
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.sol-icon .sol-icon__led { fill: currentColor; stroke: none; opacity: 0.35; }
.sol-icon__left,
.sol-icon__right,
.sol-icon__tip,
.sol-icon__shackle { transform-box: fill-box; }
.sol-icon__tip { transform-origin: 100% 0; }
/* Each icon's own move: on a hovered or focused tile, and whenever its
   service opens in the panel (re-adding .is-active restarts it). */
@media (prefers-reduced-motion: no-preference) {
    .sol-card:is(:hover, :focus-within, .is-active) .sol-icon__draw { animation: sol-icon-draw 0.7s cubic-bezier(0.45, 0, 0.25, 1) 0.15s backwards; stroke-dasharray: 1; }
    .sol-card:is(:hover, :focus-within, .is-active) .sol-icon__left { animation: sol-icon-left 0.7s var(--ease) 0.1s backwards; }
    .sol-card:is(:hover, :focus-within, .is-active) .sol-icon__right { animation: sol-icon-right 0.7s var(--ease) 0.1s backwards; }
    .sol-card:is(:hover, :focus-within, .is-active) .sol-icon__tip { animation: sol-icon-tip 0.45s cubic-bezier(0.3, 1.6, 0.5, 1) 0.7s backwards; }
    .sol-card:is(:hover, :focus-within, .is-active) .sol-icon__led { animation: sol-icon-led 1.8s ease-in-out infinite; }
    /* nth-of-type counts circles only: the three lights are circles 1-3. */
    .sol-card:is(:hover, :focus-within, .is-active) .sol-icon__led:nth-of-type(2) { animation-delay: 0.3s; }
    .sol-card:is(:hover, :focus-within, .is-active) .sol-icon__led:nth-of-type(3) { animation-delay: 0.6s; }
    .sol-card:is(:hover, :focus-within, .is-active) .sol-icon__shackle { animation: sol-icon-shackle 0.7s cubic-bezier(0.3, 1.5, 0.5, 1) 0.1s backwards; }
}
@keyframes sol-icon-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes sol-icon-left { from { transform: translateX(2.5px); opacity: 0.4; } to { transform: none; opacity: 1; } }
@keyframes sol-icon-right { from { transform: translateX(-2.5px); opacity: 0.4; } to { transform: none; opacity: 1; } }
@keyframes sol-icon-tip { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes sol-icon-led { 0%, 100% { opacity: 0.35; } 15%, 35% { opacity: 1; } }
@keyframes sol-icon-shackle { from { transform: translateY(-3px); } to { transform: none; } }
.sol-card__title {
    margin-top: auto;
    max-width: 15rem;
    font-family: var(--font-sans-new);
    font-size: clamp(1.0625rem, 0.85rem + 0.45vw, 1.25rem);
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.02em;
    color: #091E30;
}
/* White (closed) cards: no "Explore solution" text. A small outlined plus
   sits in the bottom-right corner as the open cue, over a fine dot field
   that fades out from that corner; on hover the dots warm to orange and
   the plus turns and fills navy. */
.sol-card__plus {
    position: absolute;
    right: 18px;
    bottom: 18px;
    z-index: 1;
    width: 34px;
    height: 34px;
    border: 1px solid #C9D3DC;
    border-radius: 50%;
    color: #091E30;
    background: #FFFFFF;
    transition: transform 0.4s var(--ease), background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}
.sol-card__plus::before,
.sol-card__plus::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 12px;
    height: 1.5px;
    margin: -0.75px 0 0 -6px;
    background: currentColor;
}
.sol-card__plus::after { transform: rotate(90deg); }
.sol-card.is-active .sol-card__plus { display: none; }
/* keep the title clear of the corner plus */
.sol-card:not(.is-active) .sol-card__title { padding-right: 46px; }
.sol-card:not(.is-active)::after {
    content: "";
    position: absolute;
    right: 0;
    bottom: 0;
    width: 62%;
    height: 70%;
    pointer-events: none;
    background-image: radial-gradient(circle, rgba(9, 30, 48, 0.16) 1.1px, transparent 1.5px);
    background-size: 14px 14px;
    background-position: right 4px bottom 4px;
    -webkit-mask-image: radial-gradient(circle at 100% 100%, #000 0%, transparent 72%);
    mask-image: radial-gradient(circle at 100% 100%, #000 0%, transparent 72%);
    transition: opacity 0.3s ease;
}
.sol-card:not(.is-active):hover::after { background-image: radial-gradient(circle, rgba(255, 101, 11, 0.35) 1.1px, transparent 1.5px); }
@media (hover: hover) and (pointer: fine) {
    .sol-card:not(.is-active):hover { border-color: #091E30; box-shadow: 0 18px 40px -28px #091E3066; }
    .sol-card:not(.is-active):hover .sol-card__plus { transform: rotate(90deg); border-color: #091E30; background: #091E30; color: #FFFFFF; }
}

/* --- service card: selected (the tall panel) --- */
.sol-card.is-active { border-color: #091E30; background: #091E30; color: #FFFFFF; }
.sol-card.is-active::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 2;
    height: 3px;
    background: #FF650B;
    transform-origin: left center;
}
/* Auto-cycle (app.js adds .is-auto on desktop): the bar fills over 7s on a
   faint track as the panel's timer; its animationend selects the next
   service. Held while the pointer or focus is in the grid, or it's off
   screen (.is-offscreen). */
.sol-bento.is-auto .sol-card.is-active { box-shadow: inset 0 3px 0 #FFFFFF29; }
.sol-bento.is-auto .sol-card.is-active::before { animation: sol-timer 7s linear forwards; }
.sol-bento.is-auto:hover .sol-card.is-active::before,
.sol-bento.is-auto:focus-within .sol-card.is-active::before,
.sol-bento.is-auto.is-offscreen .sol-card.is-active::before { animation-play-state: paused; }
@keyframes sol-timer { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.sol-card.is-active .svc-art,
.sol-card.is-active .sol-card__media {
    position: relative;
    display: block;
    flex: 1 1 auto;
    min-height: 0;
    /* The photo drifts from scale(1.08): clip it, or its scaled edge shows
       as a light line below the fade, over the tag. */
    overflow: hidden;
}
.sol-card.is-active .sol-card__media::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom, #091E3026 0%, #091E3000 40%, #091E30 97%);
}
.sol-card.is-active .sol-card__trigger { flex: none; padding: 0 clamp(24px, 2.4vw, 36px); cursor: default; }
.sol-card.is-active .sol-card__meta { color: #C3CEDA; }
.sol-card.is-active .sol-card__title {
    max-width: 24rem;
    margin-top: 12px;
    font-size: clamp(1.5rem, 1.1rem + 0.9vw, 2rem);
    line-height: 1.15;
    letter-spacing: -0.03em;
    color: #FFFFFF;
}
.sol-card.is-active .sol-card__detail {
    display: block;
    padding: 14px clamp(24px, 2.4vw, 36px) clamp(24px, 2.4vw, 34px);
}
/* Code typed into the panel's photo area on click (app.js typeSolCode):
   inside .sol-card__media, so the frame clips it and the frame's navy fade
   (::after, painted over it) dissolves its lower lines before the tag.
   Blurred and low contrast so it reads as texture, not content. A caret
   blinks while it types; .is-out fades it. */
/* While the code types the photo dims to a faint layer under it
   (.is-coding, app.js); when the code blurs out, the photo returns over
   the same 1.1s, so the two crossfade with no gap. */
.sol-card__media img { transition: opacity 1.1s ease-in-out; }
.sol-card.is-coding .sol-card__media img { opacity: 0.16; transition-duration: 0.4s; }
.sol-code {
    position: absolute;
    top: clamp(20px, 2vw, 28px);
    left: clamp(24px, 2.4vw, 36px);
    right: clamp(24px, 2.4vw, 36px);
    bottom: 18px;
    margin: 0;
    overflow: hidden;
    font-family: var(--font-mono);
    font-size: 11.5px;
    line-height: 1.6;
    /* Its own fade at the foot, on top of the frame's, so the last lines
       never meet the tag even when the panel is short. */
    -webkit-mask-image: linear-gradient(to bottom, #000 65%, transparent);
    mask-image: linear-gradient(to bottom, #000 65%, transparent);
    white-space: pre;
    color: #B9CCDE;
    opacity: 0.6;
    filter: blur(0.5px);
    pointer-events: none;
    transition: opacity 1.1s ease-in-out, filter 1.1s ease-in-out;
}
.sol-code.is-typing::after {
    content: "";
    display: inline-block;
    width: 7px;
    height: 13px;
    margin-left: 2px;
    vertical-align: -2px;
    background: #FF7A2E;
    animation: svc-caret 0.8s steps(1) infinite;
}
.sol-code.is-out { opacity: 0; filter: blur(4px); }
.sol-card__detail p {
    max-width: 26rem;
    margin: 0;
    font-size: 16px;
    line-height: 1.6;
    color: #C3CEDA;
}
.sol-card__link {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    min-height: 44px;
    margin-top: 20px;
    padding: 0 16px;
    border: 1px solid #FFFFFF66;
    border-radius: 6px;
    color: #FFFFFF;
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}
.sol-card__link svg { width: 16px; height: 16px; transition: transform 0.35s var(--ease); }
.sol-card__link:focus-visible { outline: 2px solid #FFFFFF; outline-offset: 3px; }
@media (hover: hover) and (pointer: fine) {
    .sol-card__link:hover { background: #FFFFFF; border-color: #FFFFFF; color: #091E30; }
    .sol-card__link:hover svg { transform: translateX(3px); }
}

/* --- line schematics (inside the light tiles) --- */
.svc-art { height: auto; }
.svc-art * {
    stroke-width: 1.4;
    stroke-linecap: round;
    stroke-linejoin: round;
    vector-effect: non-scaling-stroke;
}
.svc-art .s { stroke: #8FA3B6; }
.svc-art .a { stroke: #FF6A14; }
.svc-art .g { stroke: #DCE3EA; stroke-dasharray: 3 5; }
.svc-art__caret { stroke: #FF6A14; stroke-width: 2; opacity: 0; }
.svc-art__led { fill: #FF6A14; opacity: 0.25; }
.svc-art__dot { fill: #FF6A14; }
.svc-art__scan { stroke: #FF6A14; stroke-width: 2; opacity: 0; transform-box: view-box; transform-origin: 160px 120px; }
.svc-art__flow { stroke: #FF6A14; stroke-width: 2; stroke-dasharray: 3 14; opacity: 0; }
.svc-art .bar { transform-box: fill-box; transform-origin: 50% 100%; }
.svc-art .unit,
.svc-art__piece,
.svc-art .shackle { transform-box: fill-box; }

@media (prefers-reduced-motion: no-preference) {
    /* Scroll-in: the cells rise in turn (panel, photos, tiles), then the
       schematics draw themselves, structure first, orange accent last. */
    #solutions .sol-bento[data-reveal] { opacity: 1; transform: none; transition: none; }
    .sol-bento > * { opacity: 0; transform: translateY(18px); transition: opacity 0.7s ease, transform 0.9s var(--ease), border-color 0.3s ease, box-shadow 0.3s ease; }
    .sol-bento.is-visible > * { opacity: 1; transform: none; }
    .sol-bento.is-visible > .sol-photo--1 { transition-delay: 0.08s; }
    .sol-bento.is-visible > .sol-photo--2 { transition-delay: 0.16s; }
    .sol-bento.is-visible > .sol-card:nth-child(2) { transition-delay: 0.22s; }
    .sol-bento.is-visible > .sol-card:nth-child(3) { transition-delay: 0.28s; }
    .sol-bento.is-visible > .sol-card:nth-child(4) { transition-delay: 0.34s; }
    .sol-bento.is-visible > .sol-photo--3 { transition-delay: 0.4s; }
    .sol-photo img { transform: scale(1.12); transition: transform 1.6s var(--ease); }
    .sol-bento.is-visible .sol-photo img { transform: scale(1); }
    .svc-art .s,
    .svc-art .a { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 1.4s cubic-bezier(0.45, 0, 0.2, 1) 0.6s; }
    .svc-art .a { transition-duration: 1s; transition-delay: 1.4s; }
    .svc-art .g,
    .svc-art__dot { opacity: 0; transition: opacity 1s ease 1.2s; }
    .sol-bento.is-visible .svc-art .s,
    .sol-bento.is-visible .svc-art .a { stroke-dashoffset: 0; }
    .sol-bento.is-visible .svc-art .g,
    .sol-bento.is-visible .svc-art__dot { opacity: 1; }

    /* The selected panel's photo drifts in very slowly; the photo tiles
       keep a slower drift going so the grid never sits completely still. */
    .sol-card.is-active .sol-card__media img { animation: sol-drift 14s ease-out both; }
    .sol-bento.is-visible .sol-photo img { animation: sol-pan 22s ease-in-out 1.6s infinite alternate; }
    .sol-bento.is-visible .sol-photo--2 img { animation-delay: 4s; animation-duration: 26s; }
    .sol-bento.is-visible .sol-photo--3 img { animation-delay: 8s; animation-duration: 24s; }

    /* Hovering (or focusing) a tile replays its schematic: the outline
       redraws, then each drawing's own move, and its accent loops. */
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .s { animation: svc-draw 0.9s cubic-bezier(0.45, 0, 0.2, 1) backwards; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .a { animation: svc-draw 0.8s cubic-bezier(0.45, 0, 0.2, 1) 0.5s backwards; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art__piece { animation: svc-slot 0.8s var(--ease) 0.45s backwards; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .bar { animation: svc-bar 0.7s var(--ease) backwards; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .bar:nth-of-type(2) { animation-delay: 0.06s; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .bar:nth-of-type(3) { animation-delay: 0.12s; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .bar:nth-of-type(4) { animation-delay: 0.18s; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .bar:nth-of-type(5) { animation-delay: 0.24s; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .unit { animation: svc-unit 0.6s var(--ease) backwards; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .unit:nth-of-type(3) { animation-delay: 0.08s; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .unit:nth-of-type(4) { animation-delay: 0.16s; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .unit:nth-of-type(5) { animation-delay: 0.24s; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art .shackle { animation: svc-shackle 0.8s cubic-bezier(0.3, 1.4, 0.5, 1) 0.3s backwards; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art__caret { animation: svc-caret 1.1s steps(1) infinite; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art__led { animation: svc-led 3.2s ease-in-out infinite; }
    /* nth-of-type counts every <circle>: the four LEDs are circles 5-8. */
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art__led:nth-of-type(6) { animation-delay: 0.8s; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art__led:nth-of-type(7) { animation-delay: 1.6s; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art__led:nth-of-type(8) { animation-delay: 2.4s; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art__dot { animation: svc-dot 2.4s ease-in-out infinite 0.8s; transform-box: fill-box; transform-origin: center; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art__flow { opacity: 1; animation: svc-flow 1.6s linear infinite 0.6s backwards; }
    .sol-card:not(.is-active):is(:hover, :focus-within) .svc-art__scan { opacity: 1; animation: svc-scan 6s linear infinite 0.6s backwards; }
}
@keyframes sol-drift { from { transform: scale(1.08); } to { transform: scale(1); } }
@keyframes sol-pan { from { transform: scale(1) translate(0, 0); } to { transform: scale(1.08) translate(-2%, -1.5%); } }
@keyframes svc-caret { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
@keyframes svc-led { 0%, 100% { opacity: 0.25; } 12%, 30% { opacity: 1; } }
@keyframes svc-dot { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.6); opacity: 0.55; } }
@keyframes svc-scan { to { transform: rotate(360deg); } }
@keyframes svc-flow { to { stroke-dashoffset: -17; } }
@keyframes svc-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes svc-slot { from { transform: translate(-18px, 10px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes svc-bar { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes svc-unit { from { transform: translateX(26px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes svc-shackle { from { transform: translateY(-12px); } to { transform: none; } }

/* Below 992px: the selected panel across the top, then the three tiles and
   one photo two to a row. */
@media (max-width: 991.98px) {
    .sol-bento { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: none; grid-auto-rows: minmax(190px, auto); }
    .sol-card.is-active { grid-column: 1 / -1; grid-row: 1; min-height: 440px; }
    .sol-photo--1 { grid-column: 2; grid-row: 3; }
    .sol-photo--2,
    .sol-photo--3 { display: none; }
}
@media (max-width: 575.98px) {
    .sol-bento { gap: 10px; grid-auto-rows: minmax(176px, auto); }
    .sol-card__trigger { padding: 16px; }
    /* Under the number/tag line, which needs the tile's full width here. */
    .sol-card .svc-art { top: 38px; right: 12px; width: 40%; }
    .sol-card__title { font-size: 15px; }
    .sol-card.is-active { min-height: 420px; }
}

/* --- "why Valin" section background + heading, exact client spec --------
   #why (not .section--alt, which is shared with #approach) so this is the
   only section painted with this background. #why h2 (ID beats the shared
   body.home h2 rule's specificity) so only this heading gets the client's
   own size/weight/line-height/letter-spacing/colour. */
#why { background: #F8F6F2; }
/* Reference's own exact eyebrow-to-heading gap for this section (the
   shared clamp landed at 20px, close but not exact). */
#why .eyebrow { margin-bottom: 22px; }
#why h2 {
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1.13;
    letter-spacing: -0.045em;
    color: #091E30;
    /* Zeroes the shared body.home h2 margin-bottom (a clamp, ~28px at
       desktop) -- the reference's own h2 here carries none; the gap down to
       the first paragraph comes entirely from that paragraph's own
       margin-top (22px, set just below) rather than from the heading. Left
       unreset, the two would collapse to whichever is larger (28px) instead
       of the reference's 22px. */
    margin-bottom: 0;
}
@media (max-width: 991.98px) {
    #why h2 { font-size: var(--fs-h2); }
}

/* --- "why Valin": brief to solution --------------------------------------------
   A project card (templates/web/home.html, [data-why-brief]) on a blueprint
   grid that fades out towards the copy. While in view, app.js ("why Valin")
   loops it through data-step:
     1 the brief's three fields type in       (Brief stage)
     2 a scan bar runs: "Analysing priorities" (Recommend stage)
     3 the five services are added one by one, each lit (.is-on) together
       with the matching phrase in the paragraph (shared data-sys-key)
     4 "Plan ready", then a fade and a fresh start (Plan stage)
   The markup holds the finished card, which is what reduced motion and
   no-JS see. Type is em off a cqi base so the card scales with its column. */
#why { position: relative; overflow: hidden; }
#why > .container { position: relative; z-index: 1; }
.why-grid {
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(#091E300F 1px, transparent 1px),
        linear-gradient(90deg, #091E300F 1px, transparent 1px);
    background-size: 32px 32px;
    -webkit-mask-image: radial-gradient(ellipse 48% 75% at 26% 50%, #000 25%, transparent 78%);
    mask-image: radial-gradient(ellipse 48% 75% at 26% 50%, #000 25%, transparent 78%);
    pointer-events: none;
}
.why-visual { position: relative; }
.why-visual__tags {
    display: flex;
    flex-wrap: wrap;
    row-gap: 10px;
    justify-content: center;
    gap: clamp(18px, 3vw, 36px);
    margin-top: 8px;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: #536474;
}
.why-visual__tags li { display: inline-flex; align-items: center; gap: 10px; white-space: nowrap; }
.why-visual__tags li::before { content: ""; width: 6px; height: 6px; background: #FF650B; }

.why-brief { position: relative; container-type: inline-size; perspective: 1500px; padding: 3% 4% 5% 2%; }
.why-brief__win {
    position: relative;
    font-size: clamp(9px, 2.45cqi, 14px);
    color: #0A1D2A;
    background: #FFFFFF;
    border-radius: 1em;
    overflow: hidden;
    transform: rotateY(12deg) rotateX(5deg) rotateZ(-0.6deg);
    transform-origin: 60% 50%;
    box-shadow: 0 0 0 1px rgba(10, 29, 42, 0.07), 0 3em 5em -2.4em rgba(10, 29, 42, 0.38), 0 0.8em 1.6em -1em rgba(10, 29, 42, 0.2);
    transition: transform 0.8s var(--ease), opacity 0.4s ease;
}
@media (hover: hover) and (pointer: fine) { .why-brief:hover .why-brief__win { transform: rotateY(6deg) rotateX(2.5deg); } }
.why-brief__bar { display: flex; align-items: center; gap: 0.9em; padding: 0.8em 1.1em; border-bottom: 1px solid rgba(10, 29, 42, 0.08); background: #FBF9F6; }
.why-brief__dots { display: flex; gap: 0.38em; }
.why-brief__dots i { width: 0.6em; height: 0.6em; border-radius: 50%; background: rgba(10, 29, 42, 0.15); }
.why-brief__title { font-weight: 700; }
.why-brief__steps { display: flex; gap: 0.3em; margin: 0 0 0 auto; padding: 0; list-style: none; font-size: 0.82em; font-weight: 600; }
.why-brief__steps li { padding: 0.3em 0.75em; border-radius: 1em; color: rgba(10, 29, 42, 0.45); background: rgba(10, 29, 42, 0.05); transition: background-color 0.3s ease, color 0.3s ease; }
.why-brief__steps li:last-child,
.why-brief[data-stage="1"] .why-brief__steps li[data-brief-stage="1"],
.why-brief[data-stage="2"] .why-brief__steps li[data-brief-stage="2"] { color: #FFFFFF; background: #FF650B; }
.why-brief[data-stage] .why-brief__steps li:last-child { color: rgba(10, 29, 42, 0.45); background: rgba(10, 29, 42, 0.05); }
.why-brief[data-stage="3"] .why-brief__steps li[data-brief-stage="3"] { color: #FFFFFF; background: #FF650B; }
.why-brief__sec { padding: 1em 1.2em 0.4em; }
.why-brief__head { display: block; margin-bottom: 0.6em; font-size: 0.78em; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: rgba(10, 29, 42, 0.5); }
.why-brief__field { display: grid; grid-template-columns: 7.2em minmax(0, 1fr); align-items: center; gap: 0.6em; padding: 0.5em 0.7em; margin-bottom: 0.4em; border-radius: 0.55em; border: 1px solid rgba(10, 29, 42, 0.1); }
.why-brief__field span { font-size: 0.85em; color: rgba(10, 29, 42, 0.55); }
.why-brief__field b { min-height: 1.35em; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.why-brief__field b.is-typing::after { content: ""; display: inline-block; width: 0.08em; height: 1.05em; margin-left: 0.1em; vertical-align: -0.15em; background: #FF650B; animation: ai-demo-caret 0.8s steps(1) infinite; }
.why-brief__scan { position: relative; display: flex; align-items: center; gap: 0.7em; margin: 0.5em 1.2em 0; padding: 0.55em 0.8em; border-radius: 0.55em; background: #FFF3EB; color: #B6480B; font-size: 0.85em; font-weight: 600; overflow: hidden; }
.why-brief__scan i { flex: 1; height: 0.3em; border-radius: 1em; background: rgba(255, 101, 11, 0.18); position: relative; overflow: hidden; }
.why-brief__scan i::after { content: ""; position: absolute; inset: 0; background: #FF650B; transform-origin: left; transform: scaleX(1); }
.why-brief__chips { display: grid; gap: 0.4em; margin: 0; padding: 0; list-style: none; }
.why-brief__chip { display: flex; align-items: center; gap: 0.75em; padding: 0.5em 0.7em; border-radius: 0.6em; border: 1px solid rgba(10, 29, 42, 0.08); background: #FFFFFF; transition: border-color 0.3s ease, background-color 0.3s ease, box-shadow 0.3s ease, opacity 0.4s ease, translate 0.5s var(--ease); }
.why-brief__ico { display: grid; place-items: center; flex: none; width: 2.1em; height: 2.1em; border-radius: 0.5em; background: #0A1D2A; color: #FFFFFF; transition: background-color 0.3s ease; }
.why-brief__ico svg { width: 1.2em; height: 1.2em; }
.why-brief__name { display: grid; font-weight: 600; line-height: 1.25; }
.why-brief__name small { font-size: 0.82em; font-weight: 400; color: rgba(10, 29, 42, 0.55); }
.why-brief__tick { display: grid; place-items: center; margin-left: auto; width: 1.4em; height: 1.4em; border-radius: 50%; background: #E9F6EE; color: #1E8A4C; transition: opacity 0.3s ease, scale 0.4s var(--ease); }
.why-brief__tick svg { width: 0.9em; height: 0.9em; }
.why-brief__chip.is-on { border-color: rgba(255, 101, 11, 0.55); background: #FFF8F3; box-shadow: 0 0.5em 1.2em -0.7em rgba(255, 101, 11, 0.6); }
.why-brief__chip.is-on .why-brief__ico { background: #FF650B; }
.why-brief__foot { display: flex; align-items: center; justify-content: space-between; margin-top: 0.8em; padding: 0.8em 1.2em; border-top: 1px solid rgba(10, 29, 42, 0.08); background: #FBF9F6; }
.why-brief__ready { display: inline-flex; align-items: center; gap: 0.5em; padding: 0.4em 0.85em 0.4em 0.5em; border-radius: 2em; background: #0A1D2A; color: #FFFFFF; font-weight: 600; transition: opacity 0.4s ease, scale 0.45s var(--ease); }
.why-brief__ready svg { width: 1.3em; height: 1.3em; padding: 0.2em; border-radius: 50%; background: #FF650B; }
.why-brief__meta { font-size: 0.85em; font-weight: 600; color: rgba(10, 29, 42, 0.55); transition: opacity 0.4s ease; }

/* loop states (only once app.js has started it: .is-playing) */
.why-brief.is-playing .why-brief__scan { opacity: 0.45; }
.why-brief.is-playing .why-brief__scan i::after { transform: scaleX(0); }
.why-brief.is-playing .why-brief__chip:not(.is-added) { border-style: dashed; border-color: rgba(10, 29, 42, 0.14); background: transparent; box-shadow: none; }
.why-brief.is-playing .why-brief__chip > * { opacity: 0; translate: 0 0.4em; transition: opacity 0.4s ease, translate 0.5s var(--ease), background-color 0.3s ease; }
.why-brief.is-playing .why-brief__chip .why-brief__tick { opacity: 0; scale: 0.4; translate: none; }
.why-brief.is-playing .why-brief__ready { opacity: 0.25; scale: 0.92; }
.why-brief.is-playing .why-brief__meta { opacity: 0; }
.why-brief.is-playing[data-step="2"] .why-brief__scan,
.why-brief.is-playing[data-step="3"] .why-brief__scan,
.why-brief.is-playing[data-step="4"] .why-brief__scan { opacity: 1; }
.why-brief.is-playing[data-step="2"] .why-brief__scan i::after,
.why-brief.is-playing[data-step="3"] .why-brief__scan i::after,
.why-brief.is-playing[data-step="4"] .why-brief__scan i::after { transform: scaleX(1); transition: transform 1.1s cubic-bezier(0.45, 0, 0.2, 1); }
.why-brief.is-playing .why-brief__chip.is-added > * { opacity: 1; translate: 0 0; }
.why-brief.is-playing .why-brief__chip.is-added .why-brief__tick { opacity: 1; scale: 1; transition-delay: 0.35s; }
.why-brief.is-playing[data-step="4"] .why-brief__ready { opacity: 1; scale: 1; }
.why-brief.is-playing[data-step="4"] .why-brief__meta { opacity: 1; transition-delay: 0.2s; }
.why-brief.is-playing.is-resetting .why-brief__win { opacity: 0.35; }
@media (max-width: 991.98px) {
    .why-brief { padding: 2% 0 4%; }
    .why-brief__win, .why-brief:hover .why-brief__win { transform: none; }
}
@media (prefers-reduced-motion: reduce) { .why-brief__win { transition: none; } }

@media (prefers-reduced-motion: no-preference) {
    #why .why-visual[data-reveal] { opacity: 0; transform: translateY(24px); transition: opacity 0.7s ease, transform 0.8s var(--ease); }
    #why .why-visual.is-visible { opacity: 1; transform: none; }
    .why-visual__tags li { opacity: 0; transition: opacity 0.6s ease; }
    .why-visual.is-visible .why-visual__tags li { opacity: 1; transition-delay: 0.6s; }
    .why-visual.is-visible .why-visual__tags li:nth-child(2) { transition-delay: 0.75s; }
    .why-visual.is-visible .why-visual__tags li:nth-child(3) { transition-delay: 0.9s; }
}
/* The five expertise phrases in the paragraph (.why-key) share data-sys-key
   with the card's five services: app.js marks one key .is-on (on hover of a
   phrase, or as the card adds that service) and the phrase gets an orange
   underline while its service row lights. */
.why-key {
    background-image: linear-gradient(#FF650B, #FF650B);
    background-repeat: no-repeat;
    background-position: 0 100%;
    background-size: 0 1.5px;
    transition: background-size 0.4s var(--ease), color 0.3s ease;
}
.why-key.is-on { color: #091E30; background-size: 100% 1.5px; }

/* Copy column: the first paragraph leads (larger, darker), the button sits
   a clear step below the text. */
.why-valin-copy .why-valin-cta { margin-top: 34px; }

/* Replaces the old g-4 utility + a fixed 4rem padding-left on the copy
   column with one fluid, responsive gap -- grows with viewport instead of
   jumping at a breakpoint, and collapses to a plain row-gap once the
   columns stack (below lg). */
/* Bootstrap's grid gutter is padding/negative-margin based (--bs-gutter-x/y,
   consumed by .row's own rules), not the native `gap` property -- setting
   a native column-gap here as well as the 50/50 .col-lg-6 widths would add
   up to over 100% of the row's width and force the columns to wrap onto
   separate lines. Setting the gutter variable directly instead keeps using
   Bootstrap's own (working) mechanism, just with a larger, fluid value in
   place of the .g-4 utility's fixed 1.5rem. */
/* Matches the reference's own exact .split gap at each of its three tiers
   (76px / 45px <=1150px / 35px <=900px) for this section specifically,
   rather than a clamp approximation -- the other sections sharing this
   same gutter-override pattern (#approach/#ai/#challenge/#training/#contact
   just below) already use their own exact values; this one was missed in
   that earlier pass. */
.why-valin-row { --bs-gutter-x: 76px; --bs-gutter-y: 2rem; }
@media (max-width: 1150px) { .why-valin-row { --bs-gutter-x: 45px; } }
@media (max-width: 900px) { .why-valin-row { --bs-gutter-x: 35px; } }
/* Unlike every other two-column row on this page, the reference keeps this
   one's columns side-by-side all the way down to 680px -- not Bootstrap's
   own lg breakpoint (992px), where .col-lg-6 would otherwise stack early.
   Extends the same 50/50 split downward; narrower than 680px stacks to
   full width as normal (Bootstrap's own default, no override needed). */
@media (min-width: 681px) and (max-width: 991.98px) {
    .why-valin-row > .col-lg-6 { flex: 0 0 auto; width: 50%; }
}
/* Exact spec for this section's paragraphs (both the .lead and the second
   plain <p> -- .lead is Bootstrap's own class, font-weight:300 by default,
   which this overrides along with font-size/colour so the two paragraphs
   stay identical). Width is no longer capped: with the wider column (was
   col-lg-7, now col-lg-6 but with more breathing room from the gap above)
   letting the text reach its own natural wrap is what the reference shows,
   not a hard cap. */
.why-valin-copy .lead,
.why-valin-copy p {
    font-family: var(--font-text);
    /* 16px, not 17px -- this section's own paragraphs are a size smaller
       than #approach/#challenge's (which genuinely are 17px), a mismatch
       this rule previously papered over by giving all three the same
       value. */
    font-size: 16px;
    font-weight: 400;
    line-height: 1.7;
    color: #586C7D;
    /* Matches the reference's own spacing above every paragraph in this
       flow (heading-to-first-paragraph and paragraph-to-paragraph alike,
       h2 itself carries no margin-bottom here) -- previously unset, so the
       two paragraphs ran together with no gap between them. */
    margin-top: 22px;
}
.why-valin-copy .lead { font-size: 18px; line-height: 1.65; color: #2F4253; }
/* Stacked (below 681px): copy first, the card under it. */
@media (max-width: 680px) {
    .why-visual-col { order: 2; }
    .why-grid {
        -webkit-mask-image: radial-gradient(ellipse 80% 40% at 50% 75%, #000 25%, transparent 78%);
        mask-image: radial-gradient(ellipse 80% 40% at 50% 75%, #000 25%, transparent 78%);
    }
}

/* --- AI / digital-intelligence feature band ------------------------------------ */
.feature-band {
    position: relative;
    overflow: hidden;
    padding-block: var(--space-section);
    /* Vibrant tangerine / safety orange, flat rather than the site's
       default accent gradient which fades toward a muted, brownish
       corner. */
    background: #ff8000;
    color: #fff;
}
.feature-band h2, .feature-band h3 { color: #fff; }
.feature-band .lead { color: rgba(255, 255, 255, 0.8); font-size: 22px; max-width: 40rem; }
.feature-band .eyebrow { color: #fff; opacity: 0.85; }
.feature-band .eyebrow--rule::before { background: rgba(255, 255, 255, 0.85); }
/* Home's #ai is one of two .feature-band sections (the service detail page's
   "Intelligence" section is the other) -- #ai.* overrides below (ID beats
   .feature-band's specificity) keep this client spec scoped to the home
   page only. */
#ai {
    /* Deep navy (the page's own ink) with orange as the accent, not a full
       orange slab: a faint lighter-navy lift top left and a soft orange glow
       behind the demo so the band doesn't read as one flat block. */
    background:
        radial-gradient(ellipse 55% 75% at 74% 42%, rgba(255, 101, 11, 0.16) 0%, rgba(255, 101, 11, 0) 70%),
        radial-gradient(ellipse 60% 80% at 12% 15%, #14324C 0%, rgba(20, 50, 76, 0) 70%),
        #0A1D2A;
    /* Matches the reference's own exact, asymmetric padding -- top follows
       the same 104/75/60 steps as #solutions/#why/#approach/#challenge
       (see below), bottom is a flat 64px at every width (the reference
       never narrows it), not a symmetric clamp. */
    padding-top: var(--space-section);
    padding-bottom: var(--space-block);
}
/* AI cursor (app.js, mouse with a fine pointer only): inside #ai the system
   cursor gives way to a robotic one -- a plated navy arrow (tip on the
   pointer, a panel seam and a blinking status LED) that tracks exactly, and
   a hex sensor ring with a turning tick ring and a mono X·Y readout that
   follows with a slight lag. Over a link or button (.is-target) the ring
   closes in and turns navy, the LED goes solid and the readout hides. */
#ai.has-ai-cursor,
#ai.has-ai-cursor * { cursor: none; }
.ai-cursor {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 1080;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.25s ease;
}
.ai-cursor.is-shown { opacity: 1; }
.ai-cursor__dot,
.ai-cursor__ring {
    position: absolute;
    top: 0;
    left: 0;
    will-change: transform;
}
.ai-cursor__dot { width: 22px; height: 26px; margin: -1.5px 0 0 -1.5px; }
.ai-cursor__dot svg { display: block; width: 100%; height: 100%; overflow: visible; filter: drop-shadow(0 2px 3px rgba(10, 29, 42, 0.35)); }
.ai-cursor__arrow { fill: #FF650B; stroke: #FFFFFF; }
.ai-cursor__seam { stroke: rgba(255, 255, 255, 0.45); }
.ai-cursor__led { fill: #FFFFFF; animation: ai-cursor-led 1.6s steps(1, end) infinite; }
.ai-cursor__ring { width: 44px; height: 44px; margin: -22px 0 0 -22px; }
.ai-cursor__ring svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
    color: #FFFFFF;
    transition: transform 0.35s var(--ease), color 0.25s ease;
}
.ai-cursor__spin { transform-origin: 22px 22px; animation: ai-cursor-spin 8s linear infinite; }
.ai-cursor__hex { transform-origin: 22px 22px; transition: transform 0.35s var(--ease); }
.ai-cursor__read {
    position: absolute;
    left: 40px;
    top: 34px;
    padding: 2px 5px;
    border-radius: 3px;
    background: rgba(10, 29, 42, 0.78);
    color: #FFFFFF;
    font: 500 10px/1.3 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    letter-spacing: 0.04em;
    white-space: nowrap;
    transition: opacity 0.2s ease;
}
.ai-cursor.is-target .ai-cursor__ring svg { transform: scale(0.8); color: #FF8A3D; }
.ai-cursor.is-target .ai-cursor__hex { transform: rotate(30deg); }
.ai-cursor.is-target .ai-cursor__led { animation: none; fill: #0A1D2A; }
.ai-cursor.is-target .ai-cursor__read { opacity: 0; }
@keyframes ai-cursor-spin { to { transform: rotate(360deg); } }
@keyframes ai-cursor-led { 0%, 70% { opacity: 1; } 70.01%, 100% { opacity: 0.25; } }
@media (prefers-reduced-motion: reduce) {
    .ai-cursor__spin,
    .ai-cursor__led { animation: none; }
}

/* AI band edges: the navy band starts and ends on a gentle diagonal
   (parallel, so the band reads as one slanted ribbon) instead of a straight
   seam, and fine orange circuit traces grow out of each edge into the light
   section beside it, fading as they go. The top edge lives at the foot of
   #why, the bottom edge at the head of #approach; each is a stretched wedge
   (preserveAspectRatio none) over a fixed-aspect trace layer anchored to the
   corner, whose trace roots start under the wedge so they always appear to
   leave from the edge. They stay crisp (no fade): thin traces faded out
   lose their runs and leave the nodes floating. On scroll the traces draw out of the edge and their
   nodes pop in; then short bright pulses travel along them.
   The edges are overlays: absolutely positioned at the section's edge and
   layered under its content (each .container is z-index 1), so neither
   section adds padding for them -- the traces simply run behind the
   copy's last/first lines. */
#approach { position: relative; }
#approach > .container { position: relative; z-index: 1; }
.ai-edge { z-index: 0; }
.ai-edge {
    position: absolute;
    left: 0;
    right: 0;
    height: clamp(90px, 10.5vw, 150px);
    pointer-events: none;
}
.ai-edge--top { bottom: 0; }
.ai-edge--bottom { top: 0; }
/* Overlap the band by 1px each side: no sub-pixel seam at either diagonal. */
#ai { margin-block: -1px; }
.ai-edge svg { position: absolute; display: block; }
.ai-edge__wedge { inset: 0; width: 100%; height: 100%; }
.ai-edge__wedge polygon { fill: #0A1D2A; }
/* Taller than the band, so the traces climb well clear of the wedge into
   the light section; set in from the right, where the diagonal is lower. */
.ai-edge__traces {
    bottom: 0;
    right: 12%;
    height: 135%;
    width: auto;
    aspect-ratio: 600 / 150;
}
/* The bottom edge: the same traces turned upside down, from the left. */
.ai-edge--bottom .ai-edge__traces { top: 0; bottom: auto; right: auto; left: 12%; height: 140%; transform: rotate(180deg); }
/* Stroke widths are in the drawing's own units (it renders at ~1.4-1.7x),
   not non-scaling-stroke: that breaks pathLength-based dashes once the SVG
   is scaled up, so the draw-in would stop part-way. */
.ai-trace,
.ai-trace-pulse { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.ai-trace { stroke: #DD5F10; stroke-width: 1; opacity: 0.9; }
.ai-trace-node { fill: #F8F6F2; stroke: #DD5F10; stroke-width: 1; }
.ai-edge--bottom .ai-trace-node { fill: #FAF8F3; }
.ai-trace-pulse { stroke: #FF8A3D; stroke-width: 1.8; stroke-dasharray: 0.07 1; stroke-dashoffset: 0.07; opacity: 0; }

@media (prefers-reduced-motion: no-preference) {
    #why .ai-edge[data-reveal],
    #approach .ai-edge[data-reveal] { opacity: 1; transform: none; transition: none; }
    .ai-trace { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 1.4s cubic-bezier(0.45, 0, 0.25, 1); }
    .ai-trace-node { opacity: 0; transform-box: fill-box; transform-origin: center; transform: scale(0); transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.3, 1.6, 0.5, 1); }
    .ai-edge.is-visible .ai-trace { stroke-dashoffset: 0; }
    .ai-edge.is-visible .ai-trace-node { opacity: 1; transform: none; }
    .ai-edge.is-visible .ai-trace--2 { transition-delay: 0.12s; }
    .ai-edge.is-visible .ai-trace--3 { transition-delay: 0.24s; }
    .ai-edge.is-visible .ai-trace--4 { transition-delay: 0.36s; }
    .ai-edge.is-visible .ai-trace--5 { transition-delay: 0.48s; }
    .ai-edge.is-visible .ai-trace--6 { transition-delay: 0.6s; }
    .ai-edge.is-visible .ai-trace--7 { transition-delay: 0.72s; }
    /* Nodes land once their trace has drawn. */
    .ai-edge.is-visible .ai-trace-node--1 { transition-delay: 1.2s; }
    .ai-edge.is-visible .ai-trace-node--2 { transition-delay: 1.32s; }
    .ai-edge.is-visible .ai-trace-node--3 { transition-delay: 1.44s; }
    .ai-edge.is-visible .ai-trace-node--4 { transition-delay: 1.56s; }
    .ai-edge.is-visible .ai-trace-node--5 { transition-delay: 1.68s; }
    .ai-edge.is-visible .ai-trace-node--6 { transition-delay: 1.8s; }
    .ai-edge.is-visible .ai-trace-node--7 { transition-delay: 1.92s; }
    /* Signals: a short bright dash runs out along each trace, staggered,
       starting after the draw-in. */
    .ai-edge.is-visible .ai-trace-pulse { animation: ai-pulse 4.2s cubic-bezier(0.45, 0, 0.55, 1) infinite; }
    .ai-edge.is-visible .ai-trace-pulse--1 { animation-delay: 2.2s; }
    .ai-edge.is-visible .ai-trace-pulse--2 { animation-delay: 3.4s; }
    .ai-edge.is-visible .ai-trace-pulse--3 { animation-delay: 2.8s; }
    .ai-edge.is-visible .ai-trace-pulse--4 { animation-delay: 4.1s; }
    .ai-edge.is-visible .ai-trace-pulse--5 { animation-delay: 2.5s; }
    .ai-edge.is-visible .ai-trace-pulse--6 { animation-delay: 3.8s; }
    .ai-edge.is-visible .ai-trace-pulse--7 { animation-delay: 3.1s; }
}
@keyframes ai-pulse {
    0% { stroke-dashoffset: 0.07; opacity: 0; }
    8% { opacity: 1; }
    55% { stroke-dashoffset: -0.95; opacity: 1; }
    62%, 100% { stroke-dashoffset: -0.95; opacity: 0; }
}
/* Matches the reference's own .ai-top{grid-template-columns:.9fr 1.1fr}
   ratio (45/55), not Bootstrap's col-lg-5/col-lg-7 (5/7, 41.7/58.3) which
   is noticeably narrower on the text column -- stacked below lg exactly
   like the shared columns, so this only applies once they're actually
   side-by-side. */
@media (min-width: 992px) {
    #ai .row > .col-lg-5 { flex: 0 0 auto; width: 45%; }
    #ai .row > .col-lg-7 { flex: 0 0 auto; width: 55%; }
}
#ai .eyebrow {
    font-size: var(--fs-small);
    font-weight: 600;
    letter-spacing: 0.12em;
    color: #FFFFFF;
    opacity: 1;
    margin-bottom: 32px;
}
#ai .eyebrow--rule { gap: 14px; }
#ai .eyebrow--rule::before { width: 34px; height: 2px; background: var(--color-accent); }
#ai h2 {
    font-family: var(--font-display);
    font-size: var(--fs-h2);
    font-weight: 700;
    /* Matches the universal h2 rule's 1.13 (not redeclared by the
       reference's own .ai h2, so it inherits that instead of a bespoke
       value here). */
    line-height: 1.13;
    letter-spacing: -0.045em;
    color: #FFFFFF;
    /* Locks the heading-to-paragraph gap to ~25px instead of the shared
       body.home h2 rule's clamp (up to 28px at desktop). */
    margin-bottom: 25px;
}
#ai h2 span,
#ai h2 .text-ink { color: #FF7A1A; }
#ai .lead {
    font-family: var(--font-text);
    font-size: 16px;
    font-weight: 400;
    line-height: 1.7;
    color: rgba(255, 255, 255, 0.82);
    /* No cap, matching #approach .lead: wraps against the real col-lg-5
       column width instead of an artificially narrow fixed value. */
    max-width: none;
    /* The gap to the button below is set entirely by #ai .btn's margin-top
       instead (the two don't collapse -- the button is inline-block), so
       this is zeroed to avoid stacking on top of it. */
    margin-bottom: 0;
}
/* Paragraph-to-button gap, ~28px total (the shared .lead margin-bottom is
   zeroed above specifically so this is the only contributor). */
#ai .btn { font-size: 14px; padding: 14px 24px; margin-top: 28px; color: #FFFFFF; border-color: #FFFFFF; }
@media (max-width: 991.98px) {
    #ai h2 { font-size: var(--fs-h2); }
}

/* -- service detail page's own "Digital Intelligence" band --------------
   The other .feature-band section (see #ai above) -- light cream here
   instead of flat orange, with the brain photo as a full-bleed backdrop
   behind a single text column rather than a second grid column. Every rule
   below is #intelligence-scoped (ID beats .feature-band's class and beats
   the shared .ai-feature / .ai-feature-row rules used by Home's #ai), so
   none of this touches the Home page's own pillars. Pixel values and the
   odd breakpoints (901/680px) are copied directly from the reference's own
   live-resolved values for this exact component, not fitted to this site's
   usual rem+clamp system. */
/* min-height matches the reference's own exact value (confirmed live, not
   guessed -- its computed min-height is a flat 620px from this section's
   widest point all the way down to 681px). Without it, the section's
   height is purely text-content-driven, which happens to fall short of
   that -- shrinking the backdrop photo beneath it (height:100%, object-
   fit:fill) more than the reference's own version, instead of the full,
   generously-proportioned presentation the reference always guarantees
   regardless of exactly how much copy there is. display:flex + align-
   items:center is what actually applies that floor to the visible content
   (a plain min-height alone doesn't centre the shorter content within the
   extra space). Dropped at <=680px to 0 (i.e. not set), same as the
   reference, since that tier's own padding-bottom:340px reserves the
   backdrop's room a different way (see .svc-ai__backdrop above). */
#intelligence {
    position: relative;
    overflow: hidden;
    background: #FDF7F0;
    color: var(--color-ink);
    padding-top: var(--space-section);
    padding-bottom: var(--space-section);
    min-height: 620px;
    display: flex;
    align-items: center;
}
@media (max-width: 680px) { #intelligence { padding-top: var(--space-section); padding-bottom: 340px; min-height: 0; } }
.svc-ai__backdrop { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
/* Full-height image + horizontal fade doesn't work once the column stacks
   to full width -- the brightest part of the photo ends up directly behind
   the feature icons/note text, which isn't legible against it. Pinned to a
   short strip at the very bottom instead (below all text content, which
   sits on the section's own solid cream, with #intelligence's own
   padding-bottom:340px reserving the room for it), same approach as a
   typical "photo footer" treatment. */
@media (max-width: 680px) { .svc-ai__backdrop { inset: auto 0 0 0; height: 320px; } }
/* ai-backdrop-v2.webp is the brain-over-laptop photo with its left ~56%
   already the section's own cream (#FDF7F0), so the text needs no fade.
   The section is taller than the photo's 2.4:1, and a cover crop would
   enlarge it until the brain sat under the copy -- so from 901px it spans
   the full width at its own ratio, centred, its top and bottom edges
   faded (mask) into a blurred, height-fitted copy of itself (::before),
   kept to the right half so its glow never sits behind the copy. */
@media (min-width: 901px) {
    .svc-ai__backdrop::before {
        content: "";
        position: absolute;
        inset: -40px;
        background: url("../img/services/web-development/ai-backdrop-v2.8ae610a74ce7.webp") right center / auto 100% no-repeat;
        filter: blur(30px);
        mask-image: linear-gradient(90deg, transparent 50%, #000 75%);
    }
    .svc-ai__backdrop img {
        position: absolute;
        top: 50%;
        right: 0;
        width: 100%;
        height: auto;
        translate: 0 -50%;
        mask-image: linear-gradient(180deg, transparent 0, #000 14%, #000 86%, transparent 100%);
    }
}
@media (max-width: 900px) { .svc-ai__backdrop img { width: 100%; height: 100%; object-fit: cover; object-position: right center; } }
/* 681-900px: no room beside the copy for the brain, so the copy goes full
   width and the photo becomes a strip below it, as at <=680px. Both tiers
   fade the strip's top edge into the cream. */
@media (min-width: 681px) and (max-width: 900px) {
    #intelligence { padding-bottom: 420px; min-height: 0; }
    .svc-ai__backdrop { inset: auto 0 0 0; height: 400px; }
}
@media (max-width: 900px) { .svc-ai__backdrop img { mask-image: linear-gradient(180deg, transparent 0, #000 22%); } }
#intelligence .container { position: relative; z-index: 1; }
/* 58% of the container, capped at 730px -- not a flat max-width -- so the
   uncovered ~42% on the right keeps showing the photo unobstructed, same
   as the reference. Widens at each narrower tier as the section's own
   side padding shrinks, until it goes full-width once the backdrop photo
   stops sitting behind the text entirely (<=900px). */
.svc-ai__copy { width: 58%; max-width: 730px; }
@media (max-width: 1150px) { .svc-ai__copy { width: 64%; } }
@media (max-width: 900px) { .svc-ai__copy { width: 100%; } }
#intelligence h2 { color: var(--color-ink); font-size: clamp(30px, 3.2vw, 46px); line-height: 1.12; letter-spacing: -0.02em; }
@media (max-width: 680px) { #intelligence h2 { font-size: var(--fs-h2); } }
/* Matches the reference's own accent shade for this heading -- the same
   darker, rust-leaning orange used by the Case Study heading's accent
   (#E65305), not the sitewide .text-accent default (var(--color-accent)). */
#intelligence h2 .text-accent { color: #E65305; }
#intelligence .lead { color: var(--color-muted); font-size: 17px; line-height: 1.65; max-width: none; margin-top: 20px; margin-bottom: 0; }
@media (max-width: 1150px) { #intelligence .lead { font-size: 15px; } }
@media (max-width: 680px) { #intelligence .lead { font-size: 14px; } }
/* Plain icon in a pale peach circle, title-case label (not the shared
   .ai-feature__label's uppercase) -- matches the reference exactly. Fixed
   43px/23px (10px padding) at every breakpoint, unlike the divider below. */
#intelligence .ai-feature__icon {
    width: 52px;
    height: 52px;
    padding: 13px;
    box-sizing: border-box;
    border-radius: 50%;
    background: #FDE4D2;
    color: var(--color-accent);
    margin-bottom: 20px;
    transition: filter 0.2s var(--ease);
}
#intelligence .ai-feature__icon svg { width: 100%; height: 100%; }
/* Matches the reference's own hover glow on these icons (same drop-shadow
   recipe as the Case Study/Capabilities/FAQ icons elsewhere on this page).
   hover:hover+pointer:fine so it only engages for a real mouse/trackpad --
   on touch, tapping a card would otherwise leave it stuck "lit" until
   something else is tapped. :focus-within is unaffected (keyboard nav
   still shows the glow on any input type, as it should). */
#intelligence .ai-feature:focus-within .ai-feature__icon { filter: drop-shadow(0 0 6px rgba(255, 101, 11, 0.6)) drop-shadow(0 0 15px rgba(255, 101, 11, 0.33)); }
@media (hover: hover) and (pointer: fine) {
    #intelligence .ai-feature:hover .ai-feature__icon { filter: drop-shadow(0 0 6px rgba(255, 101, 11, 0.6)) drop-shadow(0 0 15px rgba(255, 101, 11, 0.33)); }
}
#intelligence .ai-feature__label { color: var(--color-ink); text-transform: none; letter-spacing: -0.005em; font-size: 18px; font-weight: 700; line-height: 1.3; max-width: 140px; margin-bottom: 0; }
#intelligence .ai-feature p { color: var(--color-muted); font-size: 15px; line-height: 1.6; margin-top: 10px; }
/* Four columns, no grid gap at all at desktop -- spacing instead comes
   from each column's own padding (20px right; 20px left on every column
   but the first, which is also where the divider sits). Below 901px the
   reference wraps to 2x2 using an actual gap instead (26px, or "28px 24px"
   <=680px) with no per-column padding/divider, so Bootstrap's own
   row-cols-2/row-cols-lg-4 width split is overridden here too -- its own
   lg breakpoint (992px) doesn't line up with the reference's 901px one. */
#intelligence .ai-feature-row { --bs-gutter-x: 0; --bs-gutter-y: 0; }
@media (min-width: 901px) {
    #intelligence .ai-feature-row > .col { width: 25%; padding-right: 20px; }
    #intelligence .ai-feature-row > .col:not(:first-child) { padding-left: 28px; }
}
@media (max-width: 900px) {
    /* No explicit padding override here -- Bootstrap's own gutter mechanism
       (row's negative margin + each .col's padding, both driven by
       --bs-gutter-x) needs its padding left alone to actually produce the
       gap; the >=901px tier above sets its own padding directly instead
       because it needs an asymmetric 20/20 split, not a symmetric gutter. */
    #intelligence .ai-feature-row { --bs-gutter-x: 26px; --bs-gutter-y: 26px; }
    #intelligence .ai-feature-row > .col { width: 50%; }
}
@media (max-width: 680px) {
    #intelligence .ai-feature-row { --bs-gutter-x: 24px; --bs-gutter-y: 28px; }
}
/* Divider: a vertical rule before every column but the first -- reference
   keeps this down to 901px (not Bootstrap's 992px lg breakpoint, where the
   shared base rule this would otherwise inherit from kicks in), and drops
   it entirely once the row wraps to 2x2 at <=900px (a rule spanning a row
   break would land in the wrong place). Self-contained rather than relying
   on the shared .ai-feature-row .col:not(:first-child)::before (Home's own
   #ai, <=991.98px only) so the 901-991px gap is covered correctly here. */
@media (min-width: 901px) {
    #intelligence .ai-feature-row .col:not(:first-child)::before {
        content: "";
        position: absolute;
        left: 0;
        top: 0;
        bottom: 0;
        width: 1px;
        background: rgba(9, 30, 48, 0.1);
    }
}
#intelligence .row.ai-feature-row { margin-top: 40px; }
@media (max-width: 680px) { #intelligence .row.ai-feature-row { margin-top: 30px; } }
/* Thin left rule instead of the shared .svc-ai-note's frosted box -- that
   translucent-white treatment only reads correctly on a dark/saturated
   background. */
#intelligence .svc-ai-note {
    background: none;
    border-radius: 0;
    border-left: 3px solid var(--color-accent);
    padding: 2px 0 2px 26px;
    margin-top: 52px;
}
@media (max-width: 680px) { #intelligence .svc-ai-note { margin-top: 30px; } }
#intelligence .svc-ai-note strong { color: var(--color-ink); font-size: 16px; font-weight: 700; }
#intelligence .svc-ai-note p { color: var(--color-muted); font-size: 14px; line-height: 1.65; margin-top: 4px; }

/* AI demo (#ai, right column): a product dashboard drawn in HTML/SVG that
   plays like a screen recording while the band is in view. app.js ("AI
   demo") walks .ai-demo through data-step 0..5 on a loop and moves the
   .ai-demo__pointer between the [data-demo-target] elements:
     1 chart line draws, points pop, KPIs count up
     2 pointer rests on a data point -> tooltip
     3 pointer clicks Summarise -> the summary types out
     4 pointer clicks "Automate this task" -> toggle on, toast
     5 hold, then fade and restart
   The window sits on a slight 3D tilt; type sizes are in em off a cqi base so
   the whole screen scales with its column. Reduced motion (or no JS): the
   finished state, no pointer. */
.ai-demo { position: relative; container-type: inline-size; perspective: 1400px; padding: 4% 2% 6% 0; }
.ai-demo__win {
    position: relative;
    font-size: clamp(8px, 1.95cqi, 13px);
    color: #0A1D2A;
    background: #FBF8F4;
    border-radius: 1.1em;
    overflow: hidden;
    transform: rotateY(-16deg) rotateX(7deg) rotateZ(1deg);
    transform-origin: 40% 50%;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.5), 0 3.5em 6em -2em rgba(60, 20, 0, 0.55), 0 1em 2em -1em rgba(10, 29, 42, 0.35);
    transition: transform 0.8s var(--ease);
}
@media (hover: hover) and (pointer: fine) { .ai-demo:hover .ai-demo__win { transform: rotateY(-8deg) rotateX(3deg); } }
.ai-demo__bar { display: flex; align-items: center; gap: 1em; padding: 0.85em 1.2em; background: #FFFFFF; border-bottom: 1px solid rgba(10, 29, 42, 0.08); }
.ai-demo__dots { display: flex; gap: 0.4em; }
.ai-demo__dots i { width: 0.65em; height: 0.65em; border-radius: 50%; background: rgba(10, 29, 42, 0.14); }
.ai-demo__title { font-weight: 600; font-size: 1.05em; }
.ai-demo__search { display: inline-flex; align-items: center; gap: 0.5em; margin-left: auto; width: 32%; padding: 0.45em 0.8em; border-radius: 0.6em; background: #F2EEE8; color: rgba(10, 29, 42, 0.45); }
.ai-demo__search svg { width: 1em; height: 1em; }
.ai-demo__avatar { width: 1.9em; height: 1.9em; border-radius: 50%; background: #0A1D2A; box-shadow: inset 0 -0.6em 0 rgba(255, 138, 61, 0.55); }
.ai-demo__body { display: grid; grid-template-columns: 3.6em minmax(0, 1fr) 31%; min-height: 25em; }
.ai-demo__side { display: flex; flex-direction: column; align-items: center; gap: 1.1em; padding-top: 1.3em; background: #0A1D2A; }
.ai-demo__side i { width: 1.25em; height: 1.25em; border-radius: 0.35em; border: 1.5px solid rgba(255, 255, 255, 0.35); }
.ai-demo__side i.is-on { border-color: #FF8A3D; background: rgba(255, 138, 61, 0.2); }
.ai-demo__main { padding: 1.1em 1.3em; min-width: 0; }
.ai-demo__tabs { display: flex; align-items: center; gap: 1.3em; font-weight: 600; color: rgba(10, 29, 42, 0.45); border-bottom: 1px solid rgba(10, 29, 42, 0.08); padding-bottom: 0.7em; }
.ai-demo__tabs .is-on { color: #0A1D2A; box-shadow: 0 0.78em 0 -0.62em #DD5F10; }
.ai-demo__btn { display: inline-flex; align-items: center; gap: 0.45em; margin-left: auto; padding: 0.45em 0.85em; border-radius: 0.55em; border: 1px solid rgba(10, 29, 42, 0.16); background: #FFFFFF; color: #0A1D2A; transition: background-color 0.2s ease, color 0.2s ease, transform 0.15s ease; }
.ai-demo__btn svg { width: 1.05em; height: 1.05em; color: #DD5F10; }
.ai-demo__kpis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.8em; margin-top: 1em; }
.ai-demo__kpis div { padding: 0.7em 0.85em; border-radius: 0.7em; background: #FFFFFF; border: 1px solid rgba(10, 29, 42, 0.07); }
.ai-demo__kpis small { display: block; font-size: 0.78em; line-height: 1.3; color: rgba(10, 29, 42, 0.55); }
.ai-demo__kpis b { display: block; margin-top: 0.25em; font-size: 1.55em; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.ai-demo__chart { position: relative; margin-top: 1em; padding: 0.9em; border-radius: 0.7em; background: #FFFFFF; border: 1px solid rgba(10, 29, 42, 0.07); }
.ai-demo__chart svg { display: block; width: 100%; height: 9.5em; overflow: visible; }
.ai-demo__grid { stroke: rgba(10, 29, 42, 0.07); stroke-width: 1; vector-effect: non-scaling-stroke; }
.ai-demo__area { fill: rgba(221, 95, 16, 0.1); }
.ai-demo__line { stroke: #DD5F10; stroke-width: 2.2; stroke-linecap: round; stroke-dasharray: 1; }
.ai-demo__line--b { stroke: #0A1D2A; stroke-width: 1.4; opacity: 0.35; }
/* points sit on the orange line at x = 22.5%, 62.5%, 82.5% of the plot */
.ai-demo__pt { position: absolute; width: 0.75em; height: 0.75em; margin: -0.375em 0 0 -0.375em; border-radius: 50%; background: #FFFFFF; border: 2px solid #DD5F10; transition: transform 0.35s var(--ease); }
.ai-demo__pt--1 { left: calc(0.9em + (100% - 1.8em) * 0.225); top: calc(0.9em + 9.5em * 0.653); }
.ai-demo__pt--2 { left: calc(0.9em + (100% - 1.8em) * 0.625); top: calc(0.9em + 9.5em * 0.44); }
.ai-demo__pt--3 { left: calc(0.9em + (100% - 1.8em) * 0.825); top: calc(0.9em + 9.5em * 0.293); }
.ai-demo__tip {
    position: absolute;
    left: calc(0.9em + (100% - 1.8em) * 0.625);
    top: calc(0.9em + 9.5em * 0.44 - 1em);
    translate: -50% -100%;
    display: grid;
    gap: 0.15em;
    padding: 0.5em 0.75em;
    border-radius: 0.5em;
    background: #0A1D2A;
    color: #FFFFFF;
    font-size: 0.85em;
    white-space: nowrap;
    box-shadow: 0 0.6em 1.4em -0.6em rgba(10, 29, 42, 0.6);
    transition: opacity 0.3s ease, transform 0.35s var(--ease);
}
.ai-demo__tip em { font-style: normal; color: #FF8A3D; font-weight: 700; margin-left: 0.4em; }
.ai-demo__panel { display: flex; flex-direction: column; padding: 1.1em 1.1em 1.2em; border-left: 1px solid rgba(10, 29, 42, 0.08); background: #FFFFFF; }
.ai-demo__head { display: flex; align-items: center; gap: 0.5em; font-weight: 700; }
.ai-demo__head i { width: 0.6em; height: 0.6em; border-radius: 0.15em; background: #DD5F10; rotate: 45deg; }
.ai-demo__head--sub { margin-top: auto; font-size: 0.85em; color: rgba(10, 29, 42, 0.55); text-transform: uppercase; letter-spacing: 0.06em; }
.ai-demo__type { min-height: 8.6em; margin: 0.8em 0 1em; font-size: 0.92em; line-height: 1.55; color: rgba(10, 29, 42, 0.78); }
.ai-demo__type.is-typing::after { content: ""; display: inline-block; width: 0.08em; height: 1.05em; margin-left: 0.1em; vertical-align: -0.15em; background: #DD5F10; animation: ai-demo-caret 0.8s steps(1) infinite; }
.ai-demo__todo { list-style: none; margin: 0.6em 0 1em; padding: 0; display: grid; gap: 0.5em; font-size: 0.88em; }
.ai-demo__todo li { display: flex; gap: 0.55em; align-items: center; }
.ai-demo__todo li::before { content: ""; flex: none; width: 0.9em; height: 0.9em; border-radius: 0.25em; border: 1.5px solid rgba(10, 29, 42, 0.3); }
.ai-demo__toggle { display: flex; align-items: center; justify-content: space-between; gap: 0.6em; padding: 0.65em 0.75em; border-radius: 0.7em; background: #0A1D2A; color: #FFFFFF; font-weight: 600; font-size: 0.9em; }
.ai-demo__toggle i { position: relative; flex: none; width: 2.3em; height: 1.3em; border-radius: 1em; background: rgba(255, 255, 255, 0.22); transition: background-color 0.3s ease; }
.ai-demo__toggle i::after { content: ""; position: absolute; top: 0.18em; left: 0.18em; width: 0.94em; height: 0.94em; border-radius: 50%; background: #FFFFFF; transition: translate 0.3s var(--ease); }
.ai-demo__toast { position: absolute; left: 4.9em; bottom: 1.5em; display: inline-flex; align-items: center; gap: 0.5em; padding: 0.6em 0.95em; border-radius: 0.6em; background: #0A1D2A; color: #FFFFFF; font-weight: 600; box-shadow: 0 0.8em 1.8em -0.8em rgba(10, 29, 42, 0.7); transition: opacity 0.35s ease, translate 0.45s var(--ease); }
.ai-demo__toast svg { width: 1.1em; height: 1.1em; padding: 0.15em; border-radius: 50%; background: #DD5F10; }
/* screen-recording scrubber along the window's bottom edge */
.ai-demo__progress { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: rgba(10, 29, 42, 0.06); }
.ai-demo__progress i { display: block; height: 100%; background: #DD5F10; transform-origin: left; transform: scaleX(1); }
/* the demo's own pointer: a plain white system arrow, unlike the band's robot cursor */
.ai-demo__pointer { position: absolute; top: 0; left: 0; z-index: 2; width: 18px; height: 22px; pointer-events: none; opacity: 0; transition: transform 1s cubic-bezier(0.65, 0, 0.35, 1), opacity 0.3s ease; }
.ai-demo__pointer svg { display: block; width: 100%; height: 100%; overflow: visible; filter: drop-shadow(0 2px 2px rgba(10, 29, 42, 0.4)); }
.ai-demo__pointer path { fill: #0A1D2A; stroke: #FFFFFF; stroke-width: 1.4; stroke-linejoin: round; }
.ai-demo__click { position: absolute; left: -12px; top: -12px; width: 26px; height: 26px; border-radius: 50%; border: 2px solid #FF8A3D; opacity: 0; }
.ai-demo__pointer.is-click .ai-demo__click { animation: ai-demo-click 0.5s ease-out; }
@keyframes ai-demo-click { from { opacity: 1; transform: scale(0.3); } to { opacity: 0; transform: scale(1.3); } }
@keyframes ai-demo-caret { 50% { opacity: 0; } }

/* steps (only once app.js has started the loop: .is-playing) */
.ai-demo.is-playing .ai-demo__line { stroke-dashoffset: 1; transition: stroke-dashoffset 1.6s cubic-bezier(0.45, 0, 0.2, 1); }
.ai-demo.is-playing .ai-demo__line--b { transition-delay: 0.15s; }
.ai-demo.is-playing .ai-demo__area { opacity: 0; transition: opacity 0.8s ease 0.9s; }
.ai-demo.is-playing .ai-demo__pt { transform: scale(0); }
.ai-demo.is-playing .ai-demo__tip { opacity: 0; transform: translateY(0.4em); }
.ai-demo.is-playing .ai-demo__toggle i { background: rgba(255, 255, 255, 0.22); }
.ai-demo.is-playing .ai-demo__toggle i::after { translate: 0 0; }
.ai-demo.is-playing .ai-demo__toast { opacity: 0; translate: 0 0.8em; }
.ai-demo.is-playing .ai-demo__pointer { opacity: 1; }
.ai-demo.is-playing .ai-demo__progress i { transform: scaleX(0); }
.ai-demo.is-playing[data-step] .ai-demo__progress i { transform: scaleX(var(--demo-progress, 0)); transition: transform 0.4s linear; }
.ai-demo.is-playing:not([data-step="0"]) .ai-demo__line { stroke-dashoffset: 0; }
.ai-demo.is-playing:not([data-step="0"]) .ai-demo__area { opacity: 1; }
.ai-demo.is-playing:not([data-step="0"]) .ai-demo__pt { transform: none; transition-delay: 1.2s; }
.ai-demo.is-playing:not([data-step="0"]) .ai-demo__pt--2 { transition-delay: 1.35s; }
.ai-demo.is-playing:not([data-step="0"]) .ai-demo__pt--3 { transition-delay: 1.5s; }
.ai-demo.is-playing[data-step="2"] .ai-demo__tip,
.ai-demo.is-playing[data-step="3"] .ai-demo__tip { opacity: 1; transform: none; }
.ai-demo.is-playing[data-step="2"] .ai-demo__pt--2,
.ai-demo.is-playing[data-step="3"] .ai-demo__pt--2 { transform: scale(1.35); transition-delay: 0s; }
.ai-demo.is-playing .ai-demo__btn.is-pressed { background: #0A1D2A; color: #FFFFFF; transform: scale(0.96); }
.ai-demo.is-playing[data-step="4"] .ai-demo__toggle i,
.ai-demo.is-playing[data-step="5"] .ai-demo__toggle i,
.ai-demo:not(.is-playing) .ai-demo__toggle i { background: #DD5F10; }
.ai-demo.is-playing[data-step="4"] .ai-demo__toggle i::after,
.ai-demo.is-playing[data-step="5"] .ai-demo__toggle i::after,
.ai-demo:not(.is-playing) .ai-demo__toggle i::after { translate: 1em 0; }
.ai-demo.is-playing[data-step="4"] .ai-demo__toast,
.ai-demo.is-playing[data-step="5"] .ai-demo__toast { opacity: 1; translate: 0 0; transition-delay: 0.3s; }
.ai-demo.is-playing.is-resetting .ai-demo__win > * { opacity: 0.0; transition: opacity 0.4s ease; }
.ai-demo:not(.is-playing) .ai-demo__progress { display: none; }
@media (max-width: 991.98px) {
    .ai-demo { padding: 2% 0 0; }
    .ai-demo__win, .ai-demo:hover .ai-demo__win { transform: none; }
}
@media (max-width: 575.98px) {
    .ai-demo__body { grid-template-columns: 2.6em minmax(0, 1fr); }
    .ai-demo__panel { display: none; }
    .ai-demo__search { display: none; }
}

/* AI pillars (#ai): one white panel at the foot of the band, overlapping
   its bottom edge by --ai-overlap into #approach (whose padding makes room
   and whose bottom traces start just under the panel). Four zones split by
   hairlines, each with a 120x80 navy/orange drawing:
     .ap-draw   outlines drawn in on reveal (pathLength="1")
     .ap-pop    nodes/fills that scale in after the outlines
     loops      gears turn, clock hands sweep, a data dot runs the trend
                line, bars breathe, a progress bar fills, bulb facets light
                in turn, signals run along the circuit
   Reveal comes from [data-reveal-group].is-visible on the panel. */
body.home { --ai-overlap: clamp(96px, 9vw, 130px); }
body.home #ai { position: relative; z-index: 2; padding-bottom: 0; overflow-x: clip; overflow-y: visible; display: flow-root; }
body.home #approach { padding-top: calc(var(--space-section) + var(--ai-overlap)); }
body.home .ai-edge--bottom .ai-edge__traces { top: calc(var(--ai-overlap) - 24px); }
@media (max-width: 600px) {
    body.home { --ai-overlap: 72px; }
}
.ai-pillars {
    position: relative;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    margin: clamp(2.5rem, 4.5vw, 4rem) 0 calc(-1 * var(--ai-overlap, 0px));
    padding: clamp(26px, 2.6vw, 38px) 0;
    border-radius: 20px;
    background: #FFFFFF;
    box-shadow: 0 2px 6px rgba(10, 29, 42, 0.05), 0 34px 70px -34px rgba(10, 29, 42, 0.4);
}
.ai-pillar { position: relative; padding: 4px clamp(20px, 2.3vw, 34px) 6px; }
.ai-pillar + .ai-pillar::before { content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 1px; background: rgba(10, 29, 42, 0.12); }
.ai-pillar__media { height: 80px; margin-bottom: 20px; }
.ai-pillar__art { display: block; width: auto; height: 100%; overflow: visible; transition: transform 0.45s var(--ease); transform-origin: left center; }
#ai .ai-pillar__label { margin: 0 0 10px; color: #0A1D2A; font-family: Inter, "Aptos", "Segoe UI", Arial, sans-serif; font-size: 15px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; }
#ai .ai-pillar p { margin: 0; color: #3A4A55; font-family: Inter, "Aptos", "Segoe UI", Arial, sans-serif; font-size: 15px; line-height: 1.6; }
@media (hover: hover) and (pointer: fine) { .ai-pillar:hover .ai-pillar__art { transform: scale(1.06); } }

/* drawing parts */
.ai-pillar__art .ap-draw,
.ai-pillar__art .ap-ticks,
.ai-pillar__art .ap-hand,
.ai-pillar__art .ap-base,
.ai-pillar__art .ap-line,
.ai-pillar__art .ap-circuit { stroke: #0A1D2A; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.ai-pillar__art .ap-ticks { stroke-width: 1.6; }
.ai-pillar__art .ap-hand--m { stroke: #DD5F10; }
.ai-pillar__art .ap-line { stroke-width: 1.8; opacity: 0.55; }
.ai-pillar__art .ap-circuit { stroke-width: 1.6; }
.ai-pillar__art .ap-dash { stroke: #DD5F10; stroke-width: 1.6; stroke-dasharray: 3 3; }
.ai-pillar__art .ap-fill-navy { fill: #0A1D2A; }
.ai-pillar__art .ap-fill-orange { fill: #DD5F10; }
.ai-pillar__art .ap-ring { fill: #FFFFFF; stroke: #0A1D2A; stroke-width: 2; }
.ai-pillar__art .ap-pie { fill: #DD5F10; transform-box: view-box; transform-origin: 74px 18px; }
.ai-pillar__art .ap-bar { fill: #DD5F10; transform-box: fill-box; transform-origin: 50% 100%; }
.ai-pillar__art .ap-data { fill: #DD5F10; stroke: #FFFFFF; stroke-width: 1.2; }
.ai-pillar__art .ap-gear { transform-box: fill-box; transform-origin: center; }
.ai-pillar__art .ap-gear--a { fill: #DD5F10; }
.ai-pillar__art .ap-gear--b { fill: #0A1D2A; }
.ai-pillar__art .ap-hand { transform-box: view-box; transform-origin: 40px 44px; }
.ai-pillar__art .ap-panel { fill: #FFFFFF; stroke: #0A1D2A; stroke-width: 2; }
.ai-pillar__art .ap-track { fill: rgba(10, 29, 42, 0.12); }
.ai-pillar__art .ap-progress { fill: #DD5F10; transform-box: fill-box; transform-origin: left center; }
.ai-pillar__art .ap-facet { stroke: #FFFFFF; stroke-width: 1; stroke-linejoin: round; }
.ai-pillar__art .ap-facet--1, .ai-pillar__art .ap-facet--4, .ai-pillar__art .ap-facet--7 { fill: #DD5F10; }
.ai-pillar__art .ap-facet--2, .ai-pillar__art .ap-facet--5 { fill: #F3A06A; }
.ai-pillar__art .ap-facet--3, .ai-pillar__art .ap-facet--6 { fill: #0A1D2A; }
.ai-pillar__art .ap-rays { stroke: #DD5F10; stroke-width: 2; stroke-linecap: round; }
.ai-pillar__art .ap-pulse { stroke: #DD5F10; stroke-width: 2.4; stroke-linecap: round; stroke-dasharray: 0.16 1; stroke-dashoffset: 0.16; opacity: 0; }

/* reveal + idle loops (motion only; without it the drawings simply sit finished) */
@media (prefers-reduced-motion: no-preference) {
    .ai-pillars .ap-draw { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 1.2s cubic-bezier(0.45, 0, 0.2, 1); }
    .ai-pillars .ap-pop, .ai-pillars .ap-gear, .ai-pillars .ap-bar, .ai-pillars .ap-pie, .ai-pillars .ap-facet, .ai-pillars .ap-win { opacity: 0; transition: opacity 0.5s ease, scale 0.6s var(--ease), translate 0.7s var(--ease); }
    .ai-pillars .ap-pop { transform-box: fill-box; transform-origin: center; scale: 0.3; }
    .ai-pillars .ap-gear { scale: 0.6; }
    .ai-pillars .ap-bar { scale: 1 0; }
    .ai-pillars .ap-win--back { translate: 0 6px; }
    .ai-pillars .ap-win--a { translate: -10px 0; }
    .ai-pillars .ap-win--b { translate: 10px 0; }
    .ai-pillars .ap-ticks, .ai-pillars .ap-hand, .ai-pillars .ap-dash, .ai-pillars .ap-base, .ai-pillars .ap-circuit, .ai-pillars .ap-rays, .ai-pillars .ap-data { opacity: 0; transition: opacity 0.6s ease 0.6s; }

    .ai-pillars.is-visible .ap-draw { stroke-dashoffset: 0; }
    .ai-pillars.is-visible .ap-pop, .ai-pillars.is-visible .ap-gear, .ai-pillars.is-visible .ap-pie, .ai-pillars.is-visible .ap-facet, .ai-pillars.is-visible .ap-win { opacity: 1; scale: 1; translate: 0 0; }
    .ai-pillars.is-visible .ap-bar { opacity: 1; scale: 1 1; }
    .ai-pillars.is-visible .ap-ticks, .ai-pillars.is-visible .ap-hand, .ai-pillars.is-visible .ap-dash, .ai-pillars.is-visible .ap-base, .ai-pillars.is-visible .ap-circuit, .ai-pillars.is-visible .ap-data { opacity: 1; }
    .ai-pillars.is-visible .ap-rays { opacity: 1; animation: ap-rays 2.4s ease-in-out 2s infinite; }
    /* each zone starts a beat after the one before (--z) */
    .ai-pillar:nth-child(2) { --z: 0.2s; }
    .ai-pillar:nth-child(3) { --z: 0.4s; }
    .ai-pillar:nth-child(4) { --z: 0.6s; }
    .ai-pillars.is-visible .ap-draw { transition-delay: var(--z, 0s); }
    .ai-pillars.is-visible .ap-ticks, .ai-pillars.is-visible .ap-hand, .ai-pillars.is-visible .ap-dash, .ai-pillars.is-visible .ap-base, .ai-pillars.is-visible .ap-circuit, .ai-pillars.is-visible .ap-rays, .ai-pillars.is-visible .ap-data { transition-delay: calc(var(--z, 0s) + 0.6s); }
    .ai-pillars.is-visible .ap-pop, .ai-pillars.is-visible .ap-gear, .ai-pillars.is-visible .ap-win--back { transition-delay: calc(var(--z, 0s) + 0.7s); }
    .ai-pillars.is-visible .ap-win--a, .ai-pillars.is-visible .ap-bar--1 { transition-delay: calc(var(--z, 0s) + 0.9s); }
    .ai-pillars.is-visible .ap-win--b, .ai-pillars.is-visible .ap-bar--2 { transition-delay: calc(var(--z, 0s) + 1.05s); }
    .ai-pillars.is-visible .ap-bar--3, .ai-pillars.is-visible .ap-pie { transition-delay: calc(var(--z, 0s) + 1.2s); }
    .ai-pillars.is-visible .ap-facet--1 { transition-delay: calc(var(--z, 0s) + 1s); }
    .ai-pillars.is-visible .ap-facet--2 { transition-delay: calc(var(--z, 0s) + 1.08s); }
    .ai-pillars.is-visible .ap-facet--3 { transition-delay: calc(var(--z, 0s) + 1.16s); }
    .ai-pillars.is-visible .ap-facet--4 { transition-delay: calc(var(--z, 0s) + 1.24s); }
    .ai-pillars.is-visible .ap-facet--5 { transition-delay: calc(var(--z, 0s) + 1.32s); }
    .ai-pillars.is-visible .ap-facet--6 { transition-delay: calc(var(--z, 0s) + 1.4s); }
    .ai-pillars.is-visible .ap-facet--7 { transition-delay: calc(var(--z, 0s) + 1.48s); }

    /* idle loops, all slow and quiet */
    .ai-pillars.is-visible .ap-gear--a { animation: ap-spin 12s linear 1.4s infinite; }
    .ai-pillars.is-visible .ap-gear--b { animation: ap-spin 9.6s linear 1.4s infinite reverse; }
    .ai-pillars.is-visible .ap-hand--m { animation: ap-spin 8s linear 1.4s infinite; }
    .ai-pillars.is-visible .ap-hand--h { animation: ap-spin 96s linear 1.4s infinite; }
    .ai-pillars.is-visible .ap-bar--1 { animation: ap-bar 3.6s ease-in-out 2s infinite; }
    .ai-pillars.is-visible .ap-bar--2 { animation: ap-bar 3.6s ease-in-out 2.3s infinite; }
    .ai-pillars.is-visible .ap-bar--3 { animation: ap-bar 3.6s ease-in-out 2.6s infinite; }
    .ai-pillars.is-visible .ap-progress { animation: ap-progress 3.4s cubic-bezier(0.65, 0, 0.35, 1) 1.6s infinite; }
    .ai-pillars.is-visible .ap-win--a { animation: ap-float 4.8s ease-in-out 2s infinite; }
    .ai-pillars.is-visible .ap-facets { animation: ap-glow 4.2s ease-in-out 2.2s infinite; }
    .ai-pillars.is-visible .ap-pulse { animation: ap-pulse 2.8s ease-in-out infinite; }
    .ai-pillars.is-visible .ap-pulse--1 { animation-delay: 2s; }
    .ai-pillars.is-visible .ap-pulse--2 { animation-delay: 2.6s; }
    .ai-pillars.is-visible .ap-pulse--3 { animation-delay: 3.2s; }
}
@media (prefers-reduced-motion: reduce) { .ai-pillar__art .ap-data { display: none; } }
@keyframes ap-spin { to { transform: rotate(360deg); } }
@keyframes ap-bar { 0%, 100% { transform: scaleY(1); } 50% { transform: scaleY(0.78); } }
@keyframes ap-progress { 0% { transform: scaleX(0); } 65%, 85% { transform: scaleX(1); } 100% { transform: scaleX(1); opacity: 0; } }
@keyframes ap-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-2px); } }
@keyframes ap-glow { 0%, 100% { opacity: 1; } 50% { opacity: 0.72; } }
@keyframes ap-rays { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
@keyframes ap-pulse { 0% { stroke-dashoffset: 0.16; opacity: 0; } 10% { opacity: 1; } 85% { opacity: 1; } 100% { stroke-dashoffset: -1; opacity: 0; } }
@media (max-width: 991.98px) {
    .ai-pillars { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 28px; }
    .ai-pillar:nth-child(3)::before { content: none; }
    .ai-pillar:nth-child(n+3) { padding-top: 30px; }
    .ai-pillar:nth-child(n+3)::after { content: ""; position: absolute; top: -14px; left: clamp(20px, 2.3vw, 34px); right: clamp(20px, 2.3vw, 34px); height: 1px; background: rgba(10, 29, 42, 0.12); }
}
@media (max-width: 575.98px) {
    .ai-pillars { grid-template-columns: 1fr; row-gap: 0; padding: 8px 0; }
    .ai-pillar { padding: 22px 22px 24px; }
    .ai-pillar + .ai-pillar::before { content: ""; left: 22px; right: 22px; top: 0; bottom: auto; width: auto; height: 1px; }
    .ai-pillar:nth-child(n+3) { padding-top: 22px; }
    .ai-pillar:nth-child(n+3)::after { content: none; }
    .ai-pillar__media { height: 64px; margin-bottom: 14px; }
}
@media (prefers-reduced-motion: reduce) { .ai-demo__win { transition: none; } }

.ai-feature-row .col { position: relative; }
@media (min-width: 992px) {
    .ai-feature-row .col:not(:first-child)::before {
        content: "";
        position: absolute;
        left: 0;
        top: 0.25rem;
        bottom: 0.25rem;
        width: 1px;
        background: rgba(255, 255, 255, 0.25);
    }
}
/* .ai-feature* is the service detail page's #intelligence band (Home's
   #ai uses .ai-pillar*, above). */
.ai-feature__icon { display: inline-flex; align-items: center; justify-content: center; width: 2.5rem; height: 2.5rem; margin-bottom: 1.1rem; color: #fff; }
.ai-feature__icon svg { width: 1.875rem; height: 1.875rem; }
.ai-feature__label { font-size: 14px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; margin-bottom: 0.6rem; color: #fff; }
/* Was 1.02rem (16.32px) -- larger than #ai .lead's own 16px main paragraph,
   backwards for a secondary/pillar paragraph. */
.ai-feature p { color: rgba(255, 255, 255, 0.85); font-size: 0.875rem; line-height: 1.5; margin: 0; }

/* --- approach visual (#approach) -------------------------------------------
   A systems illustration beside the intro (approach-system.webp, 1024x572),
   its edges feathered into the section's ivory with a radial mask. On reveal
   it unveils left to right while settling from a slight zoom; afterwards it
   floats very gently, its two orange signal points ping in turn, and a faint
   scan line passes over it every few seconds. A thin navy/orange swoosh then
   leads from the intro into the stage list. */
#approach { overflow-x: clip; }
.approach-visual {
    position: relative;
    margin-right: calc(-1 * clamp(0px, 4vw, 64px));
    -webkit-mask-image: radial-gradient(ellipse 54% 56% at 50% 50%, #000 52%, transparent 96%);
    mask-image: radial-gradient(ellipse 54% 56% at 50% 50%, #000 52%, transparent 96%);
}
.approach-visual__img { display: block; width: 100%; height: auto; }
.approach-visual__sig { position: absolute; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%; background: #FF650B; }
.approach-visual__sig::after { content: ""; position: absolute; inset: -2px; border-radius: 50%; border: 1.5px solid #FF650B; opacity: 0; }
.approach-visual__sig--1 { left: 59.3%; top: 68.4%; }
.approach-visual__sig--2 { left: 77.4%; top: 80.2%; }
.approach-visual__scan { position: absolute; inset: 0; pointer-events: none; opacity: 0; background: linear-gradient(100deg, transparent 42%, rgba(255, 101, 11, 0.08) 49%, rgba(255, 255, 255, 0.5) 50%, rgba(255, 101, 11, 0.08) 51%, transparent 58%) -60% 0 / 220% 100% no-repeat; }
@keyframes approach-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
@keyframes approach-ping { 0% { opacity: 0.9; transform: scale(1); } 80%, 100% { opacity: 0; transform: scale(3.2); } }
@keyframes approach-scan { 0%, 55% { background-position: 160% 0; } 100% { background-position: -60% 0; } }
@media (prefers-reduced-motion: no-preference) {
    #approach .approach-visual[data-reveal] { opacity: 1; transform: none; transition: none; }
    .approach-visual__img { clip-path: inset(0 100% 0 0); scale: 1.06; opacity: 0; transition: clip-path 1.4s cubic-bezier(0.65, 0, 0.35, 1), scale 1.8s var(--ease), opacity 0.6s ease; }
    .approach-visual.is-visible .approach-visual__img { clip-path: inset(0 0 0 0); scale: 1; opacity: 1; animation: approach-float 9s ease-in-out 2s infinite; }
    .approach-visual__sig { opacity: 0; scale: 0.4; transition: opacity 0.4s ease 1.5s, scale 0.5s var(--ease) 1.5s; }
    .approach-visual__sig--2 { transition-delay: 1.7s; }
    .approach-visual.is-visible .approach-visual__sig { opacity: 1; scale: 1; animation: approach-float 9s ease-in-out 2s infinite; }
    .approach-visual.is-visible .approach-visual__sig::after { animation: approach-ping 2.8s ease-out 2s infinite; }
    .approach-visual.is-visible .approach-visual__sig--2::after { animation-delay: 3.4s; }
    .approach-visual.is-visible .approach-visual__scan { opacity: 1; transition: opacity 0.4s ease 2s; animation: approach-scan 7s ease-in-out 2.4s infinite; }
}
@media (max-width: 991.98px) { .approach-visual { margin: 8px 0 0; } }

.approach-swoosh { display: block; width: 100vw; max-width: none; height: clamp(46px, 5vw, 80px); margin: clamp(8px, 2vw, 24px) 0 clamp(18px, 3vw, 40px) calc(50% - 50vw); }
.approach-swoosh__navy { fill: #0A1D2A; }
.approach-swoosh__orange { fill: none; stroke-width: 3; stroke-linecap: round; }

/* --- process steps: number, chevron to the next stage, label, line ---------- */
.process-steps { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: clamp(16px, 2.2vw, 32px); }
.process-step { position: relative; padding: 4px 0; }
.process-step__top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
.process-step__num {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2.6rem;
    height: 2.6rem;
    border-radius: 50%;
    background: var(--color-accent);
    color: #fff;
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 15px;
    transition: background-color 0.3s ease, box-shadow 0.3s ease;
}
.process-step__chevron { display: inline-flex; margin-right: clamp(0px, 1vw, 12px); color: #9AA8B6; }
.process-step__chevron svg { width: 18px; height: 18px; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; transition: translate 0.3s var(--ease); }
.process-step__title { font-size: 15px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; color: var(--color-ink); margin-bottom: 0.5rem; }
@media (hover: hover) and (pointer: fine) {
    .process-step:hover .process-step__num { background: #0A1D2A; box-shadow: 0 0 0 5px rgba(255, 101, 11, 0.16); }
    .process-step:hover .process-step__chevron svg { translate: 3px 0; }
}
@media (prefers-reduced-motion: no-preference) {
    .approach-swoosh__orange { stroke-dasharray: 1; stroke-dashoffset: 1; transition: stroke-dashoffset 1.4s cubic-bezier(0.45, 0, 0.2, 1); }
    .approach-swoosh__navy { opacity: 0; transition: opacity 0.8s ease; }
    #approach:has(.process-steps.is-visible) .approach-swoosh__orange { stroke-dashoffset: 0; }
    #approach:has(.process-steps.is-visible) .approach-swoosh__navy { opacity: 1; }
}
@media (max-width: 991.98px) {
    .process-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 28px; }
    .process-step:nth-child(3) .process-step__chevron { visibility: hidden; }
}
@media (max-width: 575.98px) {
    .process-steps { grid-template-columns: 1fr; gap: 0; }
    .process-step { display: grid; grid-template-columns: auto 1fr; column-gap: 16px; padding: 16px 0; border-top: 1px solid rgba(10, 29, 42, 0.1); }
    .process-step:first-child { border-top: 0; }
    .process-step__top { grid-row: span 2; margin: 0; align-self: start; }
    .process-step__chevron { display: none; }
    .process-step__title { margin-top: 4px; }
}

/* --- business-challenge picker --------------------------------------------
   Reference: a flat list (no per-item card/box) -- a hairline divider below
   each row instead, within the existing 2-col grid (each column gets its
   own stack of dividers, which is exactly what a per-item border-bottom
   produces with no structural changes). */
.challenge-item {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    width: 100%;
    /* Matches the reference's own min-height:88px -- without it the row is
       only as tall as its padding + one text line (~50-55px), noticeably
       squatter than the reference's list. */
    min-height: 88px;
    background: transparent;
    border: 0;
    border-bottom: 1px solid #E6EAED;
    padding: 1rem 0;
    font-family: var(--font-text);
    color: #091E30;
    text-decoration: none;
    font-weight: 400;
    font-size: 14px;
    line-height: 1.4;
    text-align: left;
    transition: color 0.2s var(--ease);
}
.challenge-item__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: #FFF0E4;
    color: #E55A0C;
}
.challenge-item__icon svg { width: 24px; height: 24px; }
.challenge-item__label { flex: 1; }
.challenge-item__arrow { flex-shrink: 0; font-size: 14px; color: #93A1AA; transition: color 0.2s var(--ease); }
.challenge-item:hover { color: var(--color-accent); }
.challenge-item:hover .challenge-item__arrow { color: var(--color-accent); }
/* Matches the reference's own .needs{gap:0 28px} -- Bootstrap's g-3 utility
   (templates/web/home.html: row row-cols-1 row-cols-sm-2 g-3) applies a
   uniform 1rem gutter in both directions; the reference has *no* vertical
   gap at all (rows are separated only by their own border-bottom) and a
   wider, narrower-at-tablet horizontal one. #challenge-scoped so this can't
   touch any other .g-3 row on the page. */
#challenge .row-cols-sm-2 { --bs-gutter-x: 28px; --bs-gutter-y: 0; }
@media (max-width: 1150px) {
    #challenge .row-cols-sm-2 { --bs-gutter-x: 20px; }
}
@media (max-width: 575.98px) {
    /* Matches the reference's own narrowest-mobile min-height. */
    .challenge-item { min-height: 78px; }
}

/* --- industries strip (dark) --------------------------------------------------
   Fixed text on the left, a continuously moving icon+label strip on the
   right. The automatic motion is a plain CSS animation (translateX 0 to
   -50% on .industries-carousel__track, which is exactly twice one item
   sequence wide since the sequence is duplicated in the DOM) -- reliable
   and GPU-composited, unlike a JS rAF loop nudging scrollLeft every frame,
   which is at the mercy of how often the browser actually schedules rAF
   callbacks. .industries-carousel__viewport is the real overflow-x:auto,
   focusable element beneath it, so native wheel/drag/touch/keyboard
   scrolling still work; app.js pauses the CSS animation
   (.industries-carousel.is-paused, animation-play-state) whenever the user
   is actively interacting with the viewport or has clicked the pause
   button -- pausing an animation freezes it exactly where it is, so
   resuming continues from that position rather than restarting, with no
   extra bookkeeping needed. */
/* Matches the reference's own exact 50px/40px (<=600px) padding -- the
   previous clamp(1.25rem,2.5vw,2rem) (20-32px) left this section
   noticeably more cramped than the reference at every width. */
.industries-band { background: #09222E; color: #fff; padding-block: var(--space-section-sm); }
#industries h2 { font-family: var(--font-display); font-size: var(--fs-h2); font-weight: 700; line-height: 1.18; letter-spacing: -0.045em; color: #FFFFFF; }
.industries-band .eyebrow { color: #FF8B37; }
.industries-band .lead { color: rgba(255, 255, 255, 0.75); }
.industries-band__inner { display: flex; align-items: center; }
/* Matches the reference's own fixed 340px first column (not a percentage-
   based cap, which was rendering noticeably wider than the reference at
   most desktop widths). */
.industries-band__intro { flex: 0 0 auto; width: 340px; max-width: 42%; }
.industries-band__intro h2 { white-space: nowrap; }
.industries-carousel { display: flex; flex-direction: column; gap: 0.75rem; flex: 1 1 auto; max-width: 58rem; min-width: 0; margin-inline: auto; }
.industries-carousel__viewport {
    overflow-x: auto;
    overflow-y: hidden;
    scroll-behavior: auto;
    touch-action: pan-x;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    mask-image: linear-gradient(90deg, transparent 0, #000 1.5rem, #000 calc(100% - 1.5rem), transparent 100%);
}
.industries-carousel__viewport::-webkit-scrollbar { display: none; }
.industries-carousel__viewport:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 6px; border-radius: 4px; }
.industries-carousel__track {
    display: flex;
    align-items: stretch;
    width: max-content;
    animation: industries-marquee 30s linear infinite;
}
.industries-carousel.is-paused .industries-carousel__track { animation-play-state: paused; }
@keyframes industries-marquee {
    from { transform: translateX(0); }
    to { transform: translateX(-50%); }
}
.industries-carousel__item {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    flex-shrink: 0;
    font-family: var(--font-text);
    color: #FFFFFF;
    font-weight: 400;
    font-size: 14px;
    line-height: 1.45;
}
.industries-carousel__label {
    /* A flex child's default min-width is its unwrapped content width, so
       without this it would never actually wrap no matter how narrow
       max-width is -- this lets it shrink so wrapping can kick in. */
    min-width: 0;
    max-width: 13rem;
    white-space: normal;
}
.industries-carousel__item + .industries-carousel__item {
    border-left: 1px solid rgba(255, 255, 255, 0.18);
    padding-left: 1.5rem;
    margin-left: 1.5rem;
}
.industries-carousel__icon { display: inline-flex; color: #F5B07C; flex-shrink: 0; }
.industries-carousel__icon svg { width: 31px; height: 31px; }
.industries-pause {
    display: inline-flex;
    align-items: center;
    align-self: flex-end;
    gap: 0.5rem;
    background: transparent;
    border: 0;
    padding: 0.2rem;
    color: rgba(255, 255, 255, 0.65);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
}
.industries-pause:hover { color: #fff; }
/* a full 44px touch target, without changing how the control looks */
.industries-pause { min-height: 44px; }
.industries-pause:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; border-radius: 4px; }
.industries-pause-icon { display: inline-flex; }
.industries-pause-icon svg { width: 0.85rem; height: 0.85rem; }
@media (max-width: 991.98px) {
    .industries-band__inner { gap: 1.25rem; }
    /* Matches the reference's own 280px at this tier. */
    .industries-band__intro { width: 280px; max-width: 40%; }
    .industries-band__intro h2 { white-space: normal; }
    .industries-carousel__item + .industries-carousel__item { padding-left: 1.1rem; margin-left: 1.1rem; }
}
@media (max-width: 767.98px) {
    .industries-band__inner { flex-direction: column; align-items: stretch; gap: 2rem; }
    .industries-band__intro { width: 100%; }
    #industries h2 { font-size: var(--fs-h2); }
    .industries-carousel { max-width: 100%; margin-inline: 0; }
    .industries-carousel__label { max-width: 10rem; }
}
@media (prefers-reduced-motion: reduce) {
    .industries-carousel__track { animation: none; }
    .industries-pause { display: none; }
}

/* --- technology training ------------------------------------------------------
   Clean white band (no alt/gray fill, no frame border). The photo is sized
   down and right-aligned within its column -- narrower than the column
   itself -- and the diagonal accent is an absolutely-positioned SVG (two
   strokes, pale-then-orange) that overlaps the photo's left edge with
   z-index, rather than reserved padding pushing the two apart. Cards are
   plain links styled as fixed-size white tiles so a wrapping label (e.g.
   "Python & Django") centers within the tile instead of growing it. */
.training-band { background: linear-gradient(110deg, #FFFFFF 20%, #FFFCF8 100%); }
.training-content { padding-left: 1rem; }
/* Exact client spec for this section's heading/paragraph only. #training h2
   (ID beats the shared body.home h2 rule's specificity -- .training-content
   h2 alone isn't enough: body.home h2's two element selectors outweigh its
   one extra class). .training-content/.lead needs no such scoping -- two
   classes already beats the base one-class .lead rule. */
#training h2 {
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1.16;
    letter-spacing: -0.045em;
    color: #091E30;
}
/* Bootstrap's own .lead sets font-weight:300. */
/* 16px, not 17px -- matches the reference's own value for this section's
   lead paragraph exactly (the 1.65 line-height ratio was already right). */
.training-content .lead { font-size: 16px; font-weight: 400; line-height: 1.65; max-width: none; color: #586C7D; }
@media (max-width: 991.98px) {
    #training h2 { font-size: var(--fs-h2); }
}
/* Matches the reference's own grid of 5 equal columns (not a flex-wrap with
   a fixed max-width cap) and its 12px gap. */
.training-tracks { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; margin-block: 1.5rem; }
.training-track {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    box-sizing: border-box;
    /* Matches the reference's own min-height:113px/padding exactly, instead
       of a taller fixed height. */
    min-height: 113px;
    padding: 17px 8px 14px;
    background: #fff;
    border: 1px solid #efeeec;
    border-radius: 13px;
    box-shadow: var(--shadow-sm);
    text-decoration: none;
    color: var(--color-ink);
    text-align: center;
    transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
/* Guarded for the same stuck-on-touch reason as the other lift effects
   above. */
@media (hover: hover) and (pointer: fine) {
    .training-track:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
}
.training-track img { width: 34px; height: 34px; object-fit: contain; }
.training-track__label { font-size: 14px; font-weight: 600; line-height: 1.3; }
.training-track::after { content: ""; display: block; width: 1.625rem; height: 2px; background: var(--color-accent); border-radius: 2px; }
.training-media { position: relative; }
.training-media__img {
    position: relative;
    z-index: 0;
    display: block;
    width: min(39rem, 100%);
    margin-left: auto;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: 1rem;
    /* The bottom-left corner recedes on the same diagonal as the accent
       beside it, so the line reads as continuing the image's own edge
       rather than just sitting next to a plain rectangle. */
    clip-path: polygon(0 0, 100% 0, 100% 100%, 7% 100%);
}
/* The diagonal is a wide/thick two-stroke SVG (pale behind, orange in
   front) straddling the photo's left edge, running the full height of
   the photo -- flush with its top-left corner down to its bottom edge. */
.training-media__diagonal {
    position: absolute;
    z-index: 1;
    top: -10px;
    height: calc(100% + 10px);
    /* Once the photo is at its 100% clamp (stacked/mobile layouts, no
       slack left of it), this would otherwise go negative and push the
       accent off the left edge -- clamp it to 0 so it stays flush with
       the photo's own left edge instead of disappearing offscreen. */
    left: max(0px, calc(100% - min(39rem, 100%) - 0.9rem));
    width: 3.5rem;
    pointer-events: none;
}
@media (max-width: 991.98px) {
    .training-content { padding-left: 1.5rem; }
}
@media (max-width: 575.98px) {
    /* Matches the reference's own 3-column mobile layout (not 2). */
    .training-tracks { grid-template-columns: repeat(3, 1fr); gap: 12px; }
}

/* --- closing contact band: photo background, form on a dark glass card ------
   Scoped to the --contact modifier only -- the plain .cta-band gradient is
   reused on many other pages (services, training, careers...) and must
   stay untouched. The photo sits on its own ::before: a combined slow
   zoom + pan + a hair of rotation (transform, not background-position, so
   it stays GPU-composited) reads as gentle skyline/water drift rather than
   a flat zoom. The ::after darkening overlay's orange glow drifts slightly
   too, for a touch of "light movement", independently of the photo. Both
   sit behind the .container via z-index; prefers-reduced-motion freezes
   both. */
.cta-band--contact { position: relative; overflow: hidden; text-align: left; background: var(--color-ink); padding-block: var(--space-section-sm); }
/* The service detail page's own closing contact section reuses this exact
   markup -- same classes, even the same id="contact" -- so an ID selector
   alone can't tell the two apart; body.home disambiguates every override
   below, so none of this touches that page's own contact section. */
body.home .cta-band--contact {
    /* Matches the reference's own exact background colour (it only shows
       at the photo's very edges, under the -6% inset of ::before below). */
    background: #051D2C;
    /* Matches the reference's own fixed (asymmetric) padding exactly,
       rather than a symmetric clamp. */
    padding-block: var(--space-section-sm);
}
@media (max-width: 900px) {
    body.home .cta-band--contact { padding-block: var(--space-section-sm); }
}
@media (max-width: 600px) {
    body.home .cta-band--contact { padding-block: var(--space-section-sm); }
}
/* Motion stopped on Home specifically -- the shared .cta-band--contact
   background still pans/drifts elsewhere (e.g. the service page's own
   contact section), this just holds both layers still here. */
body.home .cta-band--contact::before,
body.home .cta-band--contact::after {
    animation: none;
}
/* Home's own background photo + wash, matching the reference's own
   .contact-skyline treatment exactly (color stops taken directly from its
   CSS) rather than the shared default's radial glow + diagonal darken --
   scoped here, not on the shared rule above, so the service page's own
   contact section (a different photo entirely) is untouched.
   The horizontal gradient is a subtle side vignette (darkest at the left/
   right edges, clearest around the middle); the vertical one keeps the
   sky dark at the very top and the water dark at the very bottom while
   leaving the skyline band itself in the middle nearly unwashed, so the
   photo's own sunset colour -- the same warm orange as the "what's next"
   accent text -- reads clearly instead of being muted under a uniform
   dark scrim. */
body.home .cta-band--contact::before {
    /* The shared rule's inset:-6% exists only to feed the pan/zoom
       animation (so it never reveals an edge while scaling/drifting);
       with that animation turned off above, the same oversizing just
       meant background-size:cover zoomed the photo in further than
       needed, pushing a slice of it past the section's edges on every
       side. Reset to 0 so the full photo actually shows. */
    inset: 0;
    /* contact_bg_tech.webp: a navy city at dusk with a dark engineered panel
       on the right where the form sits. Darkened most behind the copy on the
       left and along the bottom, lightest through the middle so the skyline
       still reads; the navy is the palette's own #0A1D2A. */
    background:
        linear-gradient(90deg, rgba(10, 29, 42, 0.74) 0%, rgba(10, 29, 42, 0.4) 38%, rgba(10, 29, 42, 0.16) 58%, rgba(10, 29, 42, 0.4) 100%),
        linear-gradient(180deg, rgba(10, 29, 42, 0.35) 0%, transparent 38%, rgba(10, 29, 42, 0.72) 100%),
        url("/static/img/hero/contact_bg_tech.d3012510d422.webp") center / cover no-repeat;
}
body.home .cta-band--contact::after { background: none; }
.cta-band--contact::before {
    content: "";
    position: absolute;
    inset: -6%;
    background: url("/static/img/hero/contact_bg.78b12f3f7d14.webp") center top / cover no-repeat;
    animation: cta-band-bg-pan 22s ease-in-out infinite alternate;
    will-change: transform;
}
.cta-band--contact::after {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(50rem 30rem at 20% 20%, rgba(255, 150, 60, 0.3), transparent 55%),
        linear-gradient(190deg, rgba(9, 30, 48, 0.55) 0%, rgba(9, 30, 48, 0.88) 100%);
    background-repeat: no-repeat;
    animation: cta-band-glow-drift 17s ease-in-out infinite alternate;
}
.cta-band--contact > .container { position: relative; z-index: 1; }
@keyframes cta-band-bg-pan {
    /* Y stays 0/slightly positive (never negative) so the pan never drags
       the skyline top further out of frame -- only horizontal drift plus
       a light zoom. */
    from { transform: scale(1.01) translate(-0.5%, 0) rotate(-0.3deg); }
    to { transform: scale(1.07) translate(-2.5%, 0.5%) rotate(0.3deg); }
}
@keyframes cta-band-glow-drift {
    from { background-position: 0% 0%, 0 0; }
    to { background-position: 12% 10%, 0 0; }
}
@media (prefers-reduced-motion: reduce) {
    .cta-band--contact::before, .cta-band--contact::after { animation: none; }
}

.cta-band--contact .cta-band__lead { margin-inline: 0; }
/* Matches the reference's own .contact-grid{grid-template-columns:1fr 1.08fr}
   ratio (48.08/51.92, close to even) -- Bootstrap's col-lg-5/col-lg-7 (5/7,
   41.7/58.3) gives the form column noticeably more of the row than the
   reference does, at the text column's expense. body.home-scoped like the
   rest of this section (id="contact" also exists on the service page,
   which keeps its own col-lg-5/7 split). */
@media (min-width: 992px) {
    body.home #contact .row > .col-lg-5 { flex: 0 0 auto; width: 48.08%; }
    body.home #contact .row > .col-lg-7 { flex: 0 0 auto; width: 51.92%; }
}
/* Same body.home scoping as the background override above, for the same
   reason (this section's id="contact" also exists on the service page). */
body.home #contact h2 {
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1.16;
    letter-spacing: -0.04em;
    color: #FFFFFF;
}
body.home #contact h2 .text-accent { color: #FF851C; }
body.home .cta-band__lead {
    font-size: 16px;
    /* Bootstrap's own .lead sets font-weight:300. */
    font-weight: 400;
    line-height: 1.7;
    color: #D1DFE8;
}

@media (max-width: 991.98px) {
    body.home #contact h2 { font-size: var(--fs-h2); }
}
.cta-band__form { background: #fff; border-radius: var(--radius-lg); padding: 1.75rem; box-shadow: var(--shadow-lg); }
.cta-band__form .contact-form .form-label { color: var(--color-text); }
.cta-band--contact .cta-band__form {
    background: rgba(9, 30, 48, 0.55);
    border: 1px solid rgba(255, 255, 255, 0.16);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    padding: clamp(1.75rem, 3vw, 2.5rem);
}
/* Solid, not glass: the translucent background + backdrop-filter above let
   the skyline show through, which read as a "zoomed"/oversized glass panel
   rather than a normal opaque card. Home-scoped (the service page's own
   contact form keeps the glass effect as before) -- fully opaque navy, no
   blur, tighter padding so the panel itself reads smaller too. */
body.home .cta-band--contact .cta-band__form {
    /* Matches the reference's own translucent navy exactly (not fully
       opaque -- its 0.918 alpha still reads as solid against the dark
       skyline behind it). */
    background: rgba(3, 29, 43, 0.918);
    border-radius: 14px;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    padding: clamp(1.5rem, 2.25vw, 1.875rem);
}
/* Narrower than the col-lg-7 column it sits in (which would otherwise
   stretch it edge-to-edge) and pinned to the column's right edge -- same
   "cap width, push right" pattern used for #solutions .lead elsewhere in
   this file -- so the card reads as a compact panel next to the text
   instead of a wide block, matching the reference. Scoped to >=992px,
   the same breakpoint where col-lg-5/col-lg-7 actually go side-by-side:
   below that the columns stack to 100% width already (Bootstrap's own
   .row > * default), and capping+right-pinning the form there too would
   leave it floating with an odd empty gap on its left instead of filling
   the stacked column naturally. Home-scoped only; the service page's own
   contact form keeps filling its column as before. */
@media (min-width: 992px) {
    body.home .cta-band--contact .cta-band__form {
        /* Matches the reference's own 635px exactly. */
        max-width: 635px;
        margin-left: auto;
    }
}
.cta-band--contact .cta-band__form h3 { color: #fff; }
.cta-band--contact .cta-band__form .meta { color: rgba(255, 255, 255, 0.75); }
.cta-band--contact .contact-form .form-label { color: rgba(255, 255, 255, 0.85); font-weight: 600; font-size: 14px; }
.cta-band--contact .contact-form .form-control,
.cta-band--contact .contact-form .form-select {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.25);
    color: #fff;
}
.cta-band--contact .contact-form .form-control::placeholder { color: rgba(255, 255, 255, 0.45); }
.cta-band--contact .contact-form .form-control:focus,
.cta-band--contact .contact-form .form-select:focus {
    background: rgba(255, 255, 255, 0.1);
    border-color: var(--color-accent);
    color: #fff;
    box-shadow: 0 0 0 0.2rem rgba(255, 101, 11, 0.25);
}
/* Home's own enquiry form, matching the reference's lighter label weight and
   smaller field text -- body.home-scoped (the shared rules above are also
   used by the service page's own contact form, which keeps its current
   look). Reference bumps field text to 16px under 600px specifically to
   avoid iOS Safari's zoom-on-focus for sub-16px inputs; same breakpoint
   here. */
body.home .cta-band--contact .contact-form .form-label { color: #D1DCE3; font-weight: 400; font-size: 14px; }
body.home .cta-band--contact .contact-form .form-control,
body.home .cta-band--contact .contact-form .form-select,
body.home .cta-band--contact .contact-form .form-control::placeholder {
    font-size: 14px;
}
@media (max-width: 600px) {
    body.home .cta-band--contact .contact-form .form-control,
    body.home .cta-band--contact .contact-form .form-select {
        font-size: 16px;
    }
}
/* Home's "What do you need help with?" dropdown: same glass fill + border as
   the other fields (inherited from the shared rules above), clearly visible
   white text, and a small white down-arrow. The shared `background:`
   shorthand above wipes Bootstrap's own chevron (dark, so invisible on this
   dark form anyway), hence it is re-supplied here as background-image only. */
body.home .cta-band--contact .contact-form #home-contact-type,
body.home .cta-band--contact .contact-form #home-contact-type:focus {
    color: #fff;
    background-image: var(--select-chevron-light);
    background-repeat: no-repeat;
    background-position: right 0.75rem center;
    background-size: 12px 12px;
}
body.home .cta-band--contact .contact-form #home-contact-type option {
    background-color: #0f2a3d;
    color: #fff;
}

/* -- service detail page's own contact section ----------------------------- */
body.service-page .cta-band--contact { background: #062235; padding: var(--space-section-sm) 0; position: relative; overflow: hidden; }
body.service-page .cta-band--contact::before { background: none; animation: none; }
body.service-page .cta-band--contact::after { background: none; }
.svc-contact__ribbon { position: absolute; right: 3%; top: -110px; width: 330px; height: 760px; background: #cc641f; border-radius: 55% 45% 48% 40%; transform: rotate(-22deg); opacity: 0.65; box-shadow: inset 40px 0 70px #fdad74; pointer-events: none; }
.svc-contact__grid { position: relative; display: grid; grid-template-columns: 1fr 1.08fr; gap: 90px; align-items: center; }
body.service-page #contact h2 {
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1.16;
    letter-spacing: -0.03em;
    color: #fff;
}
.svc-contact__copy > p { font-size: 15px; margin-top: 23px; max-width: 470px; color: rgba(255, 255, 255, 0.8); }
.svc-contact__copy > .btn { margin-top: 26px; }
.svc-contact__details { display: grid; gap: 16px; margin-top: 31px; padding-top: 24px; border-top: 1px solid rgba(255, 255, 255, 0.14); max-width: 330px; font-size: 14px; color: #D1DFE8; }
.svc-contact__details a { color: #D1DFE8; text-decoration: none; }
.svc-contact__details a:hover { color: var(--color-accent-light); }
.svc-contact__details span { font-size: 14px; color: #adbfcc; }
body.service-page .cta-band--contact .cta-band__form {
    background: rgba(8, 35, 55, 0.86);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(175, 121, 85, 0.34);
    border-radius: 15px;
    padding: 27px;
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.07);
}
body.service-page .cta-band--contact .cta-band__form h3 { color: #fff; font-size: var(--fs-h3); margin-bottom: 26px; }
body.service-page .cta-band--contact .contact-form .row { --bs-gutter-x: 20px; --bs-gutter-y: 19px; }
body.service-page .cta-band--contact .contact-form .form-label { color: #d6e1e8; font-weight: 400; font-size: 14px; }
body.service-page .cta-band--contact .contact-form .form-control {
    font-size: 14px;
    background: rgba(14, 42, 58, 0.79);
    border: 1px solid #4d6575;
    border-radius: 4px;
    color: #fff;
    min-height: 43px;
    padding: 12px;
}
body.service-page .cta-band--contact .contact-form textarea.form-control { min-height: 91px; resize: vertical; }
body.service-page .cta-band--contact .contact-form .form-control::placeholder { color: #98afbf; }
body.service-page .cta-band--contact .contact-form .form-control:focus {
    background: rgba(14, 42, 58, 0.95);
    border-color: var(--color-accent);
    color: #fff;
    box-shadow: 0 0 0 0.2rem rgba(255, 101, 11, 0.25);
}
body.service-page .cta-band--contact .cta-band__form .btn-primary { width: auto; min-width: 200px; font-size: 14px; margin-top: 20px; }
.form-note { font-size: 14px; line-height: 1.6; color: var(--color-muted); margin-top: 0.6rem; }
.cta-band--contact .cta-band__form .form-note { color: rgba(255, 255, 255, 0.65); }
body.service-page .cta-band--contact .cta-band__form .form-note { font-size: 14px; margin-top: 12px; }
body.service-page .cta-band--contact .cta-band__form .form-note + .form-note { margin-top: 4px; }
body.home .cta-band--contact .cta-band__form .form-note { color: #8FAABA; font-size: 14px; }
@media (max-width: 1150px) {
    .svc-contact__grid { gap: 45px; }
    body.service-page #contact h2 { font-size: var(--fs-h2); }
    body.service-page .cta-band--contact .cta-band__form { padding: 23px; }
    body.service-page .cta-band--contact .contact-form .row { --bs-gutter-y: 16px; }
}
@media (max-width: 850px) {
    .svc-contact__grid { gap: 30px; }
    body.service-page #contact h2 { font-size: var(--fs-h2); }
    .svc-contact__copy > p { font-size: 14px; }
    body.service-page .cta-band--contact .contact-form .col-md-6 { flex: 0 0 100%; max-width: 100%; }
    body.service-page .cta-band--contact .contact-form .row { --bs-gutter-y: 15px; }
    body.service-page .cta-band--contact .cta-band__form h3 { font-size: var(--fs-h3); }
    body.service-page .cta-band--contact .cta-band__form { padding: 21px; }
}
@media (max-width: 680px) {
    body.service-page .cta-band--contact { padding: var(--space-section-sm) 0; }
    .svc-contact__grid { grid-template-columns: 1fr; gap: 35px; }
    body.service-page #contact h2 { font-size: var(--fs-h2); }
    .svc-contact__copy > p { font-size: 14px; }
    .svc-contact__copy > .btn { margin-top: 23px; font-size: 14px; }
    .svc-contact__details { margin-top: 25px; padding-top: 20px; font-size: 14px; }
    body.service-page .cta-band--contact .cta-band__form { padding: 25px 20px; border-radius: 10px; }
    body.service-page .cta-band--contact .cta-band__form h3 { font-size: var(--fs-h3); }
    body.service-page .cta-band--contact .contact-form .row { --bs-gutter-y: 19px; }
    body.service-page .cta-band--contact .contact-form .form-label { font-size: 14px; }
    body.service-page .cta-band--contact .contact-form .form-control { font-size: 16px; min-height: 46px; }
    body.service-page .cta-band--contact .cta-band__form .btn-primary { width: 100%; font-size: 14px; }
    body.service-page .cta-band--contact .cta-band__form .form-note { font-size: 14px; line-height: 1.6; }
    .svc-contact__ribbon { right: -100px; top: 80px; opacity: 0.28; }
}

/* ======================================================================
   Services listing (/services/) and the Web Development service page
   ====================================================================== */

/* -- listing cards -------------------------------------------------------- */
.service-card { display: flex; flex-direction: column; height: 100%; padding: clamp(1.5rem, 3vw, 2.25rem); border: 1px solid var(--color-border); border-radius: var(--radius-lg); background: #fff; transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease); }
.service-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.service-card__tag { display: flex; align-items: baseline; gap: 0.5rem; font-weight: 700; font-size: 14px; letter-spacing: 0.08em; color: var(--color-accent); text-transform: uppercase; margin-bottom: 0.9rem; }
.service-card__tag b { color: var(--color-ink); font-size: 18px; letter-spacing: normal; }
.service-card__title { font-size: 21px; font-weight: 700; margin-bottom: 0.6rem; }
.service-card__desc { color: var(--color-muted); flex: 1 0 auto; margin-bottom: 1.5rem; }

/* -- shared dark band: a left-aligned variant of .cta-band's ink gradient,
   used by the detail page's approach/foundations/intelligence sections
   (which need a two-column grid rather than .cta-band's centred text). --- */
.svc-dark { position: relative; overflow: hidden; background: linear-gradient(165deg, var(--color-primary) 0%, var(--color-ink) 100%); color: #fff; }
.svc-dark h2, .svc-dark h3 { color: #fff; }
.svc-dark p { color: rgba(255, 255, 255, 0.82); }
.svc-dark .eyebrow { color: #ffb877; }
.svc-dark .eyebrow--rule::before { background: #ffb877; }

/* Matches the reference's own flat navy (not the diagonal gradient
   .svc-dark gives every other dark section -- #082334 specifically, not
   var(--color-ink)/#091e30, which is a close but different shade), its own
   asymmetric top/bottom padding (clamp(64px,6vw,96px) top, fixed 62px
   bottom -- 56px/36px <=680px) instead of the shared .section clamp. */
.svc-approach {
    isolation: isolate;
    background: #082334;
    padding-top: var(--space-section);
    padding-bottom: var(--space-section);
}
@media (max-width: 680px) { .svc-approach { padding-top: var(--space-section); padding-bottom: var(--space-section); } }
.svc-approach > .container { position: relative; z-index: 1; }
/* Reference's "orange-fold" background art: a thick-stroked ellipse ring
   (a circle's border-radius:50% applied to a tall, narrow box), rotated
   and parked mostly off the top-right corner -- .svc-approach's own
   overflow:hidden (inherited from .svc-dark) clips it to the section, so
   only two curved orange strokes show through. Not a single arc/curve. */
.svc-approach__fold {
    position: absolute;
    right: -140px;
    top: -80px;
    width: 210px;
    height: 580px;
    border-radius: 50%;
    border: 48px solid #E9600C;
    transform: rotate(-17deg);
    opacity: 0.7;
    pointer-events: none;
    z-index: 0;
}
@media (max-width: 680px) { .svc-approach__fold { right: -180px; opacity: 0.4; } }
#svc-approach .eyebrow--rule::before { width: 43px; }
#svc-approach .eyebrow { margin-bottom: 24px; }
@media (max-width: 680px) {
    #svc-approach .eyebrow--rule::before { width: 34px; }
    #svc-approach .eyebrow { margin-bottom: 20px; }
}
/* ID-scoped (not just .svc-approach): the shared body.service-page h2 rule
   (line ~212) is "body.service-page h2" -- a class plus two type selectors,
   which out-specifies a single-class ".svc-approach h2" and would otherwise
   win for font-size/font-weight/letter-spacing/colour. The reference forces
   this heading's accent word onto its own line via display:block (not a
   <br>, and not simply wrapping -- it stays on its own line even when the
   line above it wouldn't otherwise be full). */
#svc-approach h2 { font-size: var(--fs-h2); font-weight: 700; line-height: 1.1; letter-spacing: -0.05em; color: #fff; margin-bottom: 0; }
@media (max-width: 850px) { #svc-approach h2 { font-size: var(--fs-h2); } }
#svc-approach h2 .text-accent { display: block; }
.svc-approach > .container p { margin-top: 23px; font-size: 15px; line-height: 1.6; max-width: 470px; color: #B7C7D2; }
.svc-approach > .container p + p { margin-top: 12px; }
@media (max-width: 850px) { .svc-approach > .container p { font-size: 14px; } }
@media (max-width: 680px) { .svc-approach > .container p { font-size: 14px; max-width: 100%; } }

/* -- heading/benefits two-column layout: matches the reference's own
   .94fr/1.06fr ratio and gap steps (85/50/40/32px) -- Bootstrap's 12-column
   .row/.col-lg-* can't express that ratio, and its own lg breakpoint
   (992px) would collapse to one column too early (the reference stays
   two-column down to 680px), so this is a plain grid instead. */
.svc-approach__grid { display: grid; align-items: center; gap: 32px; }
@media (min-width: 681px) { .svc-approach__grid { grid-template-columns: 0.94fr 1.06fr; gap: 40px; } }
@media (min-width: 851px) { .svc-approach__grid { gap: 50px; } }
@media (min-width: 1151px) { .svc-approach__grid { gap: 85px; } }

/* -- reusable icon/title/paragraph bullet: approach benefits, foundation
   details, case-study outcomes and AI points all share this shape. ------- */
.svc-points { display: grid; gap: 1.75rem 2rem; }
.svc-point__icon { display: inline-flex; width: 2.6rem; height: 2.6rem; margin-bottom: 0.9rem; color: var(--color-accent); }
.svc-point__icon svg { width: 100%; height: 100%; }
.svc-dark .svc-point__icon { color: #ffb877; }
.svc-point h3 { font-size: var(--fs-h3); font-weight: 700; margin-bottom: 0.4rem; }
.svc-point p { margin: 0; font-size: 16px; }

/* Approach section only: smaller, vivid-orange icons per the reference --
   overrides both the base 2.6rem size and the .svc-dark peach tint above,
   without touching Foundations/Case-Study/AI, which reuse the same
   .svc-point/.svc-point__icon markup and keep their existing look. Reference
   keeps this grid two-column down to 370px (not Bootstrap's 768px), with its
   own gap steps, and gives each item a bottom-border divider the shared
   .svc-point doesn't have elsewhere. */
.svc-approach .svc-points { gap: 28px 40px; }
@media (max-width: 1150px) { .svc-approach .svc-points { gap: 24px; } }
@media (max-width: 850px) { .svc-approach .svc-points { gap: 22px; } }
@media (max-width: 680px) { .svc-approach .svc-points { gap: 26px 22px; } }
.svc-approach .svc-points--2 { grid-template-columns: 1fr 1fr; }
@media (max-width: 370px) { .svc-approach .svc-points--2 { grid-template-columns: 1fr; } }
.svc-approach .svc-point { border-bottom: 1px solid rgba(145, 167, 182, 0.153); padding-bottom: 25px; }
@media (max-width: 680px) { .svc-approach .svc-point { padding-bottom: 20px; } }
.svc-approach .svc-point__icon { width: 25px; height: 27px; margin-bottom: 14px; color: #FF650B; }
.svc-approach .svc-point h3 { font-size: var(--fs-h3); font-weight: 700; margin-bottom: 0; }
@media (max-width: 1150px) { .svc-approach .svc-point h3 { font-size: var(--fs-h3); } }
@media (max-width: 850px) { .svc-approach .svc-point h3 { font-size: var(--fs-h3); } }
@media (max-width: 680px) { .svc-approach .svc-point h3 { font-size: var(--fs-h3); } }
.svc-approach .svc-point p { font-size: 14px; line-height: 1.7; margin-top: 10px; color: #B7C7D2; }
@media (max-width: 680px) { .svc-approach .svc-point p { font-size: 14px; } }

/* -- hero: full-bleed photo, reference-matched -- the source photo's own
   left-hand wall is already bright/light, so (unlike the old treatment) this
   needs only a soft light-toward-dark wash rather than a heavy dark scrim,
   with dark ink type sitting directly on that bright area instead of white
   type. Taller than before (min-height + flex centering) per request. */
/* Matches the reference's own final "cinematic-hero" treatment: a warm
   cream ground behind the full-bleed photo, and the section's own height
   driven by viewport width (42.85vw, capped) rather than a vh-based
   min-height. Scoped to >=768px -- the existing @media(max-width:767.98px)
   block further down switches to Django's own stacked mobile layout
   (full-bleed intentionally doesn't work well as a text backdrop that
   narrow), which is kept exactly as it already is. */
.svc-hero {
    position: relative;
    isolation: isolate;
    display: flex;
    align-items: center;
    overflow: hidden;
    color: var(--color-ink);
    background: #F5EEE4;
}
@media (min-width: 768px) {
    .svc-hero {
        height: 42.85vw;
        max-height: 830px;
        padding-block: 3vw;
    }
}
@media (max-width: 899.98px) and (min-width: 768px) {
    /* Ramps 490px (at 768px) down to exactly what the base `42.85vw` rule
       above already evaluates to at 900px (385.65px) -- a seamless handoff
       into that formula instead of free-falling at the 900px seam. */
    .svc-hero { height: clamp(385.65px, calc(1097.1px - 79.05vw), 490px); }
}
.svc-hero__media { position: absolute; inset: 0; z-index: 0; }
/* object-position: center -- the reference's own cinematic-hero crop, now
   that the photo is a true full-bleed backdrop rather than needing to dodge
   a fixed-width text column. The bottom-anchored fade into #directions'
   cream (matching the reference's separate cinematic-hero::after) is
   already handled below as the third layer of the wash, rather than a
   second, redundant fade element. */
/* A touch more saturated than the raw photo -- the foliage in the bottom-left
   corner in particular read as dull/washed once the legibility wash over it
   was pulled back; this keeps the greens looking natural and vivid rather
   than relying on the wash alone. */
.svc-hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: center center; filter: saturate(1.25); }
/* hero-v3.webp is already graded calm (matte orange, soft daylight); the shared boost would push it back towards the over-saturated look. */
.page-hero--web-development .page-hero__media > img { object-position: 100% 50%; }
/* --- web dev hero screens ----------------------------------------------------
   The laptop and phone in hero-v3.webp (blank screens, in the shared inner page hero) play a scrolling sample website. A
   1024x430 stage (the photo's own pixel size) holds the two screens, each a
   full-size page (960x590 laptop, 390x780 phone) mapped onto the photo's
   screen corners with matrix3d, plus a cut-out of the phone body so the
   laptop screen passes behind it. app.js scales and offsets the stage to
   match the photo's object-fit:cover crop and object-position at every
   width; until then it stays hidden. Each page holds at the top, scrolls to
   the bottom, holds, and scrolls back (16s loop, the phone a beat behind).
   Reduced motion: the pages stay at the top. */
.wd-screens { position: absolute; inset: 0; overflow: hidden; pointer-events: none; opacity: 0; transition: opacity 0.6s ease; }
.wd-screens.is-fit { opacity: 1; }
.wd-screens__stage { position: absolute; left: 0; top: 0; width: 1024px; height: 430px; transform-origin: 0 0; }
.page-hero .wd-screens img { width: auto; height: auto; max-width: none; object-fit: fill; object-position: 0 0; filter: none; }
.wd-screen { position: absolute; left: 0; top: 0; overflow: hidden; background: #FFFFFF; transform-origin: 0 0; }
.wd-screen::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: linear-gradient(118deg, rgba(255, 255, 255, 0.22) 0%, rgba(255, 255, 255, 0) 38%), linear-gradient(0deg, rgba(10, 29, 42, 0.05), rgba(10, 29, 42, 0)); }
.wd-screen--laptop { width: 960px; height: 590px; transform: matrix3d(0.222465, -0.042725, 0, -0.000141152, -0.0783968, 0.314914, 0, -5.52963e-05, 0, 0, 1, 0, 555.79, 141.28, 0, 1); }
.wd-screen--phone { width: 390px; height: 780px; border-radius: 46px; transform: matrix3d(0.140856, -0.027015, 0, -8.37876e-05, -0.057358, 0.21512, 0, -3.77634e-05, 0, 0, 1, 0, 883.94, 197.5, 0, 1); }
/* the photo's notch, redrawn over the page so it stays on top while the site scrolls */
.wd-screen--phone::before { content: ""; position: absolute; z-index: 2; top: 0; left: 50%; width: 140px; height: 30px; translate: -50% 0; border-radius: 0 0 20px 20px; background: #15191C; }
.page-hero .wd-screens .wd-phone-body { position: absolute; left: 858px; top: 187px; width: 119px; height: 197px; }

.wd-site { --wd-h: 590px; color: #0A1D2A; font-family: Inter, "Aptos", "Segoe UI", Arial, sans-serif; font-size: 24px; line-height: 1.4; background: #FFFFFF; }
.wd-site--phone { --wd-h: 780px; font-size: 21px; }
.wd-site small { display: block; margin-bottom: 12px; font-size: 0.72em; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: #3E4D57; }
.wd-site strong { display: block; font-size: 2em; font-weight: 700; line-height: 1.08; letter-spacing: -0.02em; }
.wd-site p { margin: 16px 0 0; color: #3E4D57; }
.wd-site__bar { display: flex; align-items: center; justify-content: space-between; height: 80px; padding: 0 48px; border-bottom: 1px solid #EEF0F2; }
.wd-site__bar b { font-size: 1.15em; letter-spacing: -0.01em; }
.wd-site__nav { display: flex; align-items: center; gap: 30px; font-size: 0.85em; font-weight: 600; color: #1F2E38; }
.wd-site__nav i { width: 18px; height: 18px; border: 2.5px solid #34454F; border-radius: 50%; }
.wd-site__menu { display: grid; gap: 6px; }
.wd-site__menu i { display: block; width: 30px; height: 3px; border-radius: 2px; background: #0A1D2A; }
.wd-site__btn { display: inline-block; margin-top: 30px; padding: 16px 30px; border-radius: 40px; background: #FF650B; color: #FFFFFF; font-size: 0.8em; font-weight: 600; }
.wd-site__hero { display: grid; grid-template-columns: 0.95fr 1.05fr; align-items: center; gap: 32px; height: 510px; padding-left: 48px; }
.wd-site__hero img { width: 100% !important; height: 100% !important; object-fit: cover !important; }
.wd-site__hero strong { font-size: 2.6em; }
.wd-site__sec { padding: 64px 48px; }
.wd-site__cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; margin-top: 40px; }
.wd-site__cards figure { margin: 0; }
.wd-site__cards img { width: 100% !important; border-radius: 14px; }
.wd-site__cards span { display: block; margin-top: 16px; font-weight: 600; }
.wd-site__cards em { font-style: normal; font-size: 0.82em; color: #3E4D57; }
.wd-site__stats { display: grid; grid-template-columns: repeat(3, 1fr); padding: 54px 48px; background: #FAF8F3; text-align: center; }
.wd-site__stats b { display: block; font-size: 2.4em; color: #FF650B; letter-spacing: -0.02em; }
.wd-site__stats span { font-size: 0.85em; color: #3E4D57; }
.wd-site__steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 36px; margin-top: 40px; }
.wd-site__steps i { display: block; width: 56px; height: 56px; margin-bottom: 20px; border-radius: 14px; background: #FFF1E8; box-shadow: inset 0 0 0 2px #FF650B; }
.wd-site__steps b { display: block; }
.wd-site__steps span { font-size: 0.85em; color: #3E4D57; }
.wd-site__cta { padding: 64px 48px; background: #0A1D2A; color: #FFFFFF; text-align: center; }
.wd-site__foot { display: flex; justify-content: space-between; padding: 30px 48px; background: #07151F; color: rgba(255, 255, 255, 0.75); font-size: 0.78em; }
.wd-site__foot b { color: #FFFFFF; }
/* phone layout */
.wd-site--phone .wd-site__bar { height: 120px; padding: 34px 30px 0; border: 0; }
.wd-site--phone .wd-site__hero { display: block; height: auto; padding: 10px 30px 40px; }
.wd-site--phone .wd-site__hero strong { font-size: 2.3em; }
.wd-site--phone .wd-site__hero img { display: block; height: 290px !important; margin-top: 26px; border-radius: 16px; }
.wd-site--phone .wd-site__sec,
.wd-site--phone .wd-site__cta { padding: 50px 30px; }
.wd-site--phone .wd-site__cards,
.wd-site--phone .wd-site__stats { grid-template-columns: 1fr; gap: 26px; }
.wd-site--phone .wd-site__stats { padding: 50px 30px; }
.wd-site--phone .wd-site__foot { padding: 30px; }
@keyframes wd-scroll {
    0%, 14% { transform: translateY(0); }
    50%, 62% { transform: translateY(calc(-100% + var(--wd-h))); }
    94%, 100% { transform: translateY(0); }
}
@media (prefers-reduced-motion: no-preference) {
    .wd-screens.is-fit .wd-site { animation: wd-scroll 16s cubic-bezier(0.55, 0, 0.35, 1) 0.8s infinite; }
    .wd-screens.is-fit .wd-site--phone { animation-delay: 2s; }
}
@media (max-width: 899.98px) and (min-width: 768px) {
    .svc-hero__media img { object-position: 56% center; }
}
.svc-hero__media::after {
    content: "";
    position: absolute;
    inset: 0;
    /* Deliberate, disclosed deviation from the reference: its own final
       cinematic-hero layer turns this wash off entirely (display:none),
       relying on its specific source photo being naturally light enough
       under the text. This site's hero photo doesn't have that guarantee
       at object-position:center, so the wash stays -- it's the one thing
       keeping the heading legible over an arbitrary crop of the image. */
    /* Three layers: an edge vignette (restores the photo's own depth/shadow
       instead of the flat, over-bright look the wash alone produced -- stays
       clear through the center where the laptop mockup sits), then the
       left-to-right wash that keeps the heading legible over the photo, then
       a bottom-anchored fade into the exact cream #directions starts with
       below. The wash is pulled back further than the first pass -- at
       higher strength it was washing out the greenery in the photo's
       bottom-left corner (foreground foliage) almost completely; the text's
       own natural contrast against the photo's bright wall needs much less
       help than that, so there's room to let the photo's real colour and
       shadow show through. */
    background:
        radial-gradient(120% 130% at 50% 45%, transparent 52%, rgba(9, 20, 30, 0.22) 100%),
        linear-gradient(90deg, rgba(255, 251, 246, 0.22) 0%, rgba(255, 251, 246, 0.1) 45%, rgba(255, 251, 246, 0.02) 68%, rgba(255, 251, 246, 0) 100%),
        linear-gradient(180deg, rgba(255, 250, 243, 0) 93%, #FFFAF3 100%);
}
.svc-hero__content { position: relative; z-index: 1; max-width: 42rem; }
@media (max-width: 991.98px) {
    .svc-hero__content { max-width: 26rem; }
}
/* Reference's own cinematic-hero copy-column widths -- a true two-column
   split rather than a fixed rem cap, now that the image is a true
   full-bleed backdrop (object-position: center) behind it. */
@media (min-width: 900px) {
    .svc-hero__content { width: 50%; max-width: none; }
}
@media (min-width: 768px) and (max-width: 899.98px) {
    /* A direct px clamp (not a % of .container) rather than the flat 58%
       this replaces: .container has its own, unrelated 850px gutter
       breakpoint, so 58% alone produced a small internal zigzag plus a
       ~66px cliff at the 900px seam (58% of the 830px container here vs.
       50% of it just past 900px). This ramps 768px's own current rendered
       width (417.6px) to exactly what that 50% rule evaluates to at 900px
       (415px), removing both. */
    .svc-hero__content { width: clamp(415px, calc(432.73px - 1.97vw), 417.6px); max-width: none; }
}
/* Sits directly above the heading, left-aligned with it (no extra indent --
   plain sibling flow inside .svc-hero__content) rather than the shared
   partials/breadcrumb.html bar, which renders as its own full-width section
   above the hero. Understated by design: this is a wayfinding aid sitting on
   top of a photo, not a heading in its own right. */
.svc-hero h1 { color: var(--color-ink); margin-bottom: 0; }
/* Hero headline reveal (this page's hero only, .svc-hero__headline):
   each line sits in its own overflow:hidden "mask" box; the text inside
   slides up from translateY(110%)/opacity:0 to its normal resting place
   once, on load -- a pure CSS `animation`, no JS/observer, so it can't
   cause a layout shift (the mask box's own height is the line's normal
   line-height throughout) and plays once since no `infinite`/trigger re-
   arms it. Base state (outside the media query) is fully visible with no
   transform, so no-JS/reduced-motion visitors simply see the finished
   headline immediately -- same progressive-enhancement convention as the
   sitewide [data-reveal] rule (site.css:933). */
.svc-hero__line { display: block; overflow: hidden; }
.svc-hero__line-inner { display: inline-block; }
@media (prefers-reduced-motion: no-preference) {
    .svc-hero__line-inner {
        transform: translateY(110%);
        opacity: 0;
        animation: svc-hero-line-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) forwards;
    }
    .svc-hero__line:nth-child(1) .svc-hero__line-inner { animation-delay: 0.1s; }
    .svc-hero__line:nth-child(2) .svc-hero__line-inner { animation-delay: 0.22s; }
    .svc-hero__line:nth-child(3) .svc-hero__line-inner { animation-delay: 0.34s; }
    .svc-hero__line:nth-child(4) .svc-hero__line-inner { animation-delay: 0.46s; }
}
@keyframes svc-hero-line-in { to { transform: translateY(0); opacity: 1; } }
/* Soft ambient glow radiating from the accent word -- several zero-offset,
   increasingly blurred text-shadow layers read as a diffuse glow rather
   than a hard drop shadow. */
.svc-hero h1 .text-accent { text-shadow: 0 0 12px rgba(255, 101, 11, 0.25), 0 0 46px rgba(255, 101, 11, 0.3); }
/* Matches the reference's final cinematic-hero h1 spec exactly
   (clamp(44px,4.7vw,90px), 0.99 line-height, -0.055em tracking, 700
   weight) -- its own values, not the shared body.service-page h1 ones
   (800/-.03em/1.05), which this overrides at higher specificity, scoped
   to this hero only. */
body.service-page .svc-hero h1 {
    font-size: var(--fs-h1);
    font-weight: 700;
    line-height: 0.99;
    letter-spacing: -0.055em;
}
/* No 768-899.98px override here -- the clamp() above already evaluates to
   its 44px floor uniformly from 0px through ~936px (4.7vw * 936 ~= 44), so
   removing the old flat-46px tier makes the h1 render at a constant 44px
   through this whole band with zero seam at 900px, rather than a tiny bump
   followed by a drop. */
/* Fills the gap the removed paragraph left; also the "breathing room
   around the heading and buttons" the larger hero calls for. */
.svc-hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem; margin-top: 2.5rem; }
/* Below 768px the full-bleed cropped photo stops working well as a text
   backdrop (the crop has to cut in tight, per the object-fit comment
   above), so instead: text first, then the complete, uncropped photo as
   its own block underneath -- .svc-hero__media leaves position:absolute
   for normal flow and is reordered after .container (flex order, no DOM
   change needed), the overlay wash is no longer needed once the photo
   isn't sitting behind the text, and the section's height/padding follow
   the stacked content instead of a fixed photo-background min-height. */
@media (max-width: 767.98px) {
    .svc-hero { flex-direction: column; align-items: stretch; min-height: 0; }
    .svc-hero .container { order: 1; }
    .svc-hero__media {
        position: static;
        order: 2;
        inset: auto;
        margin-top: 2rem;
        border-radius: var(--radius-lg);
        overflow: hidden;
    }
    .svc-hero__media img { height: auto; object-position: center; }
    .svc-hero__media::after { content: none; }
    /* Data-Solutions hero: stacked photo box = the photo's own aspect, so the
       bead overlay can simply fill it. */
    .svc-hero--split .svc-hero__media { position: relative; }
    .svc-hero--split .svc-hero__fx { position: absolute; inset: 0; width: 100%; height: 100%; }
}
/* Web-Development hero only: the shared mobile rule above shows the photo
   at its natural (height:auto, uncropped) aspect ratio, which on this
   particular photo leaves the laptop/phone small in the middle of a lot of
   empty wall/sunbeam space. Give this page's own instance a taller box and
   crop into the device cluster (right ~60% of the frame) via object-fit so
   they read as the hero image's actual subject on mobile, matching
   laptop/desktop's already-larger treatment -- scoped to .svc-hero--webdev
   so every other page sharing the plain .svc-hero/.svc-hero__media rules
   above (Cybersecurity, Managed IT & Cloud, Training, About, Contact) is
   untouched, and nested inside the same existing breakpoint rather than a
   new one. */
@media (max-width: 767.98px) {
    .svc-hero--webdev .svc-hero__media { position: relative; height: clamp(260px, 85vw, 420px); }
    .svc-hero--webdev .svc-hero__media img { height: 100%; object-fit: cover; object-position: 95% 50%; }
}

/* -- Data Solutions & Digital Marketing hero: reproduce the reference's own
   hero mechanism exactly, not an approximation of it.
   reference/Digital Marketing.html's own CSS: `.hero-art{inset:0 0 0 43%;
   width:57%}` (the photo box) and a SEPARATE `.hero::after` wash
   (`linear-gradient(90deg,#faf7f2 0%,#faf7f2 32%,...,transparent 61%)`)
   painted on the *whole hero*, not on the photo box. Two earlier passes
   here got the box right but kept applying the wash to `.svc-hero__media`
   itself (confined to that same 43%-100% box) -- so the fade only ever
   ran across the already-narrow photo box, leaving the 0-43% flat-colour
   zone untouched by any gradient and producing a hard seam at 43% instead
   of one continuous-looking scene. Moving the wash to a full-width
   `.svc-hero--split::after` (painted above the media's z-index:0 but below
   `.svc-hero__content`'s z-index:1, same stacking trick the reference
   itself relies on) lets it fade smoothly from the flat background,
   *across* the photo's own left edge, exactly like the reference.
   Height: reference's own `.hero` is min-height:660px / height:min(760px,
   100svh - 86px) -- taller than the shared .svc-hero's 42.85vw/830px
   formula (tuned for Web-Development's photo). 86px matches this site's
   own sticky header height too (measured ~86px), so reused as-is.
   Scoped to this page only via .svc-hero--split -- the Web-Development
   hero (shared .svc-hero rules above, untouched) keeps its own height and
   its own per-media wash. */
@media (min-width: 768px) {
    .svc-hero--split { min-height: 660px; height: min(760px, calc(100svh - 86px)); }
    .svc-hero--split .svc-hero__media { inset: 0 0 0 43%; width: 57%; }
    .svc-hero--split .svc-hero__media img { object-position: 56% center; }
    .svc-hero--split .svc-hero__media::after { content: none; }
    /* Bead overlay: laid out exactly like the cover-cropped photo (same
       994:887 box, same 56% / centre alignment), clipped to the media box,
       so the traced path stays on the photo's golden line at every width. */
    .svc-hero--split .svc-hero__media { container-type: size; overflow: hidden; }
    .svc-hero--split .svc-hero__fx { position: absolute; left: 56%; top: 50%; width: max(100cqw, 100cqh * 994 / 887); max-width: none; aspect-ratio: 994 / 887; transform: translate(-56%, -50%); }
    .svc-hero--split::after {
        content: "";
        position: absolute;
        inset: 0;
        z-index: 0;
        pointer-events: none;
        background:
            linear-gradient(90deg, #F5EEE4 0%, #F5EEE4 32%, rgba(245, 238, 228, 0.9) 40%, rgba(245, 238, 228, 0.5) 49%, rgba(245, 238, 228, 0) 61%),
            linear-gradient(180deg, rgba(255, 250, 243, 0) 93%, #FFFAF3 100%);
    }
    /* Reference's hero CTA is its own larger size (min-height:62px,
       font-size:19px, padding-inline:33px), not the shared .btn default
       (54px/16px/24px) -- same scoped-override pattern already used for
       the Home hero's button (#home .hero-cta further up). */
    .svc-hero--split .svc-hero__actions .btn {
        --bs-btn-padding-x: 2.0625rem;
        --bs-btn-padding-y: 0.95rem;
        font-size: 1.1875rem;
        min-height: 62px;
    }
}
/* Reference's hero h1 has no glow on its accent words (plain var(--color-accent)
   fill, no text-shadow) -- unlike the Web-Development hero's h1, which this
   shared .text-accent glow (further up in this file) was built for. Scoped
   override, not a change to the shared rule. */
.svc-hero--split h1 .text-accent { text-shadow: none; }
/* The bead is decorative and off entirely under reduced motion. */
.svc-hero__fx { pointer-events: none; overflow: hidden; }
/* Dashboard pulse: screen-blended so it only adds amber light on the dark laptop screen (invisible on the bright background, which is why the bead isn't). */
.svc-hero__pulse { mix-blend-mode: screen; }
@media (prefers-reduced-motion: reduce) { .svc-hero__fx { display: none; } }

/* -- "where do you want to take your website" section -------------------
   Matches the reference's own values exactly: fixed 64px/80px padding
   (38px/48px <=680px), its warm paper section background (not a gradient),
   a wider/taller orange rule than the shared .eyebrow--rule default, and
   this heading's own lighter weight/tighter tracking/true-ink colour --
   the shared body.service-page h2 (800/-.02em, generic body-text colour)
   is calibrated for other sections, not this one. */
#directions {
    padding-block: var(--space-section);
    background: #FAF8F4;
    --color-muted: #586C7D;
    --color-border: rgba(9, 30, 48, 0.1);
}
@media (max-width: 680px) { #directions { padding-block: var(--space-section); } }
#directions .eyebrow--rule::before { width: 43px; }
#directions .eyebrow { margin-bottom: 24px; }
@media (max-width: 680px) {
    #directions .eyebrow--rule::before { width: 34px; }
    #directions .eyebrow { margin-bottom: 20px; }
}
#directions h2 {
    font-size: var(--fs-h2);
    font-weight: 700;
    line-height: 1.12;
    letter-spacing: -0.04em;
    color: var(--color-ink);
    margin-bottom: 25px;
}
@media (max-width: 900px) { #directions h2 { max-width: 650px; } }
@media (max-width: 680px) { #directions h2 { margin-bottom: 23px; } }

/* -- "where do you want to take your website" tabs + demo stage --------- */
.svc-directions__grid { display: grid; gap: 64px; align-items: center; }
@media (min-width: 901px) and (max-width: 1150px) { .svc-directions__grid { grid-template-columns: 1fr 1fr; gap: 32px; } }
@media (min-width: 1151px) { .svc-directions__grid { grid-template-columns: 1fr 1.1fr; } }
@media (max-width: 900px) { .svc-directions__grid { grid-template-columns: 1fr; gap: 35px; } }
@media (max-width: 680px) { .svc-directions__grid { gap: 28px; } }
/* No min-height here: .svc-tab__desc (below) already caps every tab's
   expanded description at the same fixed max-height regardless of which
   tab or how much text it holds, so .svc-tabs' own total height is already
   constant across every tab-switch -- confirmed by measuring it at each of
   this file's breakpoints, same height no matter which tab is selected.
   A min-height here was previously added well above that already-constant
   height (34rem/544px vs. a measured 416px at its widest), which did
   nothing to prevent jumps but did inflate #directions' own bottom gap
   before the next section, since the grid row (and so the section) was
   forced to that height even though neither column ever needed it. */
.svc-tabs { display: flex; flex-direction: column; padding-top: 8px; }
@media (max-width: 680px) { .svc-tabs { padding-top: 0; } }
.svc-tab {
    display: block;
    width: calc(100% + 2rem);
    text-align: left;
    background: none;
    border: 0;
    border-bottom: 1px solid var(--color-border);
    padding: 22px 16px;
    margin-inline: -1rem;
    border-radius: 0;
    cursor: pointer;
    color: var(--color-text);
    transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease);
}
@media (max-width: 680px) { .svc-tab { padding: 18px 12px; } }
/* Subtle hover response on collapsed tabs only -- the active tab's own
   background (below) already wins visually, and nothing here touches
   .svc-tab__desc's display, so hovering the active tab can never hide its
   content (that stays keyed to [aria-selected] only, independent of :hover). */
.svc-tab:not([aria-selected="true"]):hover { background: rgba(9, 30, 48, 0.035); }
.svc-tab__top { display: flex; align-items: center; gap: 8px; }
/* Fixed width (not auto) so every number -- "01" through "04" -- takes the
   same horizontal space, which is what lets .svc-tab__desc's padding-left
   below line up with the title text reliably rather than only by luck for
   whichever digits happen to be narrowest. */
.svc-tab__num { color: var(--color-muted); font-weight: 600; font-size: 14px; flex-shrink: 0; width: 25px; }
/* flex-shrink:0 (the old value) plus a flex item's default min-width:auto
   meant the name could never shrink below its own full-text width, so on
   narrow screens a long name (e.g. "Move Beyond an Outdated Website")
   overflowed past the tab/viewport edge instead of wrapping to a second
   line. min-width:0 is what actually lets a flex child wrap text at all. */
.svc-tab__name { flex: 1 1 auto; min-width: 0; font-size: 18px; font-weight: 600; letter-spacing: -0.025em; line-height: 1.45; }
@media (min-width: 901px) and (max-width: 1150px) { .svc-tab__name { font-size: 16px; } }
@media (max-width: 680px) { .svc-tab__name { font-size: 16px; } }
@media (max-width: 370px) { .svc-tab__name { font-size: 15px; } }
/* A bordered circle rather than a bare character, and its content comes
   entirely from ::before keyed off [aria-selected] -- not JS or per-item
   HTML -- so plus/minus can never drift out of sync with the actual
   expanded state (clicking a different tab, or collapsing this one, always
   repaints the right glyph for free). The ring stays this same peach tone
   in both states -- only the glyph/number/name colour switches to rust
   when selected (below), matching the reference exactly. */
.svc-tab__sign {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 23px;
    height: 23px;
    border-radius: 50%;
    border: 1px solid #F0CBB2;
    color: var(--color-muted);
    font-weight: 400;
    font-size: 21px;
    line-height: 1;
}
.svc-tab__sign::before { content: "+"; }
/* Collapsed by default via max-height (not display:none, which can't
   transition) so opening/closing animates instead of snapping -- the
   ceiling is well above the longest description (incl. the "best for"
   line) at any breakpoint so it never visibly clips mid-animation. */
/* padding-left matches .svc-tab__num's fixed 25px width plus .svc-tab__top's
   8px gap, so the description (and the "best for" line inside it) lines up
   under the title text, not under the number. */
.svc-tab__desc { display: block; max-height: 0; opacity: 0; overflow: hidden; margin: 0; padding-left: 36px; color: var(--color-muted); font-size: 14px; line-height: 1.75; transition: max-height 0.35s var(--ease), opacity 0.25s var(--ease), padding-top 0.35s var(--ease); }
@media (min-width: 901px) { .svc-tab__desc { max-width: 470px; } }
@media (min-width: 901px) and (max-width: 1150px) { .svc-tab__desc { font-size: 14px; } }
@media (max-width: 680px) { .svc-tab__desc { font-size: 14px; padding-left: 30px; } }
.svc-tab__best-for::before { content: "\2014\00A0"; }
.svc-tab__best-for { display: block; margin-top: 15px; margin-bottom: 7px; font-size: 14px; line-height: 1.8; letter-spacing: 0.14em; color: var(--color-muted); text-transform: uppercase; }
@media (max-width: 680px) { .svc-tab__best-for { font-size: 14px; margin-top: 12px; } }
@media (max-width: 370px) { .svc-tab__best-for { font-size: 14px; } }
/* Matches the reference's own --rust (#AD4000) exactly for the
   expanded heading/number/circle here -- --color-accent itself (used by
   the "best for" line, hover states elsewhere, etc.) is unchanged. */
.svc-tab[aria-selected="true"] { color: var(--color-ink); background: rgba(255, 241, 230, 0.5); border-bottom-color: #F4C9AA; }
.svc-tab[aria-selected="true"] .svc-tab__num { color: #AD4000; }
.svc-tab[aria-selected="true"] .svc-tab__name { color: #AD4000; }
.svc-tab[aria-selected="true"] .svc-tab__sign { color: #AD4000; }
.svc-tab[aria-selected="true"] .svc-tab__sign::before { content: "\2212"; }
.svc-tab[aria-selected="true"] .svc-tab__desc { max-height: 20rem; opacity: 1; padding-top: 14px; }

/* No max-width: fills its (now equal-width) column so the image reads as
   large/prominent next to the text. Matches the reference's own cream
   "browser window" chrome exactly (background/border/radius/shadow),
   rather than the shared card look (white/var(--radius-lg)/var(--shadow-md))
   used elsewhere on this page. */
.svc-stage { background: #F3EEE6; border: 1px solid rgba(9, 30, 48, 0.125); border-radius: 9px; overflow: hidden; box-shadow: 0 24px 60px -24px rgba(9, 30, 48, 0.25); }
@media (max-width: 900px) { .svc-stage { width: min(100%, 620px); margin-inline: auto; } }
.svc-stage__bar { display: flex; align-items: center; gap: 5px; height: 33px; padding-inline: 12px; background: #FAF8F4; border-bottom: 1px solid rgba(9, 30, 48, 0.07); }
.svc-stage__bar i { width: 5px; height: 5px; border-radius: 50%; border: 1px solid #A4AEB6; display: inline-block; }
.svc-stage__address { margin-left: 14px; font-size: 14px; letter-spacing: 0.03em; color: #6A7882; }
/* All four [data-svc-scene] panels share this one grid cell (grid-area:1/1
   stacks them, rather than only the active one ever being laid out) so the
   row's height is always the max of all four scenes' natural heights --
   whichever one happens to be visible, the frame is the same size. That's
   what keeps the preview's outer box from resizing when switching items
   (the community scene, image + heading + paragraph + links, is
   substantially taller than the plain-image scenes). No JS measurement or
   guessed px/aspect-ratio needed -- the grid computes it from real content
   at whatever width the viewport is, so it stays correct responsively.
   [hidden] still means "not shown" (visibility + pointer-events), but
   Bootstrap's own global `[hidden]{display:none!important}` (not the UA
   default -- Bootstrap 5 adds this one deliberately) is overridden to
   display:flex so a hidden scene still contributes its height to that max
   instead of dropping out of the row's sizing; needs its own !important to
   win against Bootstrap's, with this selector's higher specificity then
   deciding it correctly. */
/* Matches the reference's own fixed 385px/360px/350px "browser window"
   frame height exactly (needed as a definite height, not just a floor, for
   the launch image's object-fit:cover crop below to size correctly). The
   community scene's own content (image + heading + paragraph + links) is
   sized (see .svc-scene__community-img below) to fit within this same
   frame at every width instead of needing its own internal scrollbar. */
.svc-stage__scenes { position: relative; display: grid; height: 385px; }
@media (max-width: 680px) { .svc-stage__scenes { height: 360px; } }
@media (max-width: 370px) { .svc-stage__scenes { height: 350px; } }
.svc-stage__scenes .svc-scene { grid-area: 1 / 1; display: flex; align-items: center; justify-content: center; min-width: 0; min-height: 0; }
.svc-stage__scenes .svc-scene > * { width: 100%; }
.svc-stage__scenes .svc-scene[hidden] { display: flex !important; visibility: hidden; pointer-events: none; }
#svc-scene-community { align-items: flex-start; }
.svc-scene img { display: block; width: 100%; height: auto; }
/* The featured launch scene fills the full frame height (matching the
   reference's fixed-height stage exactly) rather than keeping its own
   aspect ratio; object-fit:cover trims the decorative background
   arch/pedestal top and bottom to fit. Direct-child selector so this
   doesn't also catch the small inset thumbnail nested inside the
   before/after compare scene below. */
.svc-scene > img { height: 100%; object-fit: cover; }
/* Below 680px the reference switches this specific scene's image from a
   cropped fill to a fully-visible, letterboxed mockup against a soft cream
   backdrop -- at that narrow a crop would cut too far into the laptop
   mockup to stay legible. */
@media (max-width: 680px) {
    #svc-scene-launch img { object-fit: contain; background: #F7F3ED; }
}
.svc-stage__caption { display: flex; justify-content: space-between; align-items: flex-start; gap: 20px; min-height: 55px; padding: 18px 2px 0; font-size: 14px; line-height: 1.4; color: var(--color-muted); }
@media (max-width: 680px) {
    .svc-stage__caption { padding: 14px 2px 0; font-size: 14px; line-height: 1.6; }
    .svc-stage__caption [data-svc-caption] { max-width: 230px; }
}
.svc-stage__caption [data-svc-number] { color: #AD4000; font-size: 14px; letter-spacing: 0.12em; white-space: nowrap; }

/* redesign scene: before/after compare slider -- reproduces the reference's
   own .old-site/.new-site mockup content (not a generic placeholder),
   same wide/short target ratio as the launch scene above (829/449, was
   also 1058/793). .svc-compare__after (the redesigned site) is the
   always-visible base layer; .svc-compare__before is clipped to only its
   left [--reveal]-wide strip, on top of it -- the reference's own
   clip-path technique, just with the opposite layer clipped, so dragging
   the slider produces the identical reveal direction either way. */
.svc-compare { --reveal: 42%; position: relative; aspect-ratio: 829 / 449; background: #fff; overflow: hidden; }
.svc-compare__after, .svc-compare__before { position: absolute; inset: 0; }
.svc-compare__before { background: #E8E8E8; color: #6B7175; padding: 22px; clip-path: inset(0 calc(100% - var(--reveal)) 0 0); }
.svc-compare__after { background: #fff; }
.svc-compare__old-logo { background: #C4C9CB; padding: 12px; font-size: 16px; font-family: Georgia, serif; }
.svc-compare__old-menu { font-size: 14px; border-block: 1px solid #AEB7BB; margin-block: 12px; padding: 9px; word-spacing: 0.15em; }
.svc-compare__old-body { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.svc-compare__old-body strong { display: block; font-family: Georgia, serif; font-size: 22px; line-height: 1.25; }
.svc-compare__old-lines { height: 42px; margin-top: 14px; opacity: 0.65; background: repeating-linear-gradient(#AFB8BF 0 3px, transparent 3px 10px); }
.svc-compare__old-box { height: 110px; background: #C5CBCF; }
.svc-compare__new-nav { height: 42px; padding-inline: 17px; display: flex; align-items: center; justify-content: space-between; font-size: 14px; color: #40515B; }
.svc-compare__new-brand { font-size: 14px; font-weight: 700; letter-spacing: -0.04em; color: var(--color-ink); }
.svc-compare__new-menu { word-spacing: 0.4em; font-size: 14px; }
.svc-compare__new-launch { height: 190px; display: grid; grid-template-columns: 1fr 0.85fr; background: #F2F0EB; margin-inline: 13px; }
.svc-compare__new-copy { padding: 16px 0 12px 14px; }
.svc-compare__new-micro { display: block; font-size: 14px; letter-spacing: 0.16em; text-transform: uppercase; color: #6C777D; }
.svc-compare__new-copy strong { display: block; max-width: 150px; margin-block: 10px; font-size: 20px; line-height: 1.1; font-weight: 600; letter-spacing: -0.05em; }
.svc-compare__new-cta { display: inline-flex; gap: 10px; align-items: center; font-size: 14px; background: var(--color-ink); color: #fff; padding: 8px 10px; border-radius: 2px; }
.svc-compare__new-photo { min-height: 0; overflow: hidden; }
.svc-compare__new-photo img { width: 100%; height: 100%; object-fit: cover; }
.svc-compare__new-footer { display: flex; justify-content: space-between; gap: 10px; padding: 12px 16px; font-size: 14px; color: #4F606C; }
@media (max-width: 680px) {
    .svc-compare__new-launch { height: 170px; }
    .svc-compare__new-copy strong { font-size: 18px; }
    .svc-compare__old-body strong { font-size: 19px; }
    .svc-compare__old-box { height: 95px; }
}
@media (max-width: 370px) {
    .svc-compare__new-launch { height: 150px; }
    .svc-compare__before { padding: 12px; }
    .svc-compare__old-logo { padding: 6px; font-size: 14px; }
    .svc-compare__old-menu { margin-block: 6px; padding: 5px; }
    .svc-compare__old-body { gap: 10px; }
    .svc-compare__old-body strong { font-size: 15px; }
    .svc-compare__old-lines { height: 24px; margin-top: 8px; }
    .svc-compare__old-box { height: 80px; }
}
/* The divider tracks the same --reveal custom property the clip-path above
   uses, so it (and its drag handle) always sit exactly at the visible
   seam, in sync with the slider, with no JS beyond setting that one
   property (see [data-svc-compare] in app.js). */
.svc-compare__divider { position: absolute; inset-block: 0; left: var(--reveal); width: 2px; background: var(--color-accent); pointer-events: none; z-index: 1; }
.svc-compare__divider::after { content: "\2194"; position: absolute; top: 50%; left: -15px; width: 32px; height: 32px; border-radius: 50%; transform: translateY(-50%); display: grid; place-items: center; background: var(--color-accent); color: var(--color-ink); box-shadow: 0 2px 10px rgba(9, 30, 48, 0.2); font-size: 14px; }
.svc-compare__tag { position: absolute; bottom: 41px; font-size: 14px; font-weight: 700; padding: 4px 8px; background: #fff; color: var(--color-text); border: 1px solid #DAE0E3; z-index: 1; }
.svc-compare__tag--before { left: 15px; }
.svc-compare__tag--after { right: 15px; }
.svc-compare__controls { position: absolute; inset-inline: 0; bottom: 0; height: 35px; padding-inline: 15px; display: flex; align-items: center; gap: 10px; font-size: 14px; color: var(--color-text); background: rgba(252, 251, 249, 0.91); z-index: 1; }
.svc-compare__controls input[type="range"] { flex: 1 1 auto; min-width: 0; accent-color: var(--color-accent); }

/* AI section callout box ("AI should solve a problem...") ---------------- */
.svc-ai-note { margin-top: 1.5rem; padding: 1rem 1.25rem; border-radius: var(--radius); background: rgba(255, 255, 255, 0.16); }

/* shop / community illustrative scenes */
.svc-scene__demo { padding: clamp(1.5rem, 4vw, 2.5rem); }
.svc-scene__demo h3 { margin-bottom: 0.4rem; }
.svc-scene__products { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; margin-block: 1.25rem; }
.svc-scene__product { border: 1px solid var(--color-border); border-radius: var(--radius); padding: 0.85rem; text-align: center; font-size: 14px; }
.svc-scene__product svg { width: 3.5rem; height: 3.5rem; margin-bottom: 0.5rem; }
/* Kept side-by-side (not stacked) even this narrow, and shrunk -- a single
   column here made the product grid taller than .svc-stage__scenes' own
   fixed frame, silently clipping against .svc-stage's overflow:hidden. */
@media (max-width: 370px) {
    .svc-scene__products { gap: 0.5rem; margin-block: 0.75rem; }
    .svc-scene__product { padding: 0.5rem; font-size: 14px; }
    .svc-scene__product svg { width: 2.25rem; height: 2.25rem; margin-bottom: 0.3rem; }
}
/* Fixed height (not aspect-ratio-scaled against the full stage width) --
   matches the reference's own much shorter community-banner proportions,
   and is what lets this scene's content actually fit within .svc-stage__
   scenes' fixed frame height without the internal scrollbar a taller,
   width-scaled image previously forced. */
/* .svc-scene img (above) beats a single-class selector's own `height` on
   specificity alone -- re-qualified with the element here so this actually
   wins instead of silently losing to that `height:auto`. */
.svc-scene img.svc-scene__community-img { border-radius: var(--radius); width: 100%; height: 140px; margin-block: 0.75rem; object-fit: cover; }
@media (max-width: 680px) { .svc-scene img.svc-scene__community-img { height: 120px; } }
@media (max-width: 370px) { .svc-scene img.svc-scene__community-img { height: 100px; margin-block: 0.5rem; } }
.svc-scene__links { display: flex; flex-wrap: wrap; gap: 1rem; font-size: 14px; color: var(--color-accent); font-weight: 600; margin: 0; padding: 0; list-style: none; }

/* -- case study --------------------------------------------------------------
   Pixel values (not rem, and the odd breakpoints: 1600/1150/850/680/370px)
   are copied directly from the client-supplied reference markup/CSS for
   this exact component (reference/Valin-Services-Website Development(2).html)
   rather than fitted to this site's usual rem+clamp system, since the goal
   here is matching that reference precisely, not fluid scaling. */
/* Matches the reference's own 48px/48px exactly -- its section itself
   carries no padding at all, the 48px lives on its grid wrapper instead,
   so this is set here (the equivalent element) rather than on #work. */
#work { padding-block: var(--space-section); }
/* No .container in the template for this section -- .svc-case__grid plays
   that role itself, at the reference's own wider width (not the shared
   1280px/112px .container formula): min(1420px, 100% - 90px) down to
   1150px, then an uncapped calc() that keeps narrowing at each of the same
   breakpoints used throughout this component. */
.svc-case__grid { width: min(1420px, calc(100% - 90px)); margin-inline: auto; display: grid; grid-template-columns: .95fr 1.3fr .95fr; gap: 30px; align-items: center; }
/* Text color only -- not var(--color-accent)/orange like most eyebrows
   sitewide; the reference's own .eyebrow base color is its muted tone, with
   only the short dash (.eyebrow--rule::before, untouched) staying orange. */
#work .svc-case__copy .eyebrow { font-size: 14px; margin-bottom: 18px; color: #586C7D; }
/* letter-spacing/color: explicit here because the shared body.service-page
   h2 rule (a class + two type selectors) otherwise out-specifies this
   single-class-plus-ID-plus-tag selector for those two properties only
   (font-size/line-height already won without help). */
#work .svc-case__copy h2 { font-size: var(--fs-h2); line-height: 1.12; letter-spacing: -0.05em; color: var(--color-ink); }
/* The reference's own accent shade for this heading specifically -- a
   darker, more rust-leaning orange than the shared .text-accent default
   (var(--color-accent)/#FF650B) used everywhere else. */
#work .svc-case__copy h2 .text-accent { color: #E65305; }
.svc-case__copy .svc-case__desc { font-size: clamp(14px, 10.44px + 0.222vw, 14px); line-height: 1.6; margin-top: 16px; color: #586C7D; }
.svc-case__name { font-size: 14px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: #AD4000; margin-top: 24px; }
/* Keeps this site's own white-on-orange .btn-primary (used everywhere else
   on the page) rather than the reference's one-off dark-ink-on-orange
   variant, for consistency with every other button on the site; only the
   reference's sizing is matched here. */
.svc-case__btn { margin-top: 23px; font-size: 14px; min-height: 46px; padding-inline: 22px; }
.svc-case__art { align-self: stretch; display: flex; align-items: center; margin-inline: -18px; min-height: 310px; }

/* "View the Project" modal (#legal-modal-case-study, cloned into the shared
   #app-modal by [data-legal-modal] -- same mechanism as the footer's
   Privacy/Terms/Accessibility modals, see static/js/app.js). The shared
   .app-modal__dialog (app.css) is plain white with 1.5rem padding -- rather
   than changing that globally (it's reused by those other modals too),
   this bleeds to the dialog's own edges with a matching border-radius and
   paints its own warm off-white background + generous padding on top, so
   only this modal's content looks different; Privacy/Terms/Accessibility
   are untouched. */
.svc-case-modal { margin: -1.5rem; padding: 2.5rem; background: #FBF8F3; border-radius: 6px; }
.svc-case-modal h2 { color: var(--color-ink); margin-bottom: 1rem; }
.svc-case-modal p { color: var(--color-muted); line-height: 1.6; margin-bottom: 1.75rem; }
.svc-case-modal .btn { margin: 0; }
@media (max-width: 480px) {
    .svc-case-modal { padding: 1.75rem; }
}
.svc-case__photo { width: 100%; height: 100%; object-fit: cover; object-position: 62% center; border-radius: 2px; box-shadow: none; }

/* --- case study screens --------------------------------------------------------
   The laptop in case-study-v2.webp flips through pages of the St. David's
   site. Same .wd-screens/[data-wd-screens] fitting as the web dev hero
   screens (an 829x449 stage in the photo's own pixels, scaled by app.js to
   the photo's crop); the screen itself is the photo's 567x299 at 187,93.
   app.js ([data-case-screens]) adds .is-entering to the next slide, which
   turns in from its left edge over the current one, then becomes
   .is-active. Screenshots fit the screen's width from the top, on the
   site's cream; a 1.9:1 screenshot fills it exactly. Reduced motion: the
   first slide (the photo's own screen) stays. */
.svc-case__art { position: relative; }
.wd-screens__stage.case-screens__stage { width: 829px; height: 449px; }
.case-screens { position: absolute; left: 187px; top: 93px; width: 567px; height: 299px; overflow: hidden; background: #F4EFE8; perspective: 1400px; }
.case-screens__slide { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; object-position: center top; background: #F4EFE8; visibility: hidden; transform-origin: 0 50%; backface-visibility: hidden; }
.case-screens__slide.is-active { visibility: visible; z-index: 1; }
.case-screens__slide.is-entering { visibility: visible; z-index: 2; animation: case-screen-in 0.9s cubic-bezier(0.22, 0.7, 0.2, 1) both; }
@keyframes case-screen-in {
    from { transform: rotateY(-88deg); filter: brightness(0.6); }
    to { transform: none; filter: none; }
}

/* Outcomes: a vertical feature list, not the icon-above-heading card grid
   .svc-point/.svc-point__icon get elsewhere (Approach, Foundations, AI) --
   same markup, restyled here only. Each row is a 44px pale orange circle
   then heading + text; the rows share the column's height equally (flex: 1)
   so the hairlines between them sit evenly beside the photo. The heading's
   first line is centred on the circle (margin-top) in every row. No hover
   effects. */
.svc-case__outcomes { --case-icon: 44px; --case-h3: clamp(20px, 6px + 1.25vw, 23px); align-self: stretch; display: flex; flex-direction: column; }
.svc-case__outcomes .svc-point { flex: 1 1 0; display: grid; grid-template-columns: var(--case-icon) minmax(0, 1fr); column-gap: 20px; align-content: center; align-items: start; padding-block: 20px; }
.svc-case__outcomes .svc-point + .svc-point { border-top: 1px solid #E6E1DA; }
.svc-case__outcomes .svc-point__icon { width: var(--case-icon); height: var(--case-icon); margin: 0; border-radius: 50%; background: #FFF0E5; color: var(--color-accent); display: grid; place-items: center; }
.svc-case__outcomes .svc-point__icon svg { width: 21px; height: 21px; }
.svc-case__outcomes .svc-point h3 { margin: calc((var(--case-icon) - var(--case-h3) * 1.25) / 2) 0 0; font-size: var(--case-h3); font-weight: 700; line-height: 1.25; letter-spacing: -0.01em; color: var(--color-ink); }
.svc-case__outcomes .svc-point p { margin: 6px 0 0; font-size: 15px; line-height: 1.6; color: #586C7D; }

@media (max-width: 1150px) {
    .svc-case__grid { width: calc(100% - 60px); gap: 22px; grid-template-columns: 1fr 1.2fr 1fr; }
    #work .svc-case__copy h2 { font-size: var(--fs-h2); }
    .svc-case__copy .svc-case__desc { font-size: 14px; }
    .svc-case__art { margin-inline: -9px; min-height: 290px; }
    .svc-case__outcomes .svc-point { column-gap: 18px; }
    .svc-case__outcomes .svc-point p { font-size: 14px; }
}
@media (max-width: 850px) {
    .svc-case__grid { width: calc(100% - 48px); grid-template-columns: 1fr 1.15fr; gap: 30px; }
    #work .svc-case__copy h2 { font-size: var(--fs-h2); }
    .svc-case__copy .svc-case__desc { font-size: 14px; }
    .svc-case__art { min-height: 270px; }
    /* Below the copy and photo: three side by side, icon above the text. */
    .svc-case__outcomes { --case-h3: 20px; grid-column: 1 / -1; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px; }
    .svc-case__outcomes .svc-point { grid-template-columns: minmax(0, 1fr); row-gap: 14px; align-content: start; padding: 20px 0 0; }
    .svc-case__outcomes .svc-point,
    .svc-case__outcomes .svc-point + .svc-point { border-top: 1px solid #E6E1DA; }
    .svc-case__outcomes .svc-point h3 { margin-top: 0; }
}
@media (max-width: 680px) {
    .svc-case__grid { width: calc(100% - 40px); display: flex; flex-direction: column; gap: 24px; }
    #work .svc-case__copy h2 { font-size: var(--fs-h2); }
    .svc-case__copy .svc-case__desc { font-size: 14px; }
    .svc-case__name { line-height: 1.7; margin-top: 20px; }
    .svc-case__art { min-height: 0; height: 230px; margin-inline: -20px; }
    .svc-case__photo { object-position: center; }
    /* Stacked under the photo: back to icon-left rows. */
    .svc-case__outcomes { --case-icon: 42px; display: flex; flex-direction: column; gap: 0; }
    .svc-case__outcomes .svc-point { grid-template-columns: var(--case-icon) minmax(0, 1fr); column-gap: 18px; row-gap: 0; padding-block: 18px; border-top: 0; }
    .svc-case__outcomes .svc-point:first-child { border-top: 1px solid #E6E1DA; }
    .svc-case__outcomes .svc-point h3 { margin-top: calc((var(--case-icon) - var(--case-h3) * 1.25) / 2); }
}

/* -- foundations (service detail page) ---------------------------------------
   Copy beside the layered-site visual, then the six build qualities as a
   3x2 grid of outlined cards (icon and title side by side, line below),
   over faint circuit traces at the section's edges. The cards rise in
   order on reveal ([data-reveal-group]); hover lifts a card and warms its
   border. */
#foundations { position: relative; overflow: hidden; background: #082334; padding-block: var(--space-section); }
#foundations > .container { position: relative; z-index: 1; }
.svc-found-traces { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; pointer-events: none; }
.svc-found-traces path { fill: none; stroke: rgba(160, 190, 210, 0.12); stroke-width: 1.2; }
.svc-found-traces__nodes circle { fill: #082334; stroke: rgba(255, 101, 11, 0.45); stroke-width: 1.2; }
.svc-foundation__top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 64px; align-items: center; }
#foundations .svc-foundation__copy h2 { font-size: var(--fs-h2); color: #FFFFFF; }
.svc-foundation__copy > p { margin-top: 16px; max-width: 34rem; font-size: var(--fs-body); line-height: 1.65; color: #C9D6DF; }
.svc-foundation__copy > p:first-of-type { margin-top: 24px; color: #FFFFFF; }
.svc-foundation__art { transition: transform 0.7s var(--ease); }
.svc-foundation__art img { display: block; width: 100%; height: auto; }
@media (hover: hover) and (pointer: fine) { .svc-foundation__art:hover { transform: translateY(-6px); } }
.svc-found-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; margin-top: var(--space-block); }
.svc-found-card { padding: 26px 26px 28px; border: 1px solid rgba(160, 190, 210, 0.22); border-radius: 8px; background: rgba(4, 22, 34, 0.45); transition: border-color 0.3s ease, transform 0.35s var(--ease), background-color 0.3s ease; }
.svc-found-card__head { display: flex; align-items: center; gap: 16px; }
.svc-found-card__icon { flex: none; display: inline-flex; width: 44px; height: 44px; color: #FF650B; }
.svc-found-card__icon svg { width: 100%; height: 100%; }
#foundations .svc-found-card h3 { margin: 0; color: #FFFFFF; font-size: var(--fs-h4); line-height: 1.3; }
.svc-found-card p { margin: 16px 0 0; color: #B7C7D2; font-size: 15px; line-height: 1.6; }
@media (hover: hover) and (pointer: fine) {
    .svc-found-card:hover { border-color: rgba(255, 101, 11, 0.55); background: rgba(4, 22, 34, 0.7); transform: translateY(-4px); }
}
@media (max-width: 991.98px) {
    .svc-foundation__top { grid-template-columns: minmax(0, 1fr); gap: 40px; }
    .svc-found-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 575.98px) {
    .svc-found-grid { grid-template-columns: minmax(0, 1fr); gap: 14px; }
    .svc-found-card { padding: 22px 20px 24px; }
}

/* -- 3-step process (service detail page) --------------------------------
   The three source images (process-0{1,2,3}.webp) already have the orange
   arc, the circular photo crop and a segment of the connecting line baked
   directly into the artwork itself (cream background matching the section,
   confirmed by inspecting the files) -- they were never meant to be
   stretched into a square object-fit:cover crop with their own border
   radius on top, which is what made this section read as oversized
   rectangular cards. Shown at their natural square-ish size instead, with
   no clipping, so the pre-composed art (arc + line) displays exactly as
   designed and the three segments line up into one flowing line.
   #process-scoped sizing (not the shared body.service-page h2 clamp, which
   tops out at 48px here -- noticeably larger than the reference's compact
   38px) keeps this section from reading oversized next to the smaller
   circles, per the reference. */
/* Bottom padding trimmed (was 3rem) -- #capabilities right below now adds
   its own visual separation via a thin top border + padding-top on its row
   (see .svc-capabilities__row), reusing the reference's "connected
   sections" technique (one continuous background, a hairline instead of a
   padding gap) instead of stacking both sections' full padding. */
/* Matches the reference's own background (currently transparent here --
   the page's own paper colour was showing through instead) and its
   58px/65px padding. */
#process { background: #F8F7F4; padding-block: var(--space-section); }
#process h2 { font-size: var(--fs-h2); }
/* No separate max-width cap on the grid itself -- it previously left the
   row narrower than the heading above it without being centered to match,
   reading as pushed left with dead space on the right. It now fills the
   same .container width as the heading; "compact" instead comes from the
   fixed 190px image size (not stretched) plus a generous, even gap -- same
   mechanism the reference uses (gap:85px in a 1280px wrap), scaled down a
   little for this site's wider container. */
.svc-process-steps { position: relative; display: grid; grid-template-columns: repeat(3, 1fr); column-gap: clamp(2rem, 6vw, 5.25rem); row-gap: 2.5rem; margin-top: 2.5rem; }
/* The connecting line: reused directly from the reference (same viewBox,
   path and stroke-width), stretched behind all three circles. z-index:0
   under .svc-process-step's z-index:1 so it reads as passing behind the
   images, not over them. */
.svc-process-steps__path { position: absolute; left: 0; top: 37px; width: 100%; height: 120px; overflow: visible; z-index: 0; pointer-events: none; }
.svc-process-step { position: relative; z-index: 1; }
.svc-process-step__art { width: 190px; max-width: 100%; margin-bottom: 1rem; }
.svc-process-step__art img { display: block; width: 100%; height: auto; transition: transform 0.35s var(--ease); }
.svc-process-step__art:hover img { transform: translateY(-6px); }
.svc-process-step__label { display: block; font-size: 14px; font-weight: 700; letter-spacing: 0.1em; color: var(--color-accent); text-transform: uppercase; margin-bottom: 0.5rem; }
.svc-process-step h3 { font-size: var(--fs-h3); margin-bottom: 0; }
/* Web Development's own #process steps dropped their separate black <h3>
   (templates/web/service_web_development.html) -- the orange label is now
   each step's only heading, sized to match the removed h3 exactly. Scoped
   to #process (not the shared .svc-process-step__label rule above) because
   service_data_marketing.html's "cycle" section reuses the same class with
   its own h3 still in place and must stay untouched. */
#process .svc-process-step__label { font-size: 21px; }
.svc-process-step p { font-size: 15px; line-height: 1.7; max-width: 310px; }
@media (max-width: 991.98px) {
    #process h2 { font-size: var(--fs-h2); }
    .svc-process-step__art { width: 165px; }
}
@media (max-width: 767.98px) {
    #process { padding-block: var(--space-section); }
    #process h2 { font-size: var(--fs-h2); }
    .svc-process-steps { grid-template-columns: 1fr; row-gap: 2rem; margin-top: 1.5rem; }
    .svc-process-steps__path { display: none; }
    .svc-process-step__art { width: 150px; }
    .svc-process-step p { max-width: none; }
}

/* -- capability rows -------------------------------------------------------- */
/* -- "beyond the website" capabilities (service detail page) -------------
   #capabilities used to carry .section--alt (a flat grey band), which read
   as a hard break right after #process above -- removed from the template;
   this section now sits on the page's own background (same as #process),
   and .svc-capabilities__row's top border + padding-top is the only
   separation, matching the reference's "one continuous section, a hairline
   instead of a colour change" treatment. #process's own bottom padding was
   trimmed to match (see #process above) so the two don't stack full
   padding on both sides of that line. */
/* The divider line sits at the border-top of .svc-capabilities__row, right
   after this section's own top padding -- so "space above the line" is
   #process's bottom padding + this section's top padding (2rem + 2rem),
   and "space below the line" is the row's own padding-top. Kept equal
   (both 4rem) so the line sits centered in the gap between the two
   sections' content, not pinned near the top of it. */
/* Warm cream band with a faint arc (::before) behind the copy; the
   laptop-and-wave art (capabilities-v2.webp) bleeds off the left and
   bottom under the copy, its top and right edges masked into the band.
   The three capabilities are soft rounded cards: a large pale circle with
   the orange icon, then title, text and an underlined link with an arrow.
   Everything below is #capabilities-scoped. */
#capabilities {
    position: relative;
    overflow: hidden;
    padding: var(--space-section) 0;
    background: radial-gradient(ellipse 55% 70% at 22% 28%, #FCE8D8 0%, rgba(252, 232, 216, 0) 70%), #FDF7F0;
}
#capabilities::before {
    content: "";
    position: absolute;
    left: 0;
    top: -19vw;
    width: 54vw;
    height: 54vw;
    border-radius: 50%;
    border: 1px solid rgba(232, 140, 80, 0.22);
    background: radial-gradient(circle at 50% 60%, rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0) 70%);
    pointer-events: none;
}
#capabilities .container { position: relative; z-index: 1; }
.svc-capabilities__row { display: grid; grid-template-columns: 1.12fr 1fr; gap: 64px; align-items: center; }
#capabilities .svc-capabilities__eyebrow { display: inline-flex; align-items: center; gap: 18px; margin-bottom: 18px; font-size: 15px; font-weight: 600; letter-spacing: 0.08em; color: #E65305; }
#capabilities .svc-capabilities__eyebrow::after { content: ""; width: 200px; height: 1px; background: linear-gradient(90deg, rgba(230, 83, 5, 0.45), rgba(230, 83, 5, 0)); }
#capabilities h2 { font-size: clamp(30px, 3.4vw, 50px); font-weight: 700; line-height: 1.08; letter-spacing: -0.025em; color: var(--color-ink); }
#capabilities h2 span { color: inherit; }
#capabilities .svc-capabilities__copy > p { font-size: 17px; line-height: 1.6; color: var(--color-muted); margin-top: 22px; margin-bottom: 20px; max-width: 480px; }
/* The copy column stretches to the row's height so the art (margin-top:
   auto) always runs to the section's bottom edge, however tall the cards. */
.svc-capabilities__copy { align-self: stretch; display: flex; flex-direction: column; justify-content: center; }
.svc-capabilities__copy > * { flex: none; }
.svc-capabilities__art { position: relative; margin: 20px -40px calc(-1 * var(--space-section)) -140px; }
.svc-capabilities__copy .svc-capabilities__art { margin-top: auto; }
.svc-capabilities__art img { display: block; width: 100%; height: auto; mask-image: linear-gradient(180deg, transparent 0, #000 22%), linear-gradient(270deg, transparent 0, #000 14%); mask-composite: intersect; }

.svc-capabilities__list { display: flex; flex-direction: column; gap: 22px; }
#capabilities .svc-capability {
    display: grid;
    grid-template-columns: 72px minmax(0, 1fr);
    gap: 0 24px;
    align-items: start;
    padding: 26px 30px 26px 26px;
    background: rgba(255, 255, 255, 0.55);
    border: 1px solid rgba(236, 212, 192, 0.8);
    border-radius: 22px;
    box-shadow: 0 14px 34px -22px rgba(150, 80, 30, 0.35);
    transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
#capabilities .svc-capability__icon { width: 72px; height: 72px; border-radius: 50%; background: #FDE4D2; color: var(--color-accent); display: grid; place-items: center; }
#capabilities .svc-capability__icon svg { width: 30px; height: 30px; }
@media (hover: hover) and (pointer: fine) {
    #capabilities .svc-capability:hover { border-color: rgba(230, 120, 60, 0.45); box-shadow: 0 18px 38px -22px rgba(150, 80, 30, 0.45); }
    #capabilities .svc-capability:hover .svc-capability__icon { filter: none; }
}
#capabilities .svc-capability:focus-within .svc-capability__icon { filter: none; }
#capabilities .svc-capability h3 { font-size: 22px; font-weight: 700; line-height: 1.25; letter-spacing: -0.01em; color: var(--color-ink); margin: 4px 0 0; }
#capabilities .svc-capability p { font-size: 15px; line-height: 1.55; color: var(--color-muted); margin: 8px 0 0; }
#capabilities .text-link { display: inline-block; min-height: 0; margin-top: 14px; padding: 0; border: 0; font-size: 15px; font-weight: 600; color: #E65305; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 5px; text-decoration-color: currentColor; }
#capabilities .text-link::after { content: "\2192"; display: inline-block; margin-left: 12px; font-size: 18px; line-height: 1; transition: transform 0.2s var(--ease); }
#capabilities .text-link:hover { color: var(--color-accent); }
#capabilities .text-link:hover::after { transform: translateX(3px); }

@media (max-width: 1150px) {
    .svc-capabilities__row { gap: 40px; }
    #capabilities .svc-capability { grid-template-columns: 60px minmax(0, 1fr); gap: 0 18px; padding: 22px 22px 22px 20px; }
    #capabilities .svc-capability__icon { width: 60px; height: 60px; }
    #capabilities .svc-capability__icon svg { width: 26px; height: 26px; }
    #capabilities .svc-capability h3 { font-size: 20px; }
    #capabilities .svc-capability p { font-size: 14px; }
}
/* One column: copy, then the art, then the cards. */
@media (max-width: 900px) {
    #capabilities::before { width: 110vw; height: 110vw; top: -50vw; left: -30vw; }
    .svc-capabilities__row { grid-template-columns: 1fr; gap: 32px; }
    #capabilities .svc-capabilities__copy > p { max-width: 560px; }
    .svc-capabilities__art { margin: 16px -40px 0 -40px; }
}
@media (max-width: 680px) {
    #capabilities .svc-capabilities__eyebrow { font-size: 13px; gap: 14px; }
    #capabilities .svc-capabilities__eyebrow::after { width: 90px; }
    #capabilities .svc-capabilities__copy > p { font-size: 15px; }
    #capabilities .svc-capabilities__copy > p br { display: none; }
    .svc-capabilities__art { margin: 8px -20px 0 -20px; }
    .svc-capabilities__list { gap: 16px; }
    #capabilities .svc-capability { grid-template-columns: 50px minmax(0, 1fr); gap: 0 16px; padding: 20px 18px; border-radius: 18px; }
    #capabilities .svc-capability__icon { width: 50px; height: 50px; }
    #capabilities .svc-capability__icon svg { width: 22px; height: 22px; }
    #capabilities .svc-capability h3 { font-size: 18px; margin-top: 2px; }
    #capabilities .text-link { font-size: 14px; }
}
@media (max-width: 370px) {
    #capabilities .svc-capability { grid-template-columns: 1fr; row-gap: 14px; }
}

/* -- FAQ with a leading icon (faq-list.html has no icon slot, so this
   section uses its own markup with native <details name="..."> instead of
   JS for single-open-at-a-time behaviour) -- reference-matched: each
   question is its own bordered, rounded card (not a plain divided list),
   tinted pale orange while open, with a generated +/- indicator and the
   same cream-circle-icon + hover-glow recipe already used for the case
   study/foundations/capabilities sections above (reused, not re-derived).
   #faq-scoped throughout since .svc-faq-item isn't used elsewhere, but
   kept consistent with that scoping convention anyway. -------------------- */
#faq .svc-faq-item { border: 1px solid #E0E5E8; border-radius: 0.6rem; margin-bottom: 0.75rem; padding: 1.1rem 1.35rem; background: #fff; transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease); }
#faq .svc-faq-item:last-child { margin-bottom: 0; }
#faq .svc-faq-item[open] { border-color: #F5BC95; background: #FFF8F2; }
.svc-faq-item summary {
    display: grid;
    grid-template-columns: 2.1875rem 1fr 1rem;
    align-items: center;
    gap: 1rem;
    cursor: pointer;
    font-weight: 600;
    font-size: 0.9375rem;
    line-height: 1.5;
    list-style: none;
    color: var(--color-ink);
}
.svc-faq-item summary::-webkit-details-marker { display: none; }
/* Generated +/- indicator -- a real character, not an icon, so it can't
   drift out of sync with the actual [open] state (no JS needed to keep it
   correct; the browser's own open/close toggle drives it for free). */
.svc-faq-item summary::after { content: "+"; grid-column: 3; font-size: 1.5rem; font-weight: 400; line-height: 1; color: var(--color-accent); justify-self: end; }
.svc-faq-item[open] summary::after { content: "\2212"; }
#faq .svc-faq-item[open] summary { color: var(--color-ink); }
/* Same cream-circle-icon recipe as .svc-case__outcomes/.svc-capability
   above (cream bg, rust icon, drop-shadow glow on hover/focus) -- smaller
   here (35px vs 45px) per the reference. */
.svc-faq-item__icon { flex: none; width: 2.1875rem; height: 2.1875rem; border-radius: 50%; background: #FFF0E5; color: #AD4000; display: grid; place-items: center; transition: filter 0.2s var(--ease); }
.svc-faq-item__icon svg { width: 1.3125rem; height: 1.3125rem; }
@media (hover: hover) and (pointer: fine) {
    .svc-faq-item summary:hover .svc-faq-item__icon { filter: drop-shadow(0 0 6px rgba(255, 101, 11, 0.6)) drop-shadow(0 0 15px rgba(255, 101, 11, 0.33)); }
}
.svc-faq-item summary:focus-visible .svc-faq-item__icon { filter: drop-shadow(0 0 6px rgba(255, 101, 11, 0.6)) drop-shadow(0 0 15px rgba(255, 101, 11, 0.33)); }
.svc-faq-item p { margin: 0.9rem 0 0 3.1875rem; font-size: 14px; line-height: 1.65; color: var(--color-muted); max-width: 38rem; }
/* Matches the reference's own 65px/55px exactly, not the shared .section
   clamp. */
#faq { padding-block: var(--space-section); }
.svc-faq__art { position: relative; overflow: hidden; border-radius: var(--radius-lg); height: 260px; margin-top: 1.5rem; }
.svc-faq__art img { width: 100%; height: 100%; object-fit: cover; object-position: bottom; display: block; }
.svc-faq__art::after { content: ""; position: absolute; inset: 0; background: linear-gradient(var(--color-bg) 0%, transparent 12%); pointer-events: none; }
@media (max-width: 991.98px) {
    .svc-faq-item summary { grid-template-columns: 1.75rem 1fr 0.875rem; gap: 0.75rem; font-size: 14px; }
    .svc-faq-item__icon { width: 1.75rem; height: 1.75rem; }
    .svc-faq-item__icon svg { width: 1.0625rem; height: 1.0625rem; }
    .svc-faq-item p { margin-left: 2.5rem; font-size: 14px; }
}

/* -- Web Development's own FAQ (#faq.wd-faq) ---------------------------------
   Warm cream band with a faint arc (::before), FAQs eyebrow, large heading
   and the glass question-bubble art (faq-v2.webp) bleeding off the left
   and bottom. Questions are soft rounded cards with a large pale icon
   circle; the open one turns pale orange with an orange left edge. Scoped
   to .wd-faq so the Data & Marketing page's #faq.dm-faq is untouched. */
#faq.wd-faq {
    position: relative;
    overflow: hidden;
    background: radial-gradient(ellipse 50% 70% at 18% 30%, #FCE8D8 0%, rgba(252, 232, 216, 0) 70%), #FDF7F0;
}
#faq.wd-faq::before {
    content: "";
    position: absolute;
    left: -14vw;
    top: -12vw;
    width: 50vw;
    height: 50vw;
    border-radius: 50%;
    border: 1px solid rgba(232, 140, 80, 0.2);
    background: radial-gradient(circle at 60% 55%, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0) 70%);
    pointer-events: none;
}
#faq.wd-faq > .container { position: relative; z-index: 1; }
#faq.wd-faq .row { align-items: center; }
#faq.wd-faq .wd-faq__intro { align-self: stretch; display: flex; flex-direction: column; }
#faq.wd-faq .wd-faq__eyebrow { display: inline-flex; align-items: center; align-self: flex-start; gap: 18px; margin-bottom: 18px; font-size: 15px; font-weight: 600; letter-spacing: 0.08em; color: #E65305; }
#faq.wd-faq .wd-faq__eyebrow::after { content: ""; width: 220px; height: 1px; background: linear-gradient(90deg, rgba(230, 83, 5, 0.45), rgba(230, 83, 5, 0)); }
#faq.wd-faq h2 { font-size: clamp(30px, 3.4vw, 50px); font-weight: 700; line-height: 1.08; letter-spacing: -0.025em; color: var(--color-ink); }
#faq.wd-faq h2 span { color: inherit; }
#faq.wd-faq .lead { margin: 18px 0 0; font-size: 19px; line-height: 1.5; color: var(--color-muted); }
/* margin-top: auto pins the art to the column's bottom; the negative
   margins bleed it to the section's left and bottom edges. */
#faq.wd-faq .svc-faq__art { overflow: visible; border-radius: 0; height: auto; margin: auto -40px calc(-1 * var(--space-section)) -120px; padding-top: 24px; }
#faq.wd-faq .svc-faq__art::after { content: none; }
#faq.wd-faq .svc-faq__art img { width: 100%; height: auto; object-fit: initial; mask-image: linear-gradient(180deg, transparent 0, #000 20%), linear-gradient(270deg, transparent 0, #000 16%); mask-composite: intersect; }

#faq.wd-faq .svc-faq-item {
    position: relative;
    margin-bottom: 16px;
    padding: 16px 28px 16px 22px;
    background: rgba(255, 255, 255, 0.6);
    border: 1px solid rgba(236, 212, 192, 0.8);
    border-radius: 16px;
    box-shadow: 0 12px 30px -22px rgba(150, 80, 30, 0.35);
    transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
#faq.wd-faq .svc-faq-item:last-child { margin-bottom: 0; }
#faq.wd-faq .svc-faq-item[open] {
    padding-top: 22px;
    padding-bottom: 26px;
    background: linear-gradient(180deg, #FFF2E8, #FFF8F2);
    border-color: #F6C6A4;
    box-shadow: inset 3px 0 0 var(--color-accent), 0 16px 34px -22px rgba(200, 90, 20, 0.4);
}
#faq.wd-faq .svc-faq-item summary { grid-template-columns: 56px minmax(0, 1fr) 24px; gap: 24px; font-size: 17px; font-weight: 600; line-height: 1.4; }
#faq.wd-faq .svc-faq-item summary::after { font-size: 28px; font-weight: 300; color: var(--color-accent); }
#faq.wd-faq .svc-faq-item__icon { width: 56px; height: 56px; background: #FDE4D2; color: var(--color-accent); }
#faq.wd-faq .svc-faq-item__icon svg { width: 26px; height: 26px; }
#faq.wd-faq .svc-faq-item summary:hover .svc-faq-item__icon,
#faq.wd-faq .svc-faq-item summary:focus-visible .svc-faq-item__icon { filter: none; }
@media (hover: hover) and (pointer: fine) {
    #faq.wd-faq .svc-faq-item:not([open]):hover { border-color: rgba(230, 120, 60, 0.45); background: rgba(255, 255, 255, 0.8); }
}
#faq.wd-faq .svc-faq-item p { margin: 6px 0 0 80px; max-width: none; font-size: 15px; line-height: 1.75; color: var(--color-muted); }

@media (max-width: 1199.98px) {
    #faq.wd-faq .svc-faq-item summary { grid-template-columns: 48px minmax(0, 1fr) 22px; gap: 18px; font-size: 16px; }
    #faq.wd-faq .svc-faq-item__icon { width: 48px; height: 48px; }
    #faq.wd-faq .svc-faq-item__icon svg { width: 22px; height: 22px; }
    #faq.wd-faq .svc-faq-item p { margin-left: 66px; }
}
/* Stacked (<992px): intro, art, then the questions. */
@media (max-width: 991.98px) {
    #faq.wd-faq::before { width: 110vw; height: 110vw; top: -50vw; left: -40vw; }
    #faq.wd-faq .svc-faq__art { margin: 8px -40px 0 -40px; max-width: 640px; }
}
@media (max-width: 680px) {
    #faq.wd-faq .wd-faq__eyebrow { font-size: 13px; gap: 14px; }
    #faq.wd-faq .wd-faq__eyebrow::after { width: 100px; }
    #faq.wd-faq .lead { font-size: 16px; }
    #faq.wd-faq .svc-faq__art { margin: 4px -20px 0 -20px; }
    #faq.wd-faq .svc-faq-item { padding: 14px 16px; border-radius: 14px; margin-bottom: 12px; }
    #faq.wd-faq .svc-faq-item[open] { padding-top: 16px; padding-bottom: 20px; }
    #faq.wd-faq .svc-faq-item summary { grid-template-columns: 40px minmax(0, 1fr) 18px; gap: 14px; font-size: 15px; }
    #faq.wd-faq .svc-faq-item summary::after { font-size: 24px; }
    #faq.wd-faq .svc-faq-item__icon { width: 40px; height: 40px; }
    #faq.wd-faq .svc-faq-item__icon svg { width: 19px; height: 19px; }
    #faq.wd-faq .svc-faq-item p { margin-left: 54px; font-size: 14px; line-height: 1.7; }
}
@media (max-width: 370px) {
    #faq.wd-faq .svc-faq-item p { margin-left: 0; }
}

@media (min-width: 768px) {
    .svc-points--2 { grid-template-columns: repeat(2, 1fr); }
    .svc-points--3 { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 992px) {
    .svc-points--4 { grid-template-columns: repeat(4, 1fr); }
}
.cta-band--contact .contact-form .form-select option { color: var(--color-text); }

/* =============================================================================
   Data Solutions & Digital Marketing service page (templates/web/
   service_data_marketing.html) -- reuses the shared .svc-*/.ai-feature*/
   .svc-process-step* components above; only the handful of layouts that have
   no existing equivalent (need cards, the two-column disciplines split, the
   infinity graphic) get new rules here, prefixed .dm- and scoped to this
   page's section ids so nothing else is affected.
   ============================================================================= */
.svc-section-heading { max-width: 46rem; margin-inline: auto; }
.svc-section-heading .lead { max-width: 38rem; margin-inline: auto; }

/* -- #needs: scroll-activated list (after cuberto.com's service list) -------------
   Four long, full-width white cards. app.js sets --p (0..1) on each card from
   its position (0 low in the viewport, 1 at ~55% height): as it scrubs, the
   card's border deepens from a hairline grey to the brand blue, a blue-to-
   orange accent bar grows down its left edge and its shadow lifts. Past
   halfway it turns on (.is-on): the description opens and the illustration
   fades in on the right. Scrolling back reverses it. Without the script, or
   under reduced motion, --p is 1 and every card shows fully on. */
.dm-need-list { display: grid; gap: 16px; margin-top: 2.5rem; }
.dm-need-item {
    --p: 1;
    position: relative;
    display: grid;
    padding: clamp(1.5rem, 3vw, 2.5rem) clamp(1.75rem, 4vw, 3.5rem);
    border-radius: 24px;
    overflow: hidden;
    isolation: isolate;
    background: #FFFFFF;
    color: var(--color-ink);
    border: 1.5px solid color-mix(in srgb, var(--color-primary) calc(var(--p) * 100%), #E3E8EE);
    transition: color 0.45s var(--ease);
    box-shadow: 0 calc(var(--p) * 26px) calc(var(--p) * 50px) calc(var(--p) * -24px) rgba(30, 58, 95, 0.35);
}
/* accent bar down the left edge */
.dm-need-item::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 5px;
    background: linear-gradient(180deg, var(--color-primary), var(--color-accent));
    transform: scaleY(var(--p));
    transform-origin: top;
}
/* a faint blue wash fades in with --p so the active card reads as lit, the
   card itself stays white */
.dm-need-item::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    opacity: var(--p);
    background: radial-gradient(ellipse 60% 140% at 0% 0%, rgba(30, 58, 95, 0.06), rgba(30, 58, 95, 0) 70%);
}
.dm-need-item > :not(.dm-need-item__art) { max-width: 54%; }
.dm-need-item__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
/* card headings in the display sans, balanced so a two-line heading breaks
   evenly instead of leaving one orphan word; the section heading above uses
   the same face (not the page's serif) so the block reads as one */
.dm-need-list .dm-need-item h3 { margin: 16px 0 0; max-width: 30rem; font-family: var(--font-display); font-size: clamp(26px, 2.4vw, 34px); font-weight: 700; line-height: 1.14; letter-spacing: -0.02em; text-wrap: balance; color: inherit; }
body.dm-page main #needs h2 { font-family: var(--font-display); font-weight: 700; letter-spacing: -0.025em; line-height: 1.12; }
.dm-need-item__more { display: grid; grid-template-rows: 1fr; transition: grid-template-rows 1.2s cubic-bezier(0.16, 1, 0.3, 1); }
.dm-need-item__more > div { overflow: hidden; }
.dm-need-item__more p { margin: 0; padding-top: 14px; max-width: 36rem; font-size: 16.5px; line-height: 1.6; color: var(--color-muted); transition: opacity 0.6s var(--ease); }
/* the illustration: a white-background 3D image flush to the card's right
   edge, its left side fading into the white card so there is no box */
.dm-need-item__art { position: absolute; right: 0; top: 0; bottom: 0; width: 50%; pointer-events: none; overflow: hidden; -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 22%); mask-image: linear-gradient(90deg, transparent 0, #000 22%); transition: opacity 0.8s var(--ease), transform 1.2s cubic-bezier(0.16, 1, 0.3, 1); }
.dm-need-item__art img { width: 100%; height: 100%; object-fit: cover; object-position: right center; display: block; }
/* category chip */
.dm-need-card__tag { display: inline-flex; align-items: center; gap: 9px; padding: 5px 14px 5px 5px; border-radius: 999px; background: rgba(255, 101, 11, 0.1); color: #B9470A; font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; line-height: 1; transition: background-color 0.45s, color 0.45s; }
.dm-need-card__icon { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: var(--color-accent); color: #FFFFFF; }
.dm-need-card__icon svg { width: 15px; height: 15px; }

/* off state (only once app.js has armed the list): compact row, no art */
.dm-need-list.is-scrolly .dm-need-item:not(.is-on) .dm-need-item__more { grid-template-rows: 0fr; }
.dm-need-list.is-scrolly .dm-need-item:not(.is-on) .dm-need-item__more p { opacity: 0; }
.dm-need-list.is-scrolly .dm-need-item:not(.is-on) .dm-need-item__art { opacity: 0; transform: translateX(30px); }

@media (max-width: 850px) {
    .dm-need-item { border-radius: 20px; }
    .dm-need-item > :not(.dm-need-item__art) { max-width: none; }
    .dm-need-item__art { position: relative; inset: auto; width: auto; height: 200px; margin: 16px -24px -24px; -webkit-mask-image: none; mask-image: none; }
    .dm-need-list.is-scrolly .dm-need-item:not(.is-on) .dm-need-item__art { display: none; }
    .dm-need-item__more p { font-size: 15.5px; }
}
@media (max-width: 480px) {
    .dm-need-card__tag { white-space: nowrap; }
}

/* -- #clarity: two-column intro (headline+paragraph left, illustration right)
   and a four-column feature row with dark circular icon backgrounds,
   vertical dividers and an orange underline -- matches reference/Digital
   Marketing.html's own `.clarity-top` / `.feature` rules (43%/57% split,
   60px icon circles, 1px dividers between columns, 52x4px accent rule)
   almost exactly. `clarity-signals.webp` is a clean (text-free) crop of the
   reference's own chapter-3 illustration, background keyed to transparent
   so it sits on this section's existing navy gradient with no visible
   seam. Scoped to this page/section only -- .svc-point/.svc-points stay
   untouched for every other page that reuses them. */
/* Tighter than the shared section rhythm (the illustration used to set the
   height and left empty bands above/below the copy), on a quiet navy
   texture: a fine dot grid fading out from the art side, a lighter navy
   lift top left and a faint orange glow behind the illustration. */
#clarity.dm-clarity {
    padding-block: clamp(56px, 6vw, 88px);
    background:
        radial-gradient(ellipse 45% 60% at 78% 30%, rgba(255, 101, 11, 0.12), rgba(255, 101, 11, 0) 70%),
        radial-gradient(ellipse 50% 70% at 0% 0%, rgba(60, 100, 140, 0.28), rgba(60, 100, 140, 0) 70%),
        linear-gradient(165deg, var(--color-primary) 0%, var(--color-ink) 100%);
}
#clarity.dm-clarity::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: radial-gradient(rgba(255, 255, 255, 0.09) 1px, transparent 1.2px);
    background-size: 22px 22px;
    -webkit-mask-image: radial-gradient(ellipse 70% 80% at 80% 35%, #000 0%, transparent 75%);
    mask-image: radial-gradient(ellipse 70% 80% at 80% 35%, #000 0%, transparent 75%);
}
#clarity.dm-clarity > .container { position: relative; z-index: 1; }
.dm-clarity__top {
    display: grid;
    grid-template-columns: 43% 57%;
    align-items: center;
    gap: 2rem;
    max-width: none;
    margin-bottom: 2.25rem;
}
.dm-clarity__top p { max-width: 30rem; }
/* 80% of its column, right-aligned: the art no longer outgrows the copy. */
.dm-clarity__art { position: relative; width: 80%; justify-self: end; }
.dm-clarity__art img { width: 100%; height: auto; display: block; }
/* Thin glowing light travelling along the signal lines in
   clarity-signals.webp, from each floating icon tile in toward the wall
   and back out through the arrow -- per reference/Digital Marketing.html's
   `.filter-motion path` (`.scene-motion` overlay on its own version of this
   artwork): a single short dash looping a long dash-gap, drop-shadowed
   orange, each path staggered so the five don't travel in lockstep. The
   reference's own path coordinates belong to its full-bleed 1774x887 scene
   (wall + heading + this art together); ours is cropped to just the art at
   1074x520, so these 5 paths are redrawn at that viewBox to the same
   tile-in/wall/arrow-out shape instead of reusing its literal numbers.
   dasharray/keyframe end per path = that path's own measured total length
   (via getTotalLength in-browser), so each dash loops seamlessly with no
   jump. Static otherwise -- the artwork itself is unchanged, this is only
   an overlay -- and gated behind prefers-reduced-motion like every other
   continuous animation in this project. */
.dm-clarity__signals { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.dm-clarity__signal { fill: none; stroke: #FFDDA0; stroke-width: 1.8; stroke-linecap: round; filter: drop-shadow(0 0 4px rgba(255, 155, 50, 0.8)); opacity: 0.75; }
@media (prefers-reduced-motion: no-preference) {
    .dm-clarity__signal--a { stroke-dasharray: 12 876; animation: dm-clarity-flow-a 8s linear infinite; }
    .dm-clarity__signal--b { stroke-dasharray: 12 900; animation: dm-clarity-flow-b 8s linear infinite; animation-delay: -1.6s; }
    .dm-clarity__signal--c { stroke-dasharray: 12 903; animation: dm-clarity-flow-c 8s linear infinite; animation-delay: -3.2s; }
    .dm-clarity__signal--d { stroke-dasharray: 12 900; animation: dm-clarity-flow-d 8s linear infinite; animation-delay: -4.8s; }
    .dm-clarity__signal--e { stroke-dasharray: 12 645; animation: dm-clarity-flow-e 8s linear infinite; animation-delay: -6.4s; }
}
@keyframes dm-clarity-flow-a { to { stroke-dashoffset: -888; } }
@keyframes dm-clarity-flow-b { to { stroke-dashoffset: -912; } }
@keyframes dm-clarity-flow-c { to { stroke-dashoffset: -915; } }
@keyframes dm-clarity-flow-d { to { stroke-dashoffset: -912; } }
@keyframes dm-clarity-flow-e { to { stroke-dashoffset: -657; } }
@media (max-width: 850px) {
    .dm-clarity__top { grid-template-columns: 1fr; gap: 1.5rem; margin-bottom: 2rem; }
    .dm-clarity__art { order: -1; width: 100%; max-width: 520px; justify-self: center; }
}

.dm-clarity__points { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; }
.dm-clarity__points .svc-point { padding: 0 1.875rem; border-right: 1px solid rgba(255, 255, 255, 0.21); }
.dm-clarity__points .svc-point:first-child { padding-left: 0; }
.dm-clarity__points .svc-point:last-child { border-right: 0; padding-right: 0; }
.dm-clarity__points .svc-point__icon {
    width: 3.75rem;
    height: 3.75rem;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.04);
    color: var(--color-accent);
    margin-bottom: 1rem;
    transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease), background-color 0.35s var(--ease);
}
.dm-clarity__points .svc-point__icon svg { width: 55%; height: 55%; }
.dm-clarity__points .svc-point:hover .svc-point__icon {
    background: rgba(255, 128, 20, 0.1);
    box-shadow: 0 0 25px rgba(255, 115, 3, 0.2);
    transform: translateY(-3px) rotate(-4deg);
}
@media (max-width: 850px) {
    .dm-clarity__points { grid-template-columns: 1fr 1fr; gap: 1.75rem 1.5rem; }
    .dm-clarity__points .svc-point { border-right: 0; padding: 0; }
}

/* -- #services: infinity graphic + two-column discipline split -------------- */
.dm-disciplines {
    padding-block: var(--space-section);
    background-image: radial-gradient(ellipse at 0 30%, rgba(220, 232, 237, 0.53), transparent 28%), radial-gradient(ellipse at 100% 35%, rgba(255, 234, 210, 0.67), transparent 30%), url("/static/img/services/data-digital-marketing/disciplines-bg.22c78629cba7.webp");
    background-size: cover;
    background-position: center;
}
/* .dm-infinity: a 3-column grid (side / artwork / side) rather than a
   flex row -- `minmax(0,1fr)` on the two outer tracks forces them to be
   exactly equal width (so DATA vs. MARKETING's different text lengths can
   never pull the artwork off-centre) and lets them shrink safely instead
   of overflowing. No rem cap on the grid itself (just the .container's own
   width) so the line/label reach out toward the section's own edges, as
   wide as the page allows. */
.dm-infinity { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; column-gap: clamp(0.75rem, 2.5vw, 2rem); width: 100%; margin: 0.75rem auto 1rem; }
/* Scales continuously with viewport width (not a hard breakpoint) so the
   artwork gives the two side columns enough room for "MARKETING" (the
   longer label) at every width in between, not just at a couple of fixed
   checkpoints -- a fixed-breakpoint version of this left an unreduced gap
   around 960-1140px wide where the label still overflowed the container. */
.dm-infinity__art-wrap { position: relative; height: clamp(10.5rem, 4.6rem + 10.5vw, 13rem); display: flex; align-items: center; justify-content: center; }
.dm-infinity__art { height: 100%; width: auto; max-width: 100%; object-fit: contain; mix-blend-mode: multiply; }
.dm-infinity__light { position: absolute; top: 50%; left: 50%; width: min(28rem, 79%); height: auto; transform: translate(-50%, -50%); overflow: visible; pointer-events: none; }
.dm-infinity__light path { fill: none; stroke: #fff2ba; stroke-width: 2.8; stroke-dasharray: 14 80 5 530; filter: drop-shadow(0 0 5px #ff6a00); animation: dm-infinity-flow 12s linear infinite; }
@keyframes dm-infinity-flow { to { stroke-dashoffset: -1258; } }
/* .dm-infinity__side: one continuous line/dot/label unit per grid column.
   `.dm-infinity__dash` is the only child with flex-grow, so it alone
   stretches to fill whatever width its 1fr column has (reaching the
   artwork on one end); the dot+label keep their own natural size and sit
   flush at the column's outer edge (the row's default start-packing simply
   leaves them there once the dash has absorbed the rest) -- DATA lands at
   the far left, MARKETING at the far right, on identically-sized columns,
   so both sides are always equal length with no gap, break or random stop. */
.dm-infinity__side { position: relative; z-index: 1; display: flex; align-items: center; min-width: 0; gap: clamp(0.4rem, 1vw, 0.6rem); }
/* The artwork's own canvas has a soft transparent margin before its ring
   actually becomes visible, so a dash ending flush with the image's own
   box (the column boundary) used to leave a visible gap of plain
   background before the loop -- a negative margin on the dash's inner
   edge only (not the whole .dm-infinity__side, which would also drag the
   label inward) lets it bleed a little into that margin, so the line
   visually tucks just inside the loop's outer edge instead of stopping
   short of it. */
.dm-infinity__dash { flex: 1 1 auto; min-width: 0.5rem; height: 2px; background: var(--color-ink); }
.dm-infinity__side--left .dm-infinity__dash { margin-right: -5.5rem; }
.dm-infinity__side--right .dm-infinity__dash { background: var(--color-accent); margin-left: -5.5rem; }
.dm-infinity__dot { flex: none; width: 7px; height: 7px; border-radius: 50%; }
.dm-infinity__side--left .dm-infinity__dot { background: var(--color-ink); }
.dm-infinity__side--right .dm-infinity__dot { background: var(--color-accent); }
.dm-infinity__label { flex: none; font-size: clamp(14px, 0.42rem + 0.41vw, 0.75rem); font-weight: 700; letter-spacing: 0.25em; color: var(--color-ink); white-space: nowrap; }
/* 800px, not this page's usual 680px mobile cutoff: measured empirically
   -- "MARKETING" (the longer label) plus its dot/dash no longer has room
   next to the artwork below ~800px even at this rule's own smallest font
   size, so it's hidden a bit earlier than the rest of the page's mobile
   breakpoint rather than risk it clipping or overflowing the container. */
@media (max-width: 800px) {
    .dm-infinity { grid-template-columns: auto; justify-content: center; }
    .dm-infinity__side { display: none; }
}
/* Both columns sit on one shared six-row grid (subgrid): heading, intro and
   each of the four rows line up across the divider even when one intro
   wraps to two lines and the other doesn't. */
/* Both columns sit on one shared six-row grid (subgrid): heading, intro and
   each of the four rows line up across the gap even when one intro wraps
   to two lines and the other doesn't. Each column is a soft card panel with
   a thin top accent (navy for Data, orange for Marketing); type steps
   26 / 16 / 18 / 14px. */
.dm-service-columns { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: repeat(6, auto); column-gap: clamp(1.25rem, 2.5vw, 2rem); row-gap: 0; margin-top: 0.5rem; }
.dm-service-column {
    position: relative;
    display: grid;
    grid-row: span 6;
    grid-template-rows: subgrid;
    align-content: start;
    padding: clamp(1.5rem, 3vw, 2.25rem) clamp(1.25rem, 3vw, 2.25rem) clamp(0.75rem, 1.5vw, 1.25rem);
    background: rgba(255, 255, 255, 0.66);
    border: 1px solid rgba(225, 215, 205, 0.8);
    border-radius: 22px;
    box-shadow: 0 24px 48px -32px rgba(60, 50, 40, 0.25);
    overflow: hidden;
}
.dm-service-column::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px; background: linear-gradient(90deg, #315B78, rgba(49, 91, 120, 0)); }
.dm-service-column--marketing::before { background: linear-gradient(90deg, var(--color-accent), rgba(255, 101, 11, 0)); }
.dm-service-column > h3 { font-size: 26px; line-height: 1.2; letter-spacing: -0.02em; margin-bottom: 0.5rem; }
.dm-service-column > p { margin-bottom: 1.25rem; max-width: 32rem; font-size: 16px; line-height: 1.55; color: var(--color-muted); }
.dm-service-row { display: flex; gap: 1.125rem; align-items: center; margin-inline: -0.75rem; padding: 1rem 0.75rem; border-top: 1px solid rgba(225, 215, 205, 0.8); border-radius: 12px; transition: background-color 0.25s var(--ease); }
.dm-service-row:hover { background: rgba(49, 91, 120, 0.04); }
.dm-service-column--marketing .dm-service-row:hover { background: rgba(255, 101, 11, 0.05); }
.dm-service-row h4 { font-size: 18px; font-weight: 650; line-height: 1.3; letter-spacing: -0.01em; margin: 0 0 0.2rem; }
.dm-service-row p { margin: 0; font-size: 14px; line-height: 1.45; color: var(--color-muted); }

/* Icon circle badges: distinct blue (Data Solutions) vs orange (Digital
   Marketing) identity, including on hover -- the reference's own hover rule
   (`.service-row:hover .icon`) tints every row orange regardless of column,
   which would make Data Solutions hover orange too; overridden per-column here. */
.dm-service-row__icon {
    display: inline-flex; flex: none; align-items: center; justify-content: center;
    width: 3rem; height: 3rem; border-radius: 50%;
    background: #EAF0F3; color: #315B78;
    transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease), background-color 0.35s var(--ease);
}
.dm-service-row__icon svg { width: 1.45rem; height: 1.45rem; }
.dm-service-row:hover .dm-service-row__icon { transform: translateY(-3px) rotate(-4deg); box-shadow: 0 0 25px rgba(49, 91, 120, 0.2); background: rgba(49, 91, 120, 0.1); }
.dm-service-column--marketing .dm-service-row__icon { background: #FFF1E4; color: var(--color-accent); }
.dm-service-column--marketing .dm-service-row:hover .dm-service-row__icon { box-shadow: 0 0 25px rgba(255, 115, 3, 0.2); background: #ff801419; }


/* Scroll entrance: the two columns slide in from opposite sides rather than
   the site-wide [data-reveal] fade-up, scoped to this section only. */
#services [data-reveal][data-reveal-dir] { transform: translateX(var(--dm-reveal-x, 0)); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
#services [data-reveal][data-reveal-dir="left"] { --dm-reveal-x: -2.5rem; }
#services [data-reveal][data-reveal-dir="right"] { --dm-reveal-x: 2.5rem; }
#services [data-reveal][data-reveal-dir].is-visible { transform: translateX(0); }

@media (max-width: 850px) {
    .dm-service-columns { grid-template-columns: 1fr; grid-template-rows: none; row-gap: 1.25rem; }
    .dm-service-column { grid-row: auto; grid-template-rows: none; }
    .dm-service-column > h3 { font-size: 23px; }
}
@media (max-width: 680px) {
    .dm-infinity__art-wrap { height: 11rem; }
    .dm-service-row__icon { width: 2.9rem; height: 2.9rem; }
    .dm-service-row__icon svg { width: 1.4rem; height: 1.4rem; }
}

/* -- #search-visibility ---------------------------------------------------------
   Navy band (the site's ink, same family as #clarity) with a faint dot grid
   and soft glows. Intro: copy left, the search illustration
   (ai-powered-search-crop.webp, cropped to its subject) as a framed panel
   right with a faint orange ring and a slow float. The six capabilities are
   not cards: a two-column ledger of open rows split by hairlines, with a
   thin spine down the middle, an orange-outlined icon ring, a serif title
   and soft white text; hover fills the ring. The disclaimer is a quiet pill.
   Scoped to this section. */
#search-visibility.dm-search {
    position: relative;
    overflow: hidden;
    color: #FFFFFF;
    background:
        radial-gradient(ellipse 45% 55% at 85% 15%, rgba(255, 101, 11, 0.14), rgba(255, 101, 11, 0) 70%),
        radial-gradient(ellipse 50% 60% at 0% 0%, rgba(60, 100, 140, 0.3), rgba(60, 100, 140, 0) 70%),
        linear-gradient(165deg, var(--color-primary) 0%, var(--color-ink) 100%);
}
#search-visibility.dm-search::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: radial-gradient(rgba(255, 255, 255, 0.08) 1px, transparent 1.2px);
    background-size: 22px 22px;
    -webkit-mask-image: radial-gradient(ellipse 60% 70% at 80% 20%, #000 0%, transparent 75%);
    mask-image: radial-gradient(ellipse 60% 70% at 80% 20%, #000 0%, transparent 75%);
}
#search-visibility.dm-search > .container { position: relative; z-index: 1; }
.dm-search__top { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.08fr); align-items: center; gap: clamp(2rem, 5vw, 4.5rem); margin-bottom: clamp(2.75rem, 5vw, 4rem); }
#search-visibility .dm-search__copy h2 { font-size: var(--fs-h2); color: #FFFFFF; }
#search-visibility .dm-search__copy h2 span { color: #FF8A3D; }
.dm-search__copy .lead { margin-top: 1.25rem; max-width: 30rem; font-size: 1.1875rem; line-height: 1.6; color: rgba(255, 255, 255, 0.72); }
.dm-search__art { position: relative; }
.dm-search__art::before {
    content: "";
    position: absolute;
    inset: -8% -6% -8% 6%;
    border-radius: 50%;
    border: 1px solid rgba(255, 138, 61, 0.28);
    pointer-events: none;
}
.dm-search__art img {
    position: relative;
    display: block;
    width: 100%;
    height: auto;
    border-radius: 24px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    box-shadow: 0 40px 70px -30px rgba(0, 0, 0, 0.6), 0 0 0 8px rgba(255, 255, 255, 0.03);
}
@media (prefers-reduced-motion: no-preference) {
    .dm-search__art img { animation: dm-search-float 9s ease-in-out infinite; }
}
@keyframes dm-search-float {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-8px); }
}

/* The ledger: two columns of open rows, hairline above each, spine between. */
.dm-search__points { position: relative; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(2.5rem, 6vw, 6rem); row-gap: 0; border-bottom: 1px solid rgba(255, 255, 255, 0.1); }
.dm-search__points::before { content: ""; position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: linear-gradient(180deg, rgba(255, 138, 61, 0.5), rgba(255, 255, 255, 0.08)); }
.dm-search__points .svc-point {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr);
    column-gap: 22px;
    align-items: start;
    padding: 28px 0;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    background: none;
    border-radius: 0;
}
.dm-search__points .svc-point__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    margin: 0;
    border-radius: 50%;
    border: 1px solid rgba(255, 138, 61, 0.55);
    background: rgba(255, 101, 11, 0.08);
    color: #FF8A3D;
    transition: background-color 0.35s var(--ease), color 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.dm-search__points .svc-point__icon svg { width: 24px; height: 24px; }
.dm-search__points .svc-point h3 { font-family: var(--font-serif); font-size: 23px; font-weight: 600; line-height: 1.2; letter-spacing: -0.01em; color: #FFFFFF; margin: 4px 0 8px; }
.dm-search__points .svc-point p { margin: 0; max-width: 30rem; font-size: 15px; line-height: 1.65; color: rgba(255, 255, 255, 0.68); }
@media (hover: hover) and (pointer: fine) {
    .dm-search__points .svc-point:hover .svc-point__icon { background: var(--color-accent); color: #FFFFFF; box-shadow: 0 0 26px rgba(255, 101, 11, 0.45); }
}

.dm-search-note { display: flex; align-items: center; gap: 12px; width: fit-content; max-width: 100%; margin: 32px auto 0; padding: 12px 20px; border-radius: 999px; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.12); font-size: 14px; line-height: 1.5; color: rgba(255, 255, 255, 0.7); }
.dm-search-note span { display: inline-flex; flex: none; align-items: center; justify-content: center; width: 1.25rem; height: 1.25rem; border: 1.5px solid #FF8A3D; border-radius: 50%; color: #FF8A3D; font-size: 12px; font-weight: 700; }

@media (max-width: 991.98px) {
    .dm-search__top { grid-template-columns: 1fr; gap: 2rem; }
    .dm-search__art { max-width: 640px; }
}
@media (max-width: 767.98px) {
    .dm-search__points { grid-template-columns: 1fr; }
    .dm-search__points::before { display: none; }
    .dm-search__points .svc-point { grid-template-columns: 46px minmax(0, 1fr); column-gap: 16px; padding: 22px 0; }
    .dm-search__points .svc-point__icon { width: 46px; height: 46px; }
    .dm-search__points .svc-point__icon svg { width: 20px; height: 20px; }
    .dm-search__points .svc-point h3 { font-size: 20px; }
    .dm-search-note { border-radius: 14px; align-items: flex-start; }
}

/* -- #useful-ai: architectural photo backdrop + orbital AI composition ------
   Rebuilt from scratch, not reusing the shared .feature-band/.svc-ai__copy/
   .ai-feature* flat-card band (Home's #ai, Web-Development's #intelligence)
   -- those are a solid-orange band with a flat 4-column row, not this
   section's own cream/photo backdrop with a central glowing orb and four
   circular cards, per reference/Digital Marketing.html's own `.ai-section`/
   `.ai-composition`/`.ai-core`/`.ai-node` rules (values reused near-verbatim
   below, including their literal gradient/shadow stops -- this is
   decorative art, not a themeable UI component). `ai-scene.webp` is the
   supplied background (architectural cream/terracotta wall + floor, no
   text or UI baked in), shown full-bleed behind both columns -- its own
   cream half already sits under the copy with no extra wash needed, same
   as the search-visibility image above. Scoped entirely to `.dm-ai*`; nothing
   shared is touched, so Home's #ai and Web-Development's #intelligence are
   unaffected. */
.dm-ai { position: relative; isolation: isolate; overflow: hidden; min-height: 46rem; display: flex; align-items: center; background: #FFFAF0; }
.dm-ai__media { position: absolute; inset: 0; z-index: 0; }
.dm-ai__media img { width: 100%; height: 100%; object-fit: cover; object-position: center; }
.dm-ai__layout { position: relative; z-index: 1; display: grid; grid-template-columns: 40% 60%; align-items: center; gap: 0.75rem; }
.dm-ai__copy { max-width: 26rem; }
.dm-ai__copy h2 { font-size: var(--fs-h2); line-height: 1.08; }
.dm-ai__copy .lead { margin-top: 2.0625rem; max-width: 24.375rem; font-size: 1.3125rem; color: #304452; }
.dm-ai-quote { margin: 2.25rem 0 0; padding-left: 1.5625rem; border-left: 2px solid var(--color-accent); font-size: 1.25rem; line-height: 1.4; max-width: 24.375rem; color: var(--color-muted); font-style: normal; }
.dm-ai-quote strong { display: block; color: var(--color-ink); margin-bottom: 0.2rem; }
/* The <br> after the (already block) strong line only added a blank line. */
.dm-ai-quote br { display: none; }

.dm-ai__art { display: flex; justify-content: center; }
.dm-ai__composition { position: relative; aspect-ratio: 1 / 1; width: 100%; max-width: 41.25rem; isolation: isolate; }
/* Orbit rings, travelling highlights and connection points live in one SVG
   sharing the composition's square box (so they stay on the cards' edges at
   any width). Highlights are short dashes sliding round the rings behind the
   cards; the dots pulse softly in turn. Animation is gated below. */
.dm-ai__orbits { position: absolute; inset: 0; width: 100%; height: 100%; z-index: -1; overflow: visible; pointer-events: none; }
.dm-ai__orb { fill: none; }
.dm-ai__orb--outer { fill: rgba(255, 255, 255, 0.05); stroke: rgba(255, 232, 205, 0.38); stroke-width: 1.8; }
.dm-ai__orb--track { stroke: rgba(255, 238, 214, 0.7); stroke-width: 2.1; }
.dm-ai__spark { fill: none; stroke: #FFF3D6; stroke-width: 4.8; stroke-linecap: round; stroke-dasharray: 9 491; filter: drop-shadow(0 0 4px rgba(255, 190, 100, 0.95)); opacity: 0.9; }
.dm-ai__spark--b { stroke-width: 3.6; stroke-dasharray: 6 394; opacity: 0.7; }
.dm-ai__pts { fill: #FFEFC9; filter: drop-shadow(0 0 5px rgba(255, 181, 79, 0.95)); }
.dm-ai__pts circle { transform-box: fill-box; transform-origin: center; }
/* The reference's own `.ai-core` (reused above, verbatim, until this
   change) is itself just a single radial-gradient + box-shadow -- flat
   next to the glossy, lit-from-upper-left glass sphere in the design the
   user actually wants (its "source of truth" screenshot of this same
   section, background photo and all -- not a different asset, the
   reference's literal CSS is simply a simplification of its own intended
   look). No standalone sphere image/sprite exists anywhere in
   reference/Digital Marketing.html to lift instead -- its own baked
   "exact-image" photo layer bakes the *entire* scene (wall, sphere, all
   four cards, copy) into one flat image, which would mean giving up the
   four cards' real text/icons to get a nicer sphere; not an even trade.
   So this is a CSS-only richer version of the same technique: the base
   gradient gains more stops for a sharper near-white hotspot fading
   through amber into a near-black far edge, `overflow:hidden` + a new
   `::before` screen-blended radial-gradient highlight stands in for a
   specular reflection, and the box-shadow gains an inset top-left "rim
   light" alongside the existing bottom-right occlusion shadow -- all still
   pure CSS, no new image asset, same `::after` organic ring / `coreGlow`
   pulse / orbit animations as before (untouched, just re-balanced to the
   new shadow list so the keyframe interpolates the same stack). */
.dm-ai__core {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 24%;
    aspect-ratio: 1;
    overflow: hidden;
    border: 2px solid #FFD9A6;
    border-radius: 50%;
    background: radial-gradient(circle at 28% 24%, #FFFDF6 0%, #FFE7BC 6%, #FFB159 18%, #FF8A2E 32%, #FF6A0A 48%, #B33800 72%, #541600 96%);
    box-shadow: 0 0 0 10px rgba(96, 32, 6, 0.42), 0 0 0 22px rgba(96, 32, 6, 0.24), inset 10px 10px 20px rgba(255, 234, 196, 0.45), inset -14px -12px 26px rgba(74, 16, 0, 0.6), 0 0 36px rgba(255, 154, 54, 0.5);
    display: grid;
    place-items: center;
    font-size: clamp(1.375rem, 1vw + 1rem, 2.125rem);
    font-weight: 400;
    color: #fff;
}
.dm-ai__core::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: radial-gradient(circle at 30% 20%, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.4) 11%, rgba(255, 255, 255, 0) 32%);
    mix-blend-mode: screen;
    pointer-events: none;
}
.dm-ai__core::after { position: absolute; content: ""; inset: 10%; border: 1px solid rgba(255, 207, 147, 0.33); border-radius: 41% 59% 50% 45%; }
@keyframes dm-ai-orbit { to { transform: rotate(360deg); } }
@keyframes dm-ai-core-glow { 50% { box-shadow: 0 0 0 10px rgba(96, 32, 6, 0.36), 0 0 0 24px rgba(96, 32, 6, 0.2), inset 10px 10px 20px rgba(255, 234, 196, 0.45), inset -14px -12px 26px rgba(74, 16, 0, 0.6), 0 0 49px rgba(255, 154, 54, 0.63); } }
@media (prefers-reduced-motion: no-preference) {
    .dm-ai__core { animation: dm-ai-core-glow 8s ease-in-out infinite; }
    .dm-ai__core::after { animation: dm-ai-orbit 40s linear infinite; }
    .dm-ai__spark--a { animation: dm-ai-slide 13s linear infinite; }
    .dm-ai__spark--b { animation: dm-ai-slide 19s linear infinite reverse; }
    .dm-ai__pts circle { animation: dm-ai-pt 5s ease-in-out infinite; }
    .dm-ai__pts circle:nth-child(2) { animation-delay: 0.4s; }
    .dm-ai__pts circle:nth-child(3) { animation-delay: 0.8s; }
    .dm-ai__pts circle:nth-child(4) { animation-delay: 1.2s; }
    .dm-ai__pts circle:nth-child(5) { animation-delay: 1.6s; }
    .dm-ai__pts circle:nth-child(6) { animation-delay: 2s; }
    .dm-ai__pts circle:nth-child(7) { animation-delay: 2.4s; }
    .dm-ai__pts circle:nth-child(8) { animation-delay: 2.8s; }
    .dm-ai__pts circle:nth-child(9) { animation-delay: 3.2s; }
    .dm-ai__pts circle:nth-child(10) { animation-delay: 3.6s; }
    .dm-ai__pts circle:nth-child(11) { animation-delay: 4s; }
    .dm-ai__pts circle:nth-child(12) { animation-delay: 4.4s; }
    /* Card = drift (transform) + a brief border glow timed to the orbit
       highlight reaching it: the 13s highlight travels ~27.7deg/s and meets
       the card edges at 60deg+k*90deg, i.e. bottom + top at 2.17s, left +
       right at 5.42s of every 6.5s (two highlights, 180deg apart). The glow
       keyframe peaks 0.195s into its cycle, so the delays below are those
       times minus 0.195s. */
    .dm-ai__node { animation: dm-ai-float 9s ease-in-out infinite, dm-ai-edge 6.5s linear infinite; }
    .dm-ai__node--top { animation-delay: 0s, 1.975s; }
    .dm-ai__node--right { animation-delay: -2.2s, 5.225s; }
    .dm-ai__node--bottom { animation-delay: -4.5s, 1.975s; }
    .dm-ai__node--left { animation-delay: -6.7s, 5.225s; }
}
@keyframes dm-ai-slide { to { stroke-dashoffset: -1000; } }
@keyframes dm-ai-pt { 0%, 100% { opacity: 0.55; transform: scale(1); } 50% { opacity: 1; transform: scale(1.9); } }
@keyframes dm-ai-float { 50% { transform: translateY(-5px); } }
@keyframes dm-ai-edge {
    0%, 24%, 100% { border-color: #FFF4D7; box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.06), 0 12px 24px rgba(103, 34, 9, 0.08), 0 0 0 0 rgba(255, 196, 110, 0); }
    3% { border-color: #FFD38E; box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.06), 0 12px 24px rgba(103, 34, 9, 0.08), 0 0 24px 7px rgba(255, 190, 100, 0.95); }
}
.dm-ai__node {
    position: absolute;
    width: 34%;
    aspect-ratio: 1;
    border-radius: 50%;
    background: linear-gradient(120deg, rgba(255, 253, 244, 0.91), rgba(242, 214, 187, 0.92));
    border: 1px solid #FFF4D7;
    box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.06), 0 12px 24px rgba(103, 34, 9, 0.08);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    text-align: center;
    padding: 1.1rem 0.9rem;
}
.dm-ai__node--top { top: 0; left: 33%; }
.dm-ai__node--left { top: 33%; left: 0; }
.dm-ai__node--right { top: 33%; right: 0; }
.dm-ai__node--bottom { bottom: 0; left: 33%; }
.dm-ai__node-icon { display: block; width: 38px; height: 38px; color: var(--color-accent); margin-bottom: 0.3rem; }
.dm-ai__node-icon svg { width: 100%; height: 100%; }
.dm-ai__node h3 { font-size: var(--fs-h3); letter-spacing: -0.03em; margin: 0 0 0.5rem; color: var(--color-ink); }
.dm-ai__node p { font-size: 0.875rem; line-height: 1.33; color: #4F4E4A; margin: 0; }

.dm-ai__mobile-points { display: none; }

@media (max-width: 1150px) {
    .dm-ai__node h3 { font-size: var(--fs-h3); margin-bottom: 0.3rem; }
    .dm-ai__node p { font-size: 14px; }
    .dm-ai__node-icon { width: 30px; height: 30px; }
}
@media (max-width: 900px) {
    .dm-ai { min-height: 0; padding-block: var(--space-section); }
    /* Below this width the photo has to crop down to a narrow vertical
       sliver -- cover zooms into the dark terracotta-wall portion of the
       image, landing the heading on a dark orange backdrop with no
       legibility treatment (this image has none built in, unlike the
       search-visibility one above). Dropped in favour of the section's
       own plain cream background, same simplification already used for
       the clarity/growth-cycle sections' own photographic backdrops. */
    .dm-ai__media { display: none; }
    .dm-ai__layout { grid-template-columns: 1fr; gap: 0; }
    .dm-ai__copy { max-width: 36rem; }
    .dm-ai__copy .lead, .dm-ai-quote { max-width: 32rem; }
    /* Reference's own responsive strategy: the orbital composition only
       works at tablet+ width; below that it swaps for a plain stacked
       list (same four items), like the reference's own `.mobile-ai-points`
       fallback -- prevents the four circles/orb from overlapping or
       clipping at narrow widths. */
    .dm-ai__art { display: none; }
    .dm-ai__mobile-points { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.75rem 1.5rem; margin-top: 2.5rem; }
    .dm-ai__mobile-points article { display: flex; gap: 0.9rem; align-items: flex-start; }
    .dm-ai__mobile-points h3 { font-size: var(--fs-h3); margin: 0 0 0.3rem; color: var(--color-ink); }
    .dm-ai__mobile-points p { font-size: 14px; line-height: 1.4; margin: 0; color: var(--color-muted); }
    .dm-ai__mobile-points .dm-ai__node-icon { flex: none; margin-bottom: 0; }
}
@media (max-width: 480px) {
    .dm-ai__mobile-points { grid-template-columns: 1fr; }
}

/* -- #useful-ai, "hub" pattern (.dm-ai--hub on the section) ---------------------
   Instead of four circles orbiting the core: the four capabilities are a
   2x2 grid of frosted-glass cards meeting at the glowing AI core, which
   sits in the middle with a cream ring that notches the cards' inner
   corners. Thin orange connector lines run out from the core along the
   gaps between the cards, with a soft pulse travelling outward. Remove the
   class to get the orbit layout back. Below 900px the shared stacked list
   (.dm-ai__mobile-points) takes over, as before. */
.dm-ai--hub .dm-ai__orbits { display: none; }
/* Copy and grid share the row proportionally with a real gap, so the copy
   never runs under the cards at narrower desktop widths. */
.dm-ai--hub .dm-ai__layout { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: clamp(1.5rem, 3.5vw, 3.5rem); }
.dm-ai--hub .dm-ai__copy { max-width: 28rem; }
.dm-ai--hub .dm-ai__composition {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-areas: "a b" "c d";
    gap: 22px;
    aspect-ratio: auto;
    max-width: 40rem;
}
.dm-ai--hub .dm-ai__composition::before,
.dm-ai--hub .dm-ai__composition::after {
    content: "";
    position: absolute;
    z-index: 0;
    pointer-events: none;
    background-size: 100% 100%;
}
/* Connector lines in the gutters: vertical then horizontal, brightest at the core. */
.dm-ai--hub .dm-ai__composition::before { left: 50%; top: 4%; bottom: 4%; width: 1.5px; transform: translateX(-50%); background-image: linear-gradient(180deg, rgba(255, 101, 11, 0), rgba(255, 101, 11, 0.55) 50%, rgba(255, 101, 11, 0)); }
.dm-ai--hub .dm-ai__composition::after { top: 50%; left: 4%; right: 4%; height: 1.5px; transform: translateY(-50%); background-image: linear-gradient(90deg, rgba(255, 101, 11, 0), rgba(255, 101, 11, 0.55) 50%, rgba(255, 101, 11, 0)); }
.dm-ai--hub .dm-ai__node {
    position: relative;
    z-index: 1;
    inset: auto;
    width: auto;
    aspect-ratio: auto;
    min-height: 15rem;
    border-radius: 24px;
    align-items: flex-start;
    justify-content: flex-start;
    text-align: left;
    padding: 28px 26px;
    background: linear-gradient(150deg, rgba(255, 255, 255, 0.86), rgba(255, 246, 236, 0.74));
    border: 1px solid rgba(255, 255, 255, 0.9);
    box-shadow: 0 24px 48px -28px rgba(120, 50, 10, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.9);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    animation: none;
    transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.dm-ai--hub .dm-ai__node--top { grid-area: a; padding-right: 64px; padding-bottom: 56px; }
.dm-ai--hub .dm-ai__node--right { grid-area: b; padding-left: 64px; padding-bottom: 56px; }
.dm-ai--hub .dm-ai__node--left { grid-area: c; padding-right: 64px; padding-top: 56px; }
.dm-ai--hub .dm-ai__node--bottom { grid-area: d; padding-left: 64px; padding-top: 56px; }
.dm-ai--hub .dm-ai__node-icon { width: 48px; height: 48px; padding: 12px; margin-bottom: 16px; border-radius: 14px; background: #FFEBDD; }
.dm-ai--hub .dm-ai__node h3 { font-size: 20px; line-height: 1.25; letter-spacing: -0.015em; margin: 0 0 8px; }
.dm-ai--hub .dm-ai__node p { font-size: 14.5px; line-height: 1.55; color: var(--color-muted); }
@media (hover: hover) and (pointer: fine) {
    .dm-ai--hub .dm-ai__node:hover { transform: translateY(-4px); box-shadow: 0 30px 54px -28px rgba(160, 60, 10, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.9); }
}
.dm-ai--hub .dm-ai__core {
    z-index: 2;
    width: 112px;
    box-shadow: 0 0 0 12px #FBF1E6, 0 0 0 13px rgba(255, 101, 11, 0.25), inset 10px 10px 20px rgba(255, 234, 196, 0.45), inset -14px -12px 26px rgba(74, 16, 0, 0.6), 0 0 44px 14px rgba(255, 154, 54, 0.45);
    font-size: 30px;
    font-weight: 600;
}
@media (prefers-reduced-motion: no-preference) {
    .dm-ai--hub .dm-ai__core { animation: dm-ai-hub-glow 6s ease-in-out infinite; }
    .dm-ai--hub .dm-ai__composition::before { background-image: linear-gradient(180deg, rgba(255, 101, 11, 0), rgba(255, 101, 11, 0.55) 50%, rgba(255, 101, 11, 0)), linear-gradient(180deg, rgba(255, 190, 120, 0) 0%, #FFC27A 50%, rgba(255, 190, 120, 0) 100%); background-size: 100% 100%, 100% 18%; background-repeat: no-repeat; animation: dm-ai-hub-pulse-v 4s ease-in-out infinite; }
    .dm-ai--hub .dm-ai__composition::after { background-image: linear-gradient(90deg, rgba(255, 101, 11, 0), rgba(255, 101, 11, 0.55) 50%, rgba(255, 101, 11, 0)), linear-gradient(90deg, rgba(255, 190, 120, 0) 0%, #FFC27A 50%, rgba(255, 190, 120, 0) 100%); background-size: 100% 100%, 18% 100%; background-repeat: no-repeat; animation: dm-ai-hub-pulse-h 4s ease-in-out 2s infinite; }
}
@keyframes dm-ai-hub-glow {
    0%, 100% { box-shadow: 0 0 0 12px #FBF1E6, 0 0 0 13px rgba(255, 101, 11, 0.25), inset 10px 10px 20px rgba(255, 234, 196, 0.45), inset -14px -12px 26px rgba(74, 16, 0, 0.6), 0 0 44px 14px rgba(255, 154, 54, 0.45); }
    50% { box-shadow: 0 0 0 12px #FBF1E6, 0 0 0 13px rgba(255, 101, 11, 0.4), inset 10px 10px 20px rgba(255, 234, 196, 0.45), inset -14px -12px 26px rgba(74, 16, 0, 0.6), 0 0 60px 20px rgba(255, 154, 54, 0.6); }
}
@keyframes dm-ai-hub-pulse-v {
    0% { background-position: 0 0, 0 50%; }
    50% { background-position: 0 0, 0 0%; }
    100% { background-position: 0 0, 0 100%; }
}
@keyframes dm-ai-hub-pulse-h {
    0% { background-position: 0 0, 50% 0; }
    50% { background-position: 0 0, 0% 0; }
    100% { background-position: 0 0, 100% 0; }
}
@media (max-width: 1150px) {
    .dm-ai--hub .dm-ai__copy .lead { font-size: 1.125rem; }
    .dm-ai--hub .dm-ai-quote { font-size: 1.0625rem; }
    .dm-ai--hub .dm-ai__node { min-height: 13.5rem; padding: 22px 20px; }
    .dm-ai--hub .dm-ai__node--top, .dm-ai--hub .dm-ai__node--left { padding-right: 52px; }
    .dm-ai--hub .dm-ai__node--right, .dm-ai--hub .dm-ai__node--bottom { padding-left: 52px; }
    .dm-ai--hub .dm-ai__node--top, .dm-ai--hub .dm-ai__node--right { padding-bottom: 48px; }
    .dm-ai--hub .dm-ai__node--left, .dm-ai--hub .dm-ai__node--bottom { padding-top: 48px; }
    .dm-ai--hub .dm-ai__core { width: 92px; font-size: 24px; }
    .dm-ai--hub .dm-ai__node h3 { font-size: 18px; }
}

/* -- #cycle: extend the shared 3-step process layout to 4 steps ------------- */
@media (min-width: 992px) { .dm-cycle-steps.svc-process-steps { grid-template-columns: repeat(4, 1fr); } }

/* -- #contact: photo backdrop + white form panel, this page only -----------
   The shared body.service-page .cta-band--contact (Web-Development's own
   contact section) is a solid navy band with a dark-glass form and an
   orange ribbon shape -- reference/Digital Marketing.html's own enquiry
   section is a full-bleed architectural photo with a plain WHITE rounded
   form panel instead. All overrides below are scoped to `#contact.dm-contact`
   (ID+class beats the shared rules' class+class, so order doesn't matter)
   -- Web-Development's #contact is untouched. The ribbon div was simply
   left out of this page's markup rather than hidden, since the photo
   itself supplies all the visual interest here. */
#contact.dm-contact { background: #331104; padding-block: var(--space-section-sm); }
#contact.dm-contact::before, #contact.dm-contact::after { content: none; }
.dm-contact__media { position: absolute; inset: 0; z-index: 0; }
.dm-contact__media img { width: 100%; height: 100%; object-fit: cover; object-position: center; }
/* The photo is full-bleed (100vw) behind a centred, capped-width container,
   so which part of the scene actually sits behind the copy column shifts
   with viewport width -- a bright/busy crop can end up directly behind the
   heading/paragraph at some laptop widths with nothing to guarantee
   contrast. A fixed scrim over the copy's own side (independent of the
   photo's crop) fixes that at every width instead of fighting individual
   crops; fades out before the form panel so the photo stays visible there. */
.dm-contact__media::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, rgba(8, 5, 2, 0.62) 0%, rgba(8, 5, 2, 0.4) 32%, rgba(8, 5, 2, 0) 62%);
}
#contact.dm-contact > .container { position: relative; z-index: 1; }
#contact.dm-contact h2 .text-accent { color: var(--color-accent-light); }
/* Shorter overall: tighter section padding, a smaller/narrower form panel
   (compact field heights/gaps, no trailing notes under the button) so the
   whole section fits one laptop screen alongside the sticky header while
   scrolling, per explicit request -- not full-viewport height, just visibly
   shorter than the previous pass. */
/* Shared .svc-contact__grid vertically centres both columns -- fine when
   they're similar heights, but this page's form is much taller than its
   copy block, which left the heading/paragraph floating with a large,
   unbalanced gap above it. The reference's own `.enquiry-layout` uses
   `align-items:start` with a small top padding instead -- same fix here. */
#contact.dm-contact .svc-contact__grid { gap: 48px; align-items: start; }
#contact.dm-contact .svc-contact__copy { padding-top: 0.5rem; }
#contact.dm-contact .cta-band__form {
    background: #fff;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border: none;
    border-radius: 16px;
    max-width: 29rem;
    padding: 1.25rem 1.5rem;
    box-shadow: 0 20px 48px rgba(20, 10, 0, 0.26);
}
#contact.dm-contact .cta-band__form h3 {
    color: var(--color-ink);
    font-size: var(--fs-h3);
    line-height: 1.25;
    margin-bottom: 0.9rem;
}
#contact.dm-contact .cta-band__form h3 .text-accent { color: var(--color-accent); }
#contact.dm-contact .contact-form .row { --bs-gutter-x: 0.75rem; --bs-gutter-y: 0.6rem; }
#contact.dm-contact .contact-form .form-label { color: var(--color-ink); font-weight: 600; font-size: 14px; margin-bottom: 0.2rem; }
.dm-required { color: var(--color-accent); }
#contact.dm-contact .contact-form .form-control,
#contact.dm-contact .contact-form .form-select {
    font-size: 14px;
    background: #fff;
    border: 1px solid var(--color-border);
    border-radius: 7px;
    color: var(--color-ink);
    min-height: 36px;
    padding: 0.45rem 0.65rem;
}
#contact.dm-contact .contact-form .form-select { color: var(--color-text); }
#contact.dm-contact .contact-form .form-select option[value=""] { color: var(--color-muted); }
#contact.dm-contact .contact-form textarea.form-control { min-height: 3.25rem; resize: vertical; }
#contact.dm-contact .contact-form .form-control::placeholder { color: var(--color-muted); opacity: 0.8; }
#contact.dm-contact .contact-form .form-control:focus,
#contact.dm-contact .contact-form .form-select:focus {
    background: #fff;
    border-color: var(--color-accent);
    color: var(--color-ink);
    box-shadow: 0 0 0 0.2rem rgba(255, 101, 11, 0.18);
}
#contact.dm-contact .cta-band__form .btn-primary { width: 100%; font-size: 14px; min-height: 38px; margin-top: 0.75rem; }

@media (max-width: 1150px) {
    #contact.dm-contact .cta-band__form { padding: 1.1rem 1.25rem; }
}
@media (max-width: 850px) {
    #contact.dm-contact .contact-form .col-md-6 { flex: 0 0 100%; max-width: 100%; }
    #contact.dm-contact .cta-band__form { max-width: none; }
}
/* Below the grid's own stacking breakpoint (.svc-contact__grid, site.css:2748)
   the copy column becomes full-width, but the media's horizontal scrim
   (::after above) only darkens the left ~62% of the full-bleed photo -- on a
   narrow single column the heading/paragraph run past that into the bright
   arch/plant area with no scrim at all, badly hurting readability. Simplest
   fix: drop the photo (and its now-pointless scrim) entirely at this width
   and let #contact.dm-contact's own solid background (#331104, sampled from
   the photo's own dark-brown side with its scrim applied, so mobile keeps
   the same warm brown tone the photo+scrim already reads as on desktop --
   not a generic near-black) show through instead -- no crop or new asset
   needed, and .dm-contact__media is aria-hidden/decorative-only so this has
   no accessibility impact. Desktop/tablet above 680px are untouched. */
@media (max-width: 680px) {
    .dm-contact__media { display: none; }
}

/* -- #faq (Data Solutions & Digital Marketing only): architectural photo
   confined to the left of the section + numbered accordion cards --
   reference/Digital Marketing.html's own `.faq-item`/`.faq-no`/`.faq-plus`
   values reused. The shared `.svc-faq-item` grid (icon + text + a plain
   generated +/- character, still used by Web-Development's own #faq, same
   id, different page) is left untouched -- every override here is scoped
   `#faq.dm-faq` (ID+class beats the shared rules' plain class/ID
   selectors). `faq-scene.webp` is confined to roughly the left 44% of the
   section (not full-bleed) with a gradient fading it out to the section's
   own plain cream (#FBF8F3) well before that edge, so the accordion panel
   sits entirely on flat cream with no photo or tint behind it -- matching
   the reference's own "photo left, plain cream right" split, not a wash
   over the whole width. The accordions themselves sit inside `.dm-faq__panel`,
   a rounded off-white card (below) that reads as floating over that split. */
#faq.dm-faq { position: relative; isolation: isolate; overflow: hidden; background: #FBF8F3; }
.dm-faq__media { position: absolute; inset: 0 auto 0 0; width: 33%; z-index: 0; }
.dm-faq__media img { width: 100%; height: 100%; object-fit: cover; object-position: 30% 45%; }
.dm-faq__media::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, transparent 0%, transparent 38%, #FBF8F3 78%);
}
#faq.dm-faq > .container { position: relative; z-index: 1; }
/* .dm-faq__panel: the rounded, warm off-white card the six accordions sit
   in, floating over the photo/cream backdrop above. Applied as a plain
   background+padding on the column's own normal-flow box (not a
   fixed-height/absolutely-positioned overlay), so the panel's box is
   always exactly as tall as its content -- it cannot be shorter than what
   is inside it at any viewport width, zoom level, or with an item open. */
.dm-faq__panel {
    background: linear-gradient(135deg, #fdfbf7, #f9f5ee);
    border-radius: 1.75rem;
    padding: 1.75rem 1.75rem 1rem;
    box-shadow: 0 25px 60px rgba(35, 20, 5, 0.14);
}
@media (max-width: 767.98px) {
    .dm-faq__panel { padding: 1.25rem 1.25rem 0.25rem; border-radius: 1.25rem; }
}

#faq.dm-faq .svc-faq-item { border: 1px solid #DFDCD7; border-radius: 1rem; background: rgba(255, 252, 247, 0.9); }
#faq.dm-faq .svc-faq-item[open] { border-color: #FFC7A8; background: rgba(255, 247, 238, 0.93); }
#faq.dm-faq .svc-faq-item summary { grid-template-columns: 2.6rem 1fr 2rem; gap: 1.05rem; font-size: 1rem; font-weight: 700; }
#faq.dm-faq .svc-faq-item summary::after { content: none; }
#faq.dm-faq .svc-faq-item__no {
    font-size: 1.5rem;
    font-weight: 400;
    color: var(--color-accent);
    letter-spacing: -0.05em;
    padding-right: 1.05rem;
    border-right: 1px solid #C6BFB7;
    line-height: 1.3;
}
#faq.dm-faq .svc-faq-item__toggle {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: 1px solid #576069;
    border-radius: 50%;
    justify-self: end;
    transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease), color 0.2s var(--ease);
}
#faq.dm-faq .svc-faq-item__toggle::before { content: "+"; font-size: 1.4rem; font-weight: 400; line-height: 1; }
#faq.dm-faq .svc-faq-item[open] .svc-faq-item__toggle { background: var(--color-accent); border-color: var(--color-accent); color: #fff; }
#faq.dm-faq .svc-faq-item[open] .svc-faq-item__toggle::before { content: "\2212"; }
#faq.dm-faq .svc-faq-item p { margin: 0.75rem 0 0 3.65rem; font-size: 14px; max-width: none; }

@media (max-width: 991.98px) {
    #faq.dm-faq .svc-faq-item summary { grid-template-columns: 2.1rem 1fr 1.75rem; gap: 0.75rem; font-size: 14px; }
    #faq.dm-faq .svc-faq-item__no { font-size: 19px; padding-right: 0.75rem; }
    #faq.dm-faq .svc-faq-item__toggle { width: 1.6rem; height: 1.6rem; }
    #faq.dm-faq .svc-faq-item p { margin-left: 2.85rem; font-size: 14px; }
    /* Below lg, the text and card columns stack full-width (Bootstrap's
       col-lg-4/col-lg-8 default) -- a 44%-wide photo strip no longer reads
       as "behind the text", so it's dropped in favour of the section's
       own plain cream, same simplification used for the other photo
       backdrops on this page at narrow widths. */
    .dm-faq__media { display: none; }
}

/* -- #cycle (Data Solutions & Digital Marketing only): blob-shaped photo +
   corner icon badge + big number, a solid connecting line, static
   arrow-circle connectors -- reference/Digital Marketing.html's own
   `.cycle-picture`/`.cycle-picture .icon`/`.cycle-number`/`.cycle-line`
   values reused (its path/colour, not its dash-animation -- see the line's
   own rule further down for why). Scoped `#cycle`
   (an ID the shared `.svc-process-step*` classes below don't carry) so
   Web-Development's own #process (same shared classes) is untouched --
   confirmed live. Heading/body copy sizes intentionally NOT bumped to the
   reference's own larger px values, consistent with this page's established
   convention elsewhere (matching the rest of the site's type scale, not
   introducing a one-off larger size). */
/* Pastel-wave backdrop (CSS/SVG only, no photo): warm ivory base, two
   nested pale-orange curved shapes top-right, a solid curved peach wave
   band along the bottom -- per the user's own screen recording and
   explicit description. Rebuilt as flat-filled SVG shapes (clean curved
   edges) rather than the previous soft radial-gradient blurs, which read
   as too faint/diffuse and (per that recording) wrongly included a blue
   top-left tint that doesn't belong here at all -- dropped. This is a
   close approximation of organic generated art, not a pixel replica --
   flagged, not silently presented as exact. */
.dm-cycle { position: relative; isolation: isolate; overflow: hidden; background: #FDF6EC; }
.dm-cycle__bg {
    position: absolute;
    inset: 0;
    z-index: 0;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1280 760' preserveAspectRatio='none'%3E%3Ccircle cx='1360' cy='-40' r='430' fill='%23FFD9B8' fill-opacity='0.55'/%3E%3Ccircle cx='1300' cy='140' r='300' fill='%23FFE8D4' fill-opacity='0.6'/%3E%3Cpath d='M0 660 C 220 600 420 700 640 630 S 1060 590 1280 650 L1280 760 L0 760 Z' fill='%23FFD9B8' fill-opacity='0.5'/%3E%3Cpath d='M0 700 C 220 650 420 745 640 685 S 1060 645 1280 695 L1280 760 L0 760 Z' fill='%23FFC9A0' fill-opacity='0.45'/%3E%3C/svg%3E");
}
#cycle.dm-cycle > .container { position: relative; z-index: 1; }

/* Plain solid stroke -- per the user's own screen recording, this
   connecting line reads as a clean continuous line with no dash/dot
   pattern and no visible motion, not the reference's own fine
   stroke-dasharray animation (which, at this path's rendered scale/
   preserveAspectRatio:none stretch, looked like obvious dots rather than
   the reference's subtle shimmer). Matching what was actually observed
   over matching the reference's raw CSS value. */
#cycle .dm-cycle__line { top: 95px; height: 70px; }
#cycle .dm-cycle__line path { stroke: #FF8F51; stroke-width: 1.5; opacity: 0.85; }

.dm-cycle__arrow {
    position: absolute;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    border: 1px solid rgba(255, 143, 81, 0.7);
    background: #FFFAF3;
    color: var(--color-accent);
}
.dm-cycle__arrow svg { width: 1.1rem; height: 1.1rem; }
/* The arrows are also direct children of the [data-reveal-group] that
   staggers the four cards in -- its `[data-reveal-group] > *`/
   `[data-reveal-group].is-visible > *` rules carry a class each (0,1,0)
   and (0,2,0) of specificity, which beats this plain `.dm-cycle__arrow`
   class (0,1,0) once the section is revealed, replacing this centering
   translate with the group's own translateY and snapping every circle
   down-right by half its own size (it was still winning, by source order
   only, before reveal -- which is why this only ever showed up once the
   section had scrolled into view). The `#cycle` prefix below gives it ID
   specificity so the centering transform always wins, in both states. */
#cycle .dm-cycle__arrow { transform: translate(-50%, -50%); }
/* `left` is each gap's centre between the 4 cards: with equal columns and
   a shared gap g over total width W, the middle gap always sits at exactly
   50%, and the outer two sit symmetrically at 25% +/- g/(4W) (derived from
   the grid math, not eyeballed) -- clamp(2rem,6vw,5.25rem) keeps g/(4W)
   close to ~1.6-1.7% across the desktop breakpoints this row is shown at.
   `top` is each gap-centre x fed through the connecting path's own cubic
   bezier (read via path.getPointAtLength in the browser at that same x, in
   the SVG's viewBox units -- which equal this box's own pixels 1:1 since
   the SVG is 70px tall for a 70-unit-tall viewBox) -- not a flat value,
   since the path is a wavy S-curve whose y differs at each x. */
.dm-cycle__arrow--1 { left: 23.35%; top: 154px; }
.dm-cycle__arrow--2 { left: 50%; top: 137px; }
.dm-cycle__arrow--3 { left: 76.65%; top: 128px; }

#cycle .svc-process-step__art.dm-cycle__pic { position: relative; width: 190px; height: 190px; margin-bottom: 1.5rem; }
#cycle .dm-cycle__pic img { width: 100%; height: 100%; object-fit: cover; border-radius: 0 48% 42% 48%; }
#cycle .dm-cycle__pic:hover img { transform: none; }
.dm-cycle__icon {
    position: absolute;
    bottom: -0.45rem;
    right: -1.05rem;
    width: 3.75rem;
    height: 3.75rem;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: #FFF5E9;
    color: var(--color-accent);
    box-shadow: 0 6px 12px rgba(78, 42, 13, 0.08);
    transition: box-shadow 0.3s var(--ease);
}
.dm-cycle__icon svg { width: 55%; height: 55%; }
#cycle .dm-cycle__pic:hover .dm-cycle__icon { box-shadow: 0 0 0 2px rgba(255, 101, 11, 0.45), 0 0 16px rgba(255, 101, 11, 0.45), 0 6px 12px rgba(78, 42, 13, 0.08); }

@media (max-width: 991.98px) {
    .dm-cycle__arrow { display: none; }
    #cycle .svc-process-step__art.dm-cycle__pic { width: 165px; height: 165px; }
}
@media (max-width: 767.98px) {
    #cycle .svc-process-step__art.dm-cycle__pic { width: 150px; height: 150px; }
    .dm-cycle__icon { width: 3.25rem; height: 3.25rem; }
}

/* #cycle refinement: every step is centred under its picture, with title +
   text in a soft glass card (the step's own ::before, spanning the title and
   text rows). From 992px the four steps share one three-row grid (subgrid)
   so pictures, titles and texts line up across even when one title wraps.
   Motion: a glow travels the connector curve every 8s and each step lights
   up as it passes (icon badge fills, the dashed ring round the picture
   brightens); the pictures float gently. Reduced motion: all static. */
#cycle .svc-process-step { display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto 1fr; justify-items: center; text-align: center; }
#cycle .svc-process-step > * { grid-column: 1; }
#cycle .svc-process-step::before {
    content: "";
    grid-row: 2 / 4;
    grid-column: 1;
    align-self: stretch;
    justify-self: stretch;
    z-index: -1;
    border-radius: 20px;
    background: rgba(255, 255, 255, 0.62);
    border: 1px solid rgba(240, 215, 190, 0.85);
    box-shadow: 0 18px 36px -26px rgba(150, 80, 30, 0.35);
}
#cycle .svc-process-step { position: relative; z-index: 1; isolation: isolate; }
#cycle .svc-process-step h3 { grid-row: 2; align-self: end; margin: 0; padding: 26px 22px 10px; font-family: var(--font-serif); font-size: 22px; font-weight: 600; line-height: 1.2; letter-spacing: -0.01em; color: var(--color-ink); }
#cycle .svc-process-step p { grid-row: 3; max-width: 17rem; margin: 0; padding: 0 22px 26px; font-size: 14.5px; line-height: 1.6; color: var(--color-muted); }
#cycle .svc-process-step__art.dm-cycle__pic { grid-row: 1; margin-bottom: 28px; }
/* dashed ring round each picture; lit in turn by the animation below */
#cycle .dm-cycle__pic::before {
    content: "";
    position: absolute;
    inset: -12px;
    border-radius: 50%;
    border: 1.5px dashed rgba(255, 143, 81, 0.35);
    pointer-events: none;
}
#cycle .dm-cycle__pulse { stroke: #FFD3A8; stroke-width: 4; stroke-linecap: round; stroke-dasharray: 0.06 1; stroke-dashoffset: 0.06; opacity: 0; filter: drop-shadow(0 0 5px rgba(255, 140, 50, 0.9)); }
@media (min-width: 992px) {
    .dm-cycle-steps.svc-process-steps { grid-template-rows: auto auto auto; row-gap: 0; }
    #cycle .svc-process-step { grid-row: span 3; grid-template-rows: subgrid; }
}
@media (min-width: 768px) and (max-width: 991.98px) {
    .dm-cycle-steps.svc-process-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 2.5rem; }
    #cycle .dm-cycle__line { display: none; }
}
@media (max-width: 767.98px) {
    #cycle .dm-cycle__line { display: none; }
    #cycle .svc-process-step h3 { font-size: 20px; padding-top: 22px; }
}
@media (prefers-reduced-motion: no-preference) {
    #cycle .dm-cycle__pulse { animation: dm-cycle-pulse 8s linear infinite; }
    #cycle .dm-cycle__pic img { animation: dm-cycle-float 7s ease-in-out infinite; }
    #cycle .svc-process-step:nth-of-type(2) .dm-cycle__pic img { animation-delay: -1.75s; }
    #cycle .svc-process-step:nth-of-type(3) .dm-cycle__pic img { animation-delay: -3.5s; }
    #cycle .svc-process-step:nth-of-type(4) .dm-cycle__pic img { animation-delay: -5.25s; }
    #cycle .dm-cycle__pic::before { animation: dm-cycle-ring 8s linear infinite, dm-cycle-spin 30s linear infinite; }
    #cycle .dm-cycle__icon { animation: dm-cycle-badge 8s linear infinite; }
    /* the glow passes each picture's centre at ~12.5/37.5/62.5/87.5% of its run */
    #cycle .svc-process-step:nth-of-type(1) .dm-cycle__pic::before, #cycle .svc-process-step:nth-of-type(1) .dm-cycle__icon { animation-delay: 0s, 0s; }
    #cycle .svc-process-step:nth-of-type(2) .dm-cycle__pic::before, #cycle .svc-process-step:nth-of-type(2) .dm-cycle__icon { animation-delay: 2s, 0s; }
    #cycle .svc-process-step:nth-of-type(3) .dm-cycle__pic::before, #cycle .svc-process-step:nth-of-type(3) .dm-cycle__icon { animation-delay: 4s, 0s; }
    #cycle .svc-process-step:nth-of-type(4) .dm-cycle__pic::before, #cycle .svc-process-step:nth-of-type(4) .dm-cycle__icon { animation-delay: 6s, 0s; }
}
@keyframes dm-cycle-pulse {
    0% { stroke-dashoffset: 0.06; opacity: 0; }
    3% { opacity: 1; }
    95% { opacity: 1; }
    100% { stroke-dashoffset: -1; opacity: 0; }
}
@keyframes dm-cycle-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes dm-cycle-spin { to { rotate: 360deg; } }
@keyframes dm-cycle-ring {
    0%, 30%, 100% { border-color: rgba(255, 143, 81, 0.35); box-shadow: none; }
    10%, 18% { border-color: rgba(255, 101, 11, 0.9); box-shadow: 0 0 18px rgba(255, 101, 11, 0.25); }
}
@keyframes dm-cycle-badge {
    0%, 30%, 100% { background: #FFF5E9; color: var(--color-accent); }
    10%, 18% { background: var(--color-accent); color: #FFFFFF; }
}

/* ============================================================================
   MANAGED IT & CLOUD (#services/managed-it-cloud/) -- a brand new page built
   from reference/Valin-Services-Managed-IT-Cloud.html, its own self-contained
   static export (not the "chapter" mockup tool the Data Marketing reference
   used). Colour tokens match this project's own var(--color-accent)/
   var(--color-ink) exactly (#ff650b / #091e30 -- the reference's own
   --orange/--ink), reused directly; its --navy/--cream/--muted/--line
   (#082333/#faf8f3/#596979/#d8dad8) have no existing equivalents in this
   project's token set, so they're literal hex here, scoped to `.itc-*`.
   Breakpoints (1100/850/600) are the reference's own. All art is this
   project's usual pre-cropped .webp convention (Python/PIL), not the
   reference's inline oversized-image-+-percentage-crop technique -- the
   source illustrations (one shared image reused across several numbered
   cards via percentage crops) were cropped once into one small .webp per
   card instead, same end result, no fragile runtime positioning. Scoped
   entirely to `.itc-*`; nothing shared is touched. */

.itc-btn { color: #09202d; }

/* -- hero: split grid, left copy / right bleed-right photo with a soft left
   fade so it reads as continuous with the page background, same technique
   as this project's other service-hero art. A small pulsing glow dot sits
   over the art, per the reference's own `.hero-art:after` detail. */
.itc-hero { padding: 10px 0 75px; overflow: hidden; }
.itc-hero__grid { display: grid; grid-template-columns: 1fr 1.15fr; align-items: center; gap: 35px; min-height: 590px; }
.itc-hero h1 { font-size: var(--fs-h1); line-height: 1.04; letter-spacing: -0.045em; }
.itc-hero .btn { margin-top: 35px; }
.itc-hero__art { position: relative; margin-right: -70px; width: calc(100% + 70px); align-self: center; mask-image: linear-gradient(90deg, transparent, #000 8%, #000 97%, transparent); }
.itc-hero__art img { width: 100%; height: auto; display: block; }
/* Light layer over the hero photo: an SVG in the photo's own 912x861 box (the art box is the image's box), so bead, lights and reflections stay on the
   cables/servers/glass they were traced to at every width. The bead and reflections run on SMIL inside the SVG; the indicator-light pulses are the CSS
   below. Decorative, and removed entirely for reduced motion. */
.itc-hero__fx { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.itc-hero__led { fill: url(#itc-led); opacity: 0.2; transform-box: fill-box; transform-origin: center; animation: itc-led 4.6s ease-in-out infinite; }
.itc-hero__led:nth-child(5n+2) { animation-delay: -0.9s; }
.itc-hero__led:nth-child(5n+3) { animation-delay: -1.8s; }
.itc-hero__led:nth-child(5n+4) { animation-delay: -2.7s; }
.itc-hero__led:nth-child(5n) { animation-delay: -3.6s; }
.itc-hero__led:nth-child(3n) { animation-duration: 5.6s; }
@keyframes itc-led { 0%, 100% { opacity: 0.18; transform: scale(0.8); } 50% { opacity: 0.85; transform: scale(1.12); } }
/* Final glow on the big server's dark top: screen-blended so it only adds light there. */
.itc-hero__srvtop { mix-blend-mode: screen; }
@media (prefers-reduced-motion: reduce) { .itc-hero__fx { display: none; } }
.itc-hero__art::after { content: ""; position: absolute; width: 5px; height: 5px; border-radius: 50%; background: #ffc173; left: 68%; top: 68%; box-shadow: 0 0 12px 4px rgba(255, 156, 33, 0.25); }
@media (prefers-reduced-motion: no-preference) { .itc-hero__art::after { animation: itc-signal 8s ease-in-out infinite; } }
@keyframes itc-signal { 0%, 100% { opacity: 0.3; transform: scale(1); } 50% { opacity: 1; transform: scale(2.4); } }
@media (max-width: 1100px) {
    .itc-hero { padding: 20px 0 75px; }
    .itc-hero__art { width: calc(100% + 32px); margin-right: -32px; }
}
@media (max-width: 850px) {
    .itc-hero__grid { grid-template-columns: 1fr 1fr; min-height: 430px; gap: 15px; }
    .itc-hero h1 { font-size: var(--fs-h1); }
    .itc-hero__art { width: calc(100% + 70px); margin-left: -15px; margin-right: -55px; }
}
@media (max-width: 600px) {
    .itc-hero { padding: 42px 0 32px; }
    .itc-hero__grid { display: flex; flex-direction: column; align-items: stretch; gap: 20px; min-height: 0; }
    .itc-hero h1 { font-size: var(--fs-h1); max-width: 430px; }
    .itc-hero .btn { margin-top: 28px; }
    .itc-hero__art { margin: 0 -22px; width: calc(100% + 44px); }
}

/* -- challenges: heading + lead, then a 2x2 "issue" grid (copy + small art
   per card), closing on a solid navy banner. */
.itc-challenges { padding-top: var(--space-section); padding-bottom: var(--space-section); }
.itc-challenges > .container > h2 { max-width: 1000px; }
.itc-challenges .lead { max-width: 1000px; margin-top: 23px; font-size: 17px; }
.itc-issue-grid { display: grid; grid-template-columns: 1fr 1fr; margin-top: 45px; }
.itc-issue-grid article { display: grid; grid-template-columns: 1.08fr 0.92fr; align-items: center; gap: 18px; padding: 32px 28px 32px 0; border-bottom: 1px solid var(--color-border); }
.itc-issue-grid article:nth-child(even) { border-left: 1px solid var(--color-border); padding-left: 32px; padding-right: 0; }
.itc-issue-grid article:nth-last-child(-n+2) { border-bottom: 0; }
/* Three clear levels: the section h2 (ink, its second half in orange), the
   card titles (smaller, deep blue, a short orange bar above), then muted
   body text -- instead of every heading in the same black bold. */
.itc-challenges > .container h2 span { color: var(--color-accent); }
.itc-issue-copy h3 { margin-bottom: 12px; font-size: 22px; line-height: 1.25; font-weight: 700; letter-spacing: -0.015em; color: var(--color-primary); }
/* Each issue opens with a small icon chip that names the problem (a looping
   arrow for recurring issues, a person with a question mark, a cloud with an
   alert, a rising line), each with its own gentle motion and a soft ping ring. */
.itc-issue-icon { position: relative; display: grid; place-items: center; width: 46px; height: 46px; margin-bottom: 16px; border-radius: 14px; background: #FFF0E5; color: var(--color-accent); border: 1px solid rgba(255, 101, 11, 0.22); }
.itc-issue-icon svg { width: 23px; height: 23px; }
@media (prefers-reduced-motion: no-preference) {
    .itc-issue-icon::after { content: ""; position: absolute; inset: -1px; border-radius: 14px; border: 1.5px solid rgba(255, 101, 11, 0.45); animation: itc-issue-ping 3.2s ease-out infinite; }
    article:nth-child(2) .itc-issue-icon::after { animation-delay: 0.8s; }
    article:nth-child(3) .itc-issue-icon::after { animation-delay: 1.6s; }
    article:nth-child(4) .itc-issue-icon::after { animation-delay: 2.4s; }
    .itc-issue-icon--loop svg { animation: itc-issue-spin 6s linear infinite; }
    .itc-issue-icon--who svg { animation: itc-issue-nod 3s ease-in-out infinite; }
    .itc-issue-icon--cloud svg { animation: itc-issue-drift 4s ease-in-out infinite; }
    .itc-issue-icon--grow svg path:first-child { stroke-dasharray: 26; animation: itc-issue-draw 3.2s ease-in-out infinite; }
}
@keyframes itc-issue-ping { 0% { opacity: 0.8; scale: 1; } 70%, 100% { opacity: 0; scale: 1.35; } }
@keyframes itc-issue-spin { to { rotate: 360deg; } }
@keyframes itc-issue-nod { 0%, 100% { rotate: 0deg; } 30% { rotate: -8deg; } 60% { rotate: 6deg; } }
@keyframes itc-issue-drift { 0%, 100% { translate: 0 0; } 50% { translate: 0 -2px; } }
@keyframes itc-issue-draw { 0% { stroke-dashoffset: 26; } 45%, 80% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: -26; } }
.itc-issue-copy p { font-size: 15px; line-height: 1.65; color: var(--color-muted); }
.itc-issue-art { width: 100%; }
/* Card 4's crop (the shared source illustration's 4th icon) has a sliver of
   the heading text ("...nent" from "Environment") bleeding into its top-left
   corner -- the reference hides the exact same bleed on its own version of
   this card with this same notch clip-path rather than a tighter crop. */
.itc-issue-art--notch { clip-path: polygon(17% 0, 100% 0, 100% 100%, 0 100%, 0 40%, 17% 40%); }
.itc-issue-art img { width: 100%; height: auto; display: block; }
.itc-closing { background: #082333; color: #fff; padding: 26px 30px; text-align: center; border-radius: 7px; margin-top: 22px; font-size: 20px; line-height: 1.4; }
.itc-closing em { font-weight: 600; font-style: normal; color: inherit; }
.itc-closing em.text-accent { color: var(--color-accent); }
@media (max-width: 1100px) {
    .itc-issue-grid article { grid-template-columns: 1fr 0.75fr; gap: 10px; padding-right: 22px; }
    .itc-issue-grid article:nth-child(even) { padding-left: 22px; }
    .itc-issue-copy h3 { font-size: 20px; }
    .itc-issue-copy p { font-size: 14px; }
}
@media (max-width: 850px) {
    .itc-issue-grid { gap: 0; }
    .itc-issue-grid article { display: flex; flex-direction: column; align-items: stretch; }
    .itc-issue-art { width: 70%; align-self: center; }
}
@media (max-width: 600px) {
    .itc-challenges .lead { font-size: 16px; }
    .itc-issue-grid { grid-template-columns: 1fr; margin-top: 24px; }
    .itc-issue-grid article, .itc-issue-grid article:nth-child(even) { border-left: 0; border-bottom: 1px solid var(--color-border); padding: 30px 0; }
    .itc-issue-grid article:last-child { border: 0; }
    .itc-issue-copy h3 { font-size: 20px; }
    .itc-issue-copy p { font-size: 15px; }
    .itc-issue-art { width: 72%; margin-top: 14px; }
    .itc-closing { font-size: 19px; text-align: left; padding: 24px; }
}

/* -- services ("One Environment Managed as a Whole"): staggered, connected
   layout drawn on a 1024x410 stage (aspect-ratio keeps every % / cqw
   position and the SVG's viewBox in the same coordinate space, so rings,
   dotted paths, nodes and cards stay registered at any width). Light
   background with network lines/ripples in the SVG; the old managed.webp
   artwork (baked dotted curves that couldn't line up with this layout) is
   no longer used here. Below 1100px the stage collapses to a plain card
   grid (rings, paths and decor hidden). */
.itc-services {
    position: relative;
    padding-top: clamp(56px, 6vw, 84px);
    padding-bottom: clamp(56px, 6vw, 84px);
    overflow: hidden;
    background:
        radial-gradient(60rem 28rem at 0% 78%, rgba(255, 150, 70, 0.2), transparent 65%),
        radial-gradient(50rem 34rem at 100% 70%, rgba(120, 180, 240, 0.22), transparent 65%),
        linear-gradient(120deg, #ffffff 0%, #fdfaf6 40%, #f3f8fd 100%);
}
.itc-services h2 { margin-bottom: 1rem; font-size: var(--fs-h2); line-height: 1.2; font-weight: 700; letter-spacing: -0.02em; }
.itc-flow { position: relative; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem; padding-top: 1rem; }
.itc-ring, .itc-flow__art { display: none; }
.itc-card { position: relative; background: linear-gradient(180deg, #ffffff, #fbf7f2); border: 1px solid rgba(255, 138, 38, 0.3); border-radius: 14px; padding: 1.1rem 1.1rem 1.1rem 3.6rem; box-shadow: 0 10px 24px -14px rgba(9, 30, 48, 0.3), inset 0 0 0 100vmax rgba(255, 138, 38, 0); transition: opacity 0.6s var(--ease), transform 0.3s var(--ease), box-shadow 0.3s var(--ease); }
.itc-card__badge { position: absolute; left: -0.9rem; top: 0.9rem; display: flex; align-items: center; justify-content: center; width: 2.6rem; height: 2.6rem; border-radius: 50%; background: #ff7a1a; border: 2px solid #ff8a26; color: #fff; transition: background-color 0.3s var(--ease), color 0.3s var(--ease), filter 0.9s var(--ease), text-shadow 0.9s var(--ease); font-weight: 700; font-size: 15px; box-shadow: 0 4px 10px rgba(255, 106, 19, 0.25); }
/* Hover: card lifts with a faint orange tint (inset shadow, so it
   transitions); its number flips white -> orange (the disc goes white so the
   orange number stays legible). Other cards untouched. The group-reveal
   stagger delay is zeroed on hover so the response is immediate. */
.itc-card:hover { transform: translateY(-6px); box-shadow: 0 16px 28px -14px rgba(255, 106, 19, 0.35), inset 0 0 0 100vmax rgba(255, 138, 38, 0.09); }
.itc-flow.is-visible > .itc-card:hover { transition-delay: 0s; }
/* Cards 04 and 05 are the blue pair: same hover lift, but a light blue glow/tint instead of orange. */
.itc-card--4:hover, .itc-card--5:hover { box-shadow: 0 16px 28px -14px rgba(47, 141, 232, 0.35), inset 0 0 0 100vmax rgba(90, 167, 240, 0.09); }
.itc-card:hover .itc-card__badge { background: #fff; color: #ff6a13; }
/* Scroll highlight: once the section first scrolls into view (app.js adds
   .is-lit a single time) the numbers brighten with a soft white glow and stay
   lit -- never orange, and not re-triggered on scrolling in/out. Before that
   (only when JS armed it) they sit slightly dimmed. */
.itc-flow.is-armed .itc-card__badge { filter: brightness(0.88); }
.itc-flow.is-lit .itc-card__badge { filter: brightness(1.08); text-shadow: 0 0 6px rgba(255, 255, 255, 0.95); }
.itc-flow.is-lit .itc-card--2 .itc-card__badge { transition-delay: 0s, 0s, 0.15s, 0.15s; }
.itc-flow.is-lit .itc-card--3 .itc-card__badge { transition-delay: 0s, 0s, 0.3s, 0.3s; }
.itc-flow.is-lit .itc-card--4 .itc-card__badge { transition-delay: 0s, 0s, 0.45s, 0.45s; }
.itc-flow.is-lit .itc-card--5 .itc-card__badge { transition-delay: 0s, 0s, 0.6s, 0.6s; }
@media (prefers-reduced-motion: reduce) {
    .itc-card, .itc-card__badge { transition: none; }
    .itc-card:hover { transform: none; }
}
.itc-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.4rem; }
/* One title size for all five cards (scaled with the layout from 1101px). */
.itc-card h3 { margin: 0; font-size: 20px; line-height: 1.22; font-weight: 700; letter-spacing: -0.01em; color: var(--color-ink); overflow-wrap: break-word; }
.itc-card__icon { flex: none; color: #4a5563; }
.itc-card__icon svg { width: 1.3rem; height: 1.3rem; display: block; }
.itc-card p { margin: 0; font-size: 14px; line-height: 1.5; color: var(--color-muted); }
@media (min-width: 1101px) {
    /* Wider than the text container (up to 1400px, never past the viewport's
       24px gutters) so the whole diagram, sized in cqw, scales up together. */
    .itc-flow { display: block; container-type: inline-size; aspect-ratio: 1024 / 410; padding-top: 0; width: min(1400px, 100vw - 48px); margin-left: calc(50% - min(700px, 50vw - 24px)); }
    .itc-ring, .itc-flow__art { display: block; position: absolute; }
    .itc-flow__art { inset: 0; width: 100%; height: 100%; z-index: 2; pointer-events: none; overflow: visible; }
    .itc-flow__ripples circle { stroke-width: 0.9; opacity: 0.3; }
    .itc-flow__dots path { stroke-width: 2.6; stroke-dasharray: 0.1 8; }
    /* Highlight travelling along the existing dotted connectors: a short
       bright dash on a copy of each path (butt caps, pathLength-normalised, so
       it starts fully before and ends fully past the line and can't overshoot).
       The connectors themselves never move; four segments take turns. */
    .itc-flow__spark { fill: none; stroke: #fff; filter: drop-shadow(0 0 3px rgba(255, 255, 255, 0.9)); stroke-width: 3.6; stroke-linecap: butt; stroke-dasharray: 55 1000; stroke-dashoffset: 55; opacity: 0; }
}
@media (min-width: 1101px) and (prefers-reduced-motion: no-preference) {
    .itc-ring--4, .itc-ring--5 { transition: box-shadow 0.3s var(--ease); }
    .itc-node--4, .itc-node--5 { transition: filter 0.3s var(--ease); }
    .itc-flow.is-visible .itc-flow__spark { opacity: 0.95; animation: itc-spark-travel 8s linear infinite; }
    .itc-flow.is-visible .itc-flow__spark:nth-child(2) { animation-delay: 2s; }
    .itc-flow.is-visible .itc-flow__spark:nth-child(3) { animation-delay: 4s; }
    .itc-flow.is-visible .itc-flow__spark:nth-child(4) { animation-delay: 6s; }
}
/* The travelling white highlight "lights" each number's disc (the number
   itself is left alone) as it arrives: badge 1
   as the first segment leaves, 2-5 as the previous segment reaches them
   (segment i runs 2s*(i-1) .. +1.44s of the 8s loop). Same breakpoint/motion
   gates as the highlight itself. */
@media (min-width: 1101px) and (prefers-reduced-motion: no-preference) {
    .itc-flow.is-visible .itc-card__badge { animation: itc-badge-lit 8s ease-out infinite; }
    .itc-flow.is-visible .itc-card--2 .itc-card__badge { animation-delay: 0.8s; }
    .itc-flow.is-visible .itc-card--3 .itc-card__badge { animation-delay: 2.8s; }
    .itc-flow.is-visible .itc-card--4 .itc-card__badge { animation-delay: 4.8s; }
    .itc-flow.is-visible .itc-card--5 .itc-card__badge { animation-delay: 6.8s; }
    .itc-flow.is-visible .itc-card:hover .itc-card__badge { animation: none; }
}
@keyframes itc-badge-lit {
    0%, 14%, 100% { background-color: #ff7a1a; box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
    5% { background-color: #ffe9d2; box-shadow: 0 0 16px 4px rgba(255, 255, 255, 0.95); }
}
@keyframes itc-spark-travel { 0% { stroke-dashoffset: 55; } 18% { stroke-dashoffset: -1000; } 100% { stroke-dashoffset: -1000; } }
@media (min-width: 1101px) {
    .itc-ring { z-index: 1; box-sizing: border-box; border-radius: 50%; border-style: solid; border-width: 0.7cqw; background: radial-gradient(circle at 50% 45%, #ffffff 60%, #f3eee9 100%); box-shadow: 0 1.2cqw 3cqw -1cqw rgba(9, 30, 48, 0.22), inset 0 0 2.4cqw rgba(255, 255, 255, 0.9); pointer-events: none; }
    .itc-card { position: absolute; z-index: 3; padding: 1.2cqw 1cqw 1.2cqw 3.1cqw; border-radius: 1.4cqw; box-shadow: 0 1cqw 2.4cqw -1cqw rgba(9, 30, 48, 0.3), inset 0 0 0 0.12cqw rgba(255, 255, 255, 0.8), inset 0 0 0 100vmax rgba(255, 138, 38, 0); }
    .itc-card__badge { left: -1.6cqw; top: 1.7cqw; width: 3.7cqw; height: 3.7cqw; font-size: clamp(14px, 1.6cqw, 1.1rem); border-width: 0.25cqw; }
    .itc-card__head { margin-bottom: 0.5cqw; }
    .itc-card h3 { font-size: clamp(15px, 1.55cqw, 22px); }
    .itc-card__icon svg { width: clamp(0.95rem, 1.6cqw, 1.3rem); height: clamp(0.95rem, 1.6cqw, 1.3rem); }
    .itc-card p { font-size: clamp(14px, 1.08cqw, 15.5px); line-height: 1.5; }
    .itc-card--1 { left: 7.3cqw; top: 4.4cqw; width: 19.6cqw; }
    .itc-card--2 { left: 28.3cqw; top: 16.8cqw; width: 19.4cqw; }
    .itc-card--3 { left: 50.3cqw; top: 4.6cqw; width: 19.4cqw; }
    .itc-card--4 { left: 54.0cqw; top: 24.4cqw; width: 19.6cqw; }
    .itc-card--5 { left: 76.2cqw; top: 12.9cqw; width: 19.4cqw; }
    .itc-ring--1 { left: 5.4cqw; top: 1.0cqw; width: 18.6cqw; height: 18.6cqw; border-color: #ff8a26 #ff8a26 transparent transparent; rotate: -35deg; }
    .itc-ring--2 { left: 29.3cqw; top: 14.6cqw; width: 16.6cqw; height: 16.6cqw; border-color: transparent transparent #f3b78d #f3b78d; rotate: 15deg; }
    .itc-ring--3 { left: 51.1cqw; top: 0.8cqw; width: 17.1cqw; height: 17.1cqw; border-color: #ff8a26 transparent transparent #ff8a26; rotate: 20deg; }
    .itc-ring--4 { left: 55.0cqw; top: 20.3cqw; width: 17.1cqw; height: 17.1cqw; border-color: #5aa7f0 #5aa7f0 transparent transparent; rotate: -10deg; box-shadow: 0 1.2cqw 3cqw -1cqw rgba(9, 30, 48, 0.22), inset 0 0 2.4cqw rgba(255, 255, 255, 0.9), 0 0 0 0 rgba(90, 167, 240, 0); }
    /* Card 04's arch and right-hand connection point are blue (same #5aa7f0 / #2f8de8 as card 05's); hovering the card lights both with a soft blue glow. */
    .itc-flow:has(.itc-card--4:hover) .itc-ring--4 { box-shadow: 0 1.2cqw 3cqw -1cqw rgba(9, 30, 48, 0.22), inset 0 0 2.4cqw rgba(255, 255, 255, 0.9), 0 0 1.8cqw 0.25cqw rgba(90, 167, 240, 0.45); }
    .itc-flow:has(.itc-card--4:hover) .itc-node--4 { filter: drop-shadow(0 0 4px rgba(47, 141, 232, 0.85)); }
    .itc-flow:has(.itc-card--5:hover) .itc-ring--5 { box-shadow: 0 1.2cqw 3cqw -1cqw rgba(9, 30, 48, 0.22), inset 0 0 2.4cqw rgba(255, 255, 255, 0.9), 0 0 1.8cqw 0.25cqw rgba(90, 167, 240, 0.45); }
    .itc-flow:has(.itc-card--5:hover) .itc-node--5 { filter: drop-shadow(0 0 4px rgba(47, 141, 232, 0.85)); }
    .itc-ring--5 { left: 76.2cqw; top: 9.3cqw; width: 17.6cqw; height: 17.6cqw; border-color: #5aa7f0 #5aa7f0 #5aa7f0 transparent; rotate: 30deg; box-shadow: 0 1.2cqw 3cqw -1cqw rgba(9, 30, 48, 0.22), inset 0 0 2.4cqw rgba(255, 255, 255, 0.9), 0 0 0 0 rgba(90, 167, 240, 0); }
}
.itc-closing--light { background: none; color: var(--color-ink); font-weight: 600; font-size: 22px; line-height: 1.4; margin-top: clamp(1.25rem, 2vw, 1.75rem); padding: 0; text-align: left; border-radius: 0; }
@media (max-width: 600px) {
    .itc-flow { grid-template-columns: 1fr; gap: 1.25rem; }
    .itc-closing--light { font-size: 21px; margin-top: 28px; }
}

/* -- operations: solid rust/orange band, 5-step row with connecting line and
   a travelling signal dot between each icon (paused for reduced-motion). */
.itc-operations { position: relative; background: #b54b18; color: #fff4e8; padding: var(--space-section) 0; isolation: isolate; }
.itc-operations::before { content: ""; position: absolute; inset: 0; background: radial-gradient(ellipse at 15% 20%, rgba(224, 93, 36, 0.13), transparent 65%); z-index: -1; }
.itc-operation-head { display: grid; grid-template-columns: 1.05fr 1fr; gap: 90px; align-items: start; }
.itc-operation-head h2 { font-size: var(--fs-h2); }
.itc-operation-head h2 em { color: #ffd19b; font-style: normal; }
.itc-operation-head p { color: #fff0e4; font-size: 17px; }
.itc-step-rows { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 30px; margin-top: 56px; position: relative; padding-bottom: 44px; }
.itc-step-rows::after { content: ""; position: absolute; left: 2%; right: 1%; bottom: 0; height: 30px; border: 1px solid #fce5cf; border-top: 0; border-radius: 0 0 24px 24px; opacity: 0.8; }
.itc-step-rows article { position: relative; }
.itc-step-rows article::before { content: ""; position: absolute; left: 35px; right: -20px; top: 85px; height: 1px; background: #f8dbc4; }
.itc-step-rows article:last-child::before { display: none; }
/* Arrowhead: a plain CSS triangle (no new asset), sat right where the line
   used to simply stop, so the line now reads as pointing at the next icon
   instead of trailing off. One real element (not a 3rd pseudo-element --
   ::before is the line, ::after is the bead below) only on the 4
   non-last articles; the template itself just omits it on the last one. */
.itc-step-arrow { position: absolute; left: calc(100% + 11px); top: 85px; transform: translateY(-50%); width: 0; height: 0; border-style: solid; border-width: 4px 0 4px 7px; border-color: transparent transparent transparent #f8dbc4; }
/* Bead: starts at the line's own left end (not partway along it) and
   travels the line's full responsive length via `left` percentages (so it
   scales with the article's own width instead of a fixed px distance),
   fading in just after it starts and fading out right as it reaches the
   arrow -- a one-way travel-then-vanish, not the old back-and-forth
   14px-only tween. */
.itc-step-rows article:not(:last-child)::after { content: ""; position: absolute; left: 35px; top: 85px; width: 6px; height: 6px; margin-top: -3px; border-radius: 50%; background: #ffdbac; opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
    .itc-step-rows article:not(:last-child)::after { animation: itc-process-signal 3.4s ease-in-out infinite; }
    .itc-step-rows article:nth-child(2)::after { animation-delay: 0.6s; }
    .itc-step-rows article:nth-child(3)::after { animation-delay: 1.2s; }
    .itc-step-rows article:nth-child(4)::after { animation-delay: 1.8s; }
}
@keyframes itc-process-signal {
    0%, 4% { left: 35px; opacity: 0; }
    12% { opacity: 1; }
    80% { opacity: 1; }
    92%, 100% { left: calc(100% + 8px); opacity: 0; }
}
.itc-process-icon { width: 65px; height: auto; transition: filter 0.3s; }
.itc-step-rows article:hover .itc-process-icon { filter: drop-shadow(0 0 6px rgba(247, 166, 83, 0.21)); }
.itc-operations h3 { font-size: var(--fs-h3); margin: 25px 0 15px; position: relative; padding-top: 24px; }
.itc-operations h3::before { content: ""; position: absolute; top: 0; left: 25px; width: 12px; height: 12px; border: 1.5px solid #fff0e3; border-radius: 50%; background: #b54b18; }
.itc-step-rows article:hover h3::before { box-shadow: 0 0 0 5px rgba(255, 241, 219, 0.13); }
.itc-operations p { color: #fff2e6; font-size: 15px; }
@media (min-width: 851px) {
    .itc-step-rows article { display: grid; grid-template-rows: 65px auto 1fr; align-content: start; }
}
@media (max-width: 1100px) {
    .itc-operation-head { gap: 45px; }
    .itc-step-rows { gap: 22px; }
    .itc-operations p { font-size: 14px; }
    .itc-operations h3 { font-size: var(--fs-h3); }
}
@media (max-width: 850px) {
    .itc-operation-head { gap: 35px; }
    .itc-step-rows { grid-template-columns: repeat(3, 1fr); gap: 32px; padding-bottom: 0; }
    .itc-step-rows article::before, .itc-step-rows article::after, .itc-step-arrow, .itc-step-rows::after { display: none; }
    .itc-operations h3 { padding-top: 10px; margin-top: 14px; }
    .itc-operations h3::before { display: none; }
}
@media (max-width: 600px) {
    .itc-operation-head { grid-template-columns: 1fr; gap: 25px; }
    .itc-operation-head p { font-size: 16px; }
    .itc-step-rows { grid-template-columns: 1fr; margin-top: 30px; gap: 0; padding-left: 22px; border-left: 1px solid rgba(255, 225, 203, 0.38); }
    .itc-step-rows article { padding: 26px 0; display: grid; grid-template-columns: 60px 1fr; gap: 0 20px; border-bottom: 1px solid rgba(255, 225, 203, 0.19); }
    .itc-process-icon { width: 55px; height: auto; grid-row: 1 / 3; }
    .itc-operations h3 { font-size: var(--fs-h3); margin: 0; padding: 0; }
    .itc-operations p { font-size: 16px; margin-top: 12px; }
}

/* -- cybersecurity: "work together, not the same" ---------------------------------
   Centred heading, then two different panels side by side -- a light Managed
   IT panel (blue icon) and a deep navy Cybersecurity panel (orange icon) --
   joined by one hub: the interlocking-rings image in a round medallion that
   overlaps both where they meet, floating gently with a soft pulsing ring.
   The closing note and the CTA share one rounded "bridge" bar underneath.
   Panels lift on hover. Motion is behind prefers-reduced-motion. */
.itc-cybersecurity {
    position: relative;
    padding-block: clamp(64px, 7vw, 100px);
    background: radial-gradient(ellipse 60% 70% at 50% 60%, rgba(255, 140, 60, 0.08), rgba(255, 140, 60, 0) 70%), #FBF8F4;
}
.itc-cyber-head { text-align: center; max-width: 820px; margin: 0 auto; }
.itc-cyber-head h2 { font-size: var(--fs-h2); line-height: 1.15; }
.itc-cyber-head h2 span { color: var(--color-accent); }

.itc-vs { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 90px minmax(0, 1fr); align-items: stretch; max-width: 1000px; margin: clamp(2.5rem, 5vw, 3.5rem) auto 0; }
.itc-vs__panel {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: clamp(24px, 2.6vw, 34px);
    border-radius: 20px;
    transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.itc-vs__panel--it {
    grid-column: 1;
    padding-right: clamp(56px, 5.5vw, 76px);
    /* a cool steel-blue tint (not plain white on cream), a firmer border, a
       blue top edge and a real shadow so the panel holds its own beside the
       navy one */
    background: linear-gradient(160deg, #F1F6FA 0%, #E6EEF5 100%);
    border: 1px solid #CBD8E4;
    box-shadow: inset 0 3px 0 #315B78, 0 28px 50px -30px rgba(9, 30, 48, 0.35);
}
.itc-vs__panel--sec {
    grid-column: 3;
    padding-left: clamp(56px, 5.5vw, 76px);
    color: #FFFFFF;
    background: radial-gradient(ellipse 70% 80% at 100% 0%, rgba(255, 101, 11, 0.2), rgba(255, 101, 11, 0) 60%), linear-gradient(160deg, var(--color-primary), var(--color-ink));
    box-shadow: 0 30px 60px -30px rgba(9, 30, 48, 0.6);
}
.itc-vs__icon { display: grid; place-items: center; width: 46px; height: 46px; margin-bottom: 18px; border-radius: 14px; }
.itc-vs__icon svg { width: 22px; height: 22px; }
.itc-vs__panel--it .itc-vs__icon { background: #FFFFFF; color: #315B78; border: 1px solid #CBD8E4; }
.itc-vs__panel--sec .itc-vs__icon { background: rgba(255, 101, 11, 0.15); color: #FF8A3D; border: 1px solid rgba(255, 138, 61, 0.35); }
.itc-vs__panel h3 { margin: 0 0 10px; font-size: 23px; line-height: 1.2; letter-spacing: -0.015em; }
.itc-vs__panel--it h3 { color: var(--color-ink); }
.itc-vs__panel--sec h3 { color: #FFFFFF; }
.itc-vs__panel p { margin: 0; font-size: 15px; line-height: 1.65; }
.itc-vs__panel--it p { color: #3E4D57; }
.itc-vs__panel--sec p { color: rgba(255, 255, 255, 0.75); }
@media (hover: hover) and (pointer: fine) {
    .itc-vs__panel:hover { transform: translateY(-4px); }
    .itc-vs__panel--it:hover { box-shadow: inset 0 3px 0 #315B78, 0 34px 60px -30px rgba(9, 30, 48, 0.42); }
}
/* the hub: the gear-and-shield cut-out (transparent webp) floating on the seam,
   overlapping both panels, with a soft drop shadow instead of a frame */
.itc-vs__hub {
    position: absolute;
    left: 50%;
    top: 50%;
    z-index: 2;
    width: clamp(96px, 9vw, 128px);
    translate: -50% -50%;
    filter: drop-shadow(0 16px 18px rgba(9, 30, 48, 0.35));
}
.itc-vs__hub img { width: 100%; height: auto; display: block; }

.itc-vs__bridge {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px 40px;
    max-width: 1000px;
    margin: 28px auto 0;
    padding: 22px 22px 22px 30px;
    border-radius: 18px;
    background: #FFFFFF;
    border: 1px solid #E7E1D8;
    border-left: 4px solid var(--color-accent);
}
.itc-vs__bridge p { margin: 0; max-width: 46rem; font-size: 16px; line-height: 1.6; color: var(--color-ink); }
.itc-vs__bridge .itc-btn { flex: none; margin: 0; }

@media (prefers-reduced-motion: no-preference) {
    .itc-vs__hub { animation: itc-vs-float 7s ease-in-out infinite; }
}
@keyframes itc-vs-float { 0%, 100% { translate: -50% -50%; } 50% { translate: -50% calc(-50% - 8px); } }
@keyframes itc-vs-float-s { 0%, 100% { translate: 0 0; } 50% { translate: 0 -6px; } }

/* stacked: panels one above the other, the hub between them */
@media (max-width: 850px) {
    .itc-vs { grid-template-columns: 1fr; grid-template-rows: auto 70px auto; }
    .itc-vs__panel--it { grid-column: 1; grid-row: 1; padding-right: clamp(28px, 3.5vw, 44px); padding-bottom: 80px; }
    .itc-vs__panel--sec { grid-column: 1; grid-row: 3; padding-left: clamp(28px, 3.5vw, 44px); padding-top: 80px; }
    .itc-vs__hub { position: relative; grid-column: 1; grid-row: 2; left: auto; top: auto; translate: none; justify-self: center; align-self: center; width: 104px; margin: -60px 0; animation-name: itc-vs-float-s; }
    .itc-vs__bridge { flex-direction: column; align-items: flex-start; }
}
@media (max-width: 600px) {
    .itc-cyber-head { text-align: left; }
    .itc-vs__panel h3 { font-size: 22px; }
    .itc-vs__panel p { font-size: 15px; }
    .itc-vs__bridge { padding: 20px; }
    .itc-vs__bridge .itc-btn { width: 100%; justify-content: center; }
}

/* -- automation: dark navy band, lead image + copy, then 3 icon rows with a
   travelling signal dot along the connecting line. */
.itc-automation { background: #062536; color: #f9f8f3; padding-block: clamp(56px, 6vw, 84px); }
.itc-automation h2 { font-size: var(--fs-h2); margin-bottom: 32px; }
.itc-automation-lead { display: grid; grid-template-columns: 1fr 1fr; gap: 75px; align-items: center; }
.itc-automation-art img { width: 100%; height: auto; display: block; }
.itc-automation-lead p { color: #cbd9e1; font-size: 17px; line-height: 1.7; }
.itc-automation-lead p + p { margin-top: 28px; }
.itc-auto-rows { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 65px; margin-top: 40px; }
/* 64px tall icons; lighten blends their baked-in dark tile into the band's navy. */
.itc-auto-icon { display: block; width: auto; height: 64px; margin-bottom: 22px; mix-blend-mode: lighten; transition: filter 0.3s; }
.itc-auto-rows article:hover .itc-auto-icon { filter: drop-shadow(0 0 6px rgba(247, 166, 83, 0.21)); }
.itc-auto-rows h3 { margin: 0 0 10px; font-size: 22px; line-height: 1.25; letter-spacing: -0.01em; }
.itc-auto-rows p { margin: 0; color: #cbd9e1; max-width: 300px; font-size: 15px; line-height: 1.65; }
.itc-auto-rows article { position: relative; }
.itc-auto-rows article:not(:last-child)::after { content: ""; position: absolute; left: 96px; right: -22px; top: 32px; height: 1px; background: rgba(126, 147, 156, 0.44); }
/* Bead travels the line's full responsive length (left: 105px -> just
   short of the line's own end, a `calc(100% + Npx)` matching the line's
   own `right:-22px`) and fades out right as it arrives instead of the old
   16px-only back-and-forth tween -- same technique as the Operations
   timeline above (site.css:4741), reused here rather than re-invented. */
.itc-auto-rows article:not(:last-child)::before {
    --bead-start: 96px;
    --bead-end: calc(100% + 10px);
    content: ""; position: absolute; left: var(--bead-start); top: 32px; margin-top: -3px; width: 6px; height: 6px; background: var(--color-accent); border-radius: 50%; box-shadow: 0 0 9px rgba(255, 135, 39, 0.33); opacity: 0;
}
@media (prefers-reduced-motion: no-preference) {
    .itc-auto-rows article:not(:last-child)::before { animation: itc-path-signal 3.6s ease-in-out infinite; }
    .itc-auto-rows article:nth-child(2)::before { animation-delay: 0.9s; }
}
@keyframes itc-path-signal {
    0%, 4% { left: var(--bead-start); opacity: 0; }
    12% { opacity: 1; }
    80% { opacity: 1; }
    92%, 100% { left: var(--bead-end); opacity: 0; }
}
.itc-closing--dark { background: none; color: #f3f6f7; border-top: 1px solid rgba(174, 193, 202, 0.25); padding: 29px 0 0; margin-top: 44px; font-size: 23px; font-weight: 600; line-height: 1.45; text-align: left; border-radius: 0; }
/* -- automation: closing statement ("Technology can assist the process. People
   remain responsible for the decisions.") as a feature panel: an orange-ringed
   person-with-check icon (soft pulse), the first line in soft white, the second
   large and bold with an orange underline that draws in when the panel is
   revealed, and an orange accent edge that grows down the panel's left side. */
.itc-pledge {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    gap: 28px;
    margin-top: 44px;
    padding: 32px 40px;
    border-radius: 22px;
    overflow: hidden;
    background: linear-gradient(115deg, rgba(255, 101, 11, 0.16) 0%, rgba(255, 255, 255, 0.05) 45%, rgba(255, 255, 255, 0.02) 100%);
    border: 1px solid rgba(255, 255, 255, 0.12);
}
.itc-pledge::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: linear-gradient(180deg, var(--color-accent), #FFB066); transform-origin: top; }
.itc-pledge__icon { position: relative; display: grid; place-items: center; width: 68px; height: 68px; border-radius: 50%; color: #FF8A3D; background: rgba(255, 101, 11, 0.12); border: 1.5px solid rgba(255, 138, 61, 0.6); }
.itc-pledge__icon svg { width: 30px; height: 30px; }
.itc-pledge__text { margin: 0; }
.itc-pledge__text span { display: block; margin-bottom: 6px; font-size: 19px; font-weight: 500; line-height: 1.4; color: rgba(255, 255, 255, 0.7); }
.itc-pledge__text strong {
    font-size: clamp(24px, 2.4vw, 32px);
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -0.015em;
    color: #FFFFFF;
    background: linear-gradient(var(--color-accent), var(--color-accent)) 0 100% / 100% 3px no-repeat;
    padding-bottom: 4px;
}
@media (prefers-reduced-motion: no-preference) {
    .itc-pledge::before { transform: scaleY(0); transition: transform 0.8s var(--ease) 0.2s; }
    .itc-pledge.is-visible::before { transform: scaleY(1); }
    .itc-pledge__text span { opacity: 0; transform: translateX(-12px); transition: opacity 0.6s var(--ease) 0.25s, transform 0.6s var(--ease) 0.25s; }
    .itc-pledge__text strong { background-size: 0% 3px; transition: background-size 1.1s var(--ease) 0.7s; }
    .itc-pledge.is-visible .itc-pledge__text span { opacity: 1; transform: none; }
    .itc-pledge.is-visible .itc-pledge__text strong { background-size: 100% 3px; }
    .itc-pledge__icon::after { content: ""; position: absolute; inset: -6px; border-radius: 50%; border: 1.5px solid rgba(255, 138, 61, 0.55); animation: itc-pledge-pulse 3s ease-out infinite; }
}
@keyframes itc-pledge-pulse { 0% { opacity: 0.8; scale: 1; } 70%, 100% { opacity: 0; scale: 1.3; } }
@media (max-width: 600px) {
    .itc-pledge { grid-template-columns: 1fr; gap: 18px; padding: 26px 24px; }
    .itc-pledge__icon { width: 56px; height: 56px; }
    .itc-pledge__text span { font-size: 17px; }
}
@media (min-width: 601px) {
    .itc-auto-rows article { display: grid; grid-template-rows: 86px auto 1fr; align-content: start; }
}
@media (max-width: 1100px) {
    .itc-automation-lead { gap: 40px; }
    .itc-auto-rows { gap: 40px; }
}
@media (max-width: 850px) {
    .itc-automation-lead { gap: 25px; }
    .itc-automation-lead p { font-size: 16px; }
    .itc-auto-rows { gap: 30px; }
    .itc-auto-rows article:not(:last-child)::after { left: 85px; right: -5px; }
    .itc-auto-rows article:not(:last-child)::before { --bead-start: 85px; --bead-end: calc(100% + 5px); }
    .itc-auto-rows p { font-size: 15px; }
}
@media (max-width: 600px) {
    .itc-automation h2 { font-size: var(--fs-h2); margin-bottom: 28px; }
    .itc-automation-lead { grid-template-columns: 1fr; gap: 25px; }
    .itc-auto-rows { grid-template-columns: 1fr; gap: 30px; margin-top: 35px; }
    .itc-auto-rows article { display: grid; grid-template-columns: 65px 1fr; gap: 0 19px; }
    .itc-auto-icon { width: 59px; height: auto; grid-row: 1 / 3; margin: 0; }
    .itc-auto-rows article:not(:last-child)::after, .itc-auto-rows article:not(:last-child)::before { display: none; }
    .itc-auto-rows h3 { margin: 6px 0 8px; font-size: 20px; }
    .itc-auto-rows p { font-size: 15px; }
    .itc-closing--dark { font-size: 20px; margin-top: 35px; }
}

/* -- approach: lead copy, diagram + a numbered 3-step list (counter-based
   "01/02/03", not a literal span, matching the reference exactly). */
.itc-approach { padding-block: var(--space-section); }
.itc-approach > .container > .lead { margin-top: 24px; max-width: 960px; font-size: 17px; }
.itc-approach-grid { display: grid; grid-template-columns: 0.78fr 1.1fr; gap: 100px; margin-top: 50px; align-items: center; }
.itc-approach-art { width: 100%; max-width: 425px; }
.itc-approach-art img { width: 100%; height: auto; display: block; }
.itc-step-list { counter-reset: itc-step; }
.itc-step-list article { position: relative; padding: 25px 0 28px 68px; border-bottom: 1px solid var(--color-border); counter-increment: itc-step; }
.itc-step-list article:last-child { border-bottom: 0; }
.itc-step-list article::before { content: "0" counter(itc-step); position: absolute; left: 0; top: 25px; font-size: 22px; font-weight: 600; color: var(--color-accent); }
.itc-step-list article p { margin-top: 18px; }
@media (max-width: 1100px) {
    .itc-approach-grid { gap: 50px; }
}
@media (max-width: 850px) {
    .itc-approach-grid { gap: 25px; }
    .itc-step-list article { padding-left: 42px; }
    .itc-step-list article h3 { font-size: var(--fs-h3); }
}
@media (max-width: 600px) {
    .itc-approach > .container > .lead { font-size: 16px; }
    .itc-approach-grid { grid-template-columns: 1fr; gap: 25px; margin-top: 30px; }
    .itc-approach-art { width: 90%; margin: auto; max-width: 350px; }
    .itc-step-list article { padding: 24px 0 25px 44px; }
    .itc-step-list article p { margin-top: 14px; }
}

/* -- enquiry: dark navy band with two glowing orange halo shapes, copy left,
   dark-themed form card right (own field/select/textarea skin, not the
   light Bootstrap one used by the Data Marketing page's form). */
/* Background treatment reused from the Web-Development page's own enquiry
   section (body.service-page .cta-band--contact, site.css:2665) -- a solid
   navy band plus its shared `.svc-contact__ribbon` element (a real div in
   the template, not a page-specific pseudo-element) rather than this
   page's own previous pair of orange ::before/::after blobs, which would
   otherwise sit underneath and show through as a second, conflicting
   background. `overflow:hidden` added so the ribbon (taller than the
   section) clips the same way it does there. */
.itc-enquiry { position: relative; overflow: hidden; background: #082635; color: #fff; padding: var(--space-section-sm) 0; isolation: isolate; }
/* position:relative lifts the grid (and so the form) above the section's orange ribbon, exactly as .svc-contact__grid does on the Web-Development enquiry; without it the ribbon painted over the right half of the form. */
.itc-contact-grid { position: relative; display: grid; grid-template-columns: 0.95fr 1.05fr; gap: 70px; align-items: start; }
.itc-contact-copy { padding-top: 20px; }
.itc-contact-copy h2 { font-size: var(--fs-h2); }
.itc-contact-copy > p { color: #d0dfe7; margin-top: 28px; font-size: 17px; max-width: 530px; }
.itc-contact-copy > .btn { margin-top: 32px; }
.itc-contact-details { display: grid; gap: 12px; border-top: 1px solid rgba(184, 200, 208, 0.23); margin-top: 34px; padding-top: 24px; max-width: 345px; font-size: 14px; }
.itc-contact-details a { color: inherit; }
.itc-contact-details p { color: #b5c9d5; margin: 0; }
/* Form surface = the Web-Development enquiry form (body.service-page .cta-band--contact .cta-band__form), value for value. */
.itc-enquiry-form {
    background: rgba(8, 35, 55, 0.86);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(175, 121, 85, 0.34);
    border-radius: 15px;
    padding: 27px;
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.07);
}
.itc-contact-form__title { font-size: 24px; margin: 0 0 26px; color: #fff; }
.itc-contact-form .row { --bs-gutter-x: 20px; --bs-gutter-y: 19px; }
.itc-contact-form .form-label { font-size: 14px; line-height: 1.4; margin-bottom: 9px; color: #d6e1e8; font-weight: 400; }
.itc-required { color: var(--color-accent); }
.itc-contact-form .form-control,
.itc-contact-form .form-select,
.itc-contact-form textarea.form-control {
    width: 100%;
    background: rgba(14, 42, 58, 0.79);
    border: 1px solid #4d6575;
    border-radius: 4px;
    color: #fff;
    font-size: 14px;
    padding: 12px;
    min-height: 43px;
}
.itc-contact-form .form-control::placeholder { color: #98afbf; opacity: 1; }
.itc-contact-form .form-select { color: #d1dce3; }
.itc-contact-form textarea.form-control { min-height: 91px; resize: vertical; line-height: 1.5; }
.itc-contact-form .form-control:focus,
.itc-contact-form .form-select:focus { background: rgba(14, 42, 58, 0.95); border-color: var(--color-accent); color: #fff; box-shadow: 0 0 0 0.2rem rgba(255, 101, 11, 0.25); }
/* .itc-submit carries plain Bootstrap .btn (for its base padding/transition
   vars) but not .btn-primary, so Bootstrap's own .btn:hover and :active
   rules (which read the --bs-btn-hover-* and --bs-btn-active-* custom
   properties for background-color, border-color and color) were resolving
   against undefined custom properties -- an invalid var() with no
   fallback, which drops background-color/border-color to their initial
   value (transparent) on hover, letting this dark section's own backdrop
   show through the button (it reads as turning blue). Declaring them here
   keeps hover/active at the same resting orange instead. */
.itc-submit {
    --bs-btn-hover-bg: var(--color-accent);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-hover-color: #fff;
    --bs-btn-active-bg: var(--color-accent);
    --bs-btn-active-border-color: transparent;
    --bs-btn-active-color: #fff;
    border: 0;
    border-radius: 40px;
    background: var(--color-accent);
    color: #fff;
    font-weight: 600;
    padding: 15px 25px;
    font-size: 14px;
    min-width: 200px;
    min-height: 50px;
    transition: box-shadow 0.2s, transform 0.2s;
}
/* Same lift + glow as .btn-primary:hover (site.css:144, e.g. this page's
   own "Discuss Your IT Environment" hero button) -- identical values, and
   gated behind the same hover:hover+pointer:fine guard so tapping it on
   touch doesn't leave it stuck "lifted". */
@media (hover: hover) and (pointer: fine) {
    .itc-submit:hover { box-shadow: 0 10px 22px -4px rgba(255, 101, 11, 0.55); transform: translateY(-2px); color: #fff; }
}
@media (max-width: 1100px) {
    .itc-contact-grid { gap: 40px; }
    .itc-enquiry-form { padding: 26px; }
    .itc-contact-copy > p { font-size: 16px; }
}
@media (max-width: 850px) {
    .itc-contact-grid { grid-template-columns: 1fr; gap: 45px; }
    .itc-contact-copy { max-width: 680px; padding-top: 0; }
    .itc-enquiry-form { padding: 30px; }
}
@media (max-width: 600px) {
    .itc-contact-copy h2 { font-size: var(--fs-h2); }
    .itc-contact-copy > p { font-size: 16px; }
    .itc-contact-grid { gap: 35px; }
    .itc-contact-details { margin-top: 28px; }
    .itc-enquiry-form { padding: 24px 20px; }
    .itc-contact-form .form-control,
    .itc-contact-form .form-select,
    .itc-contact-form textarea.form-control { font-size: 16px; min-height: 51px; }
    .itc-contact-form .form-label { font-size: 14px; }
    .itc-contact-form__title { font-size: 28px; }
    .itc-submit { width: 100%; padding: 16px 12px; }
}

/* -- faq: title column + a plain native <details>/<summary> accordion (no
   numbered badges -- unlike this page's `.svc-faq-item` elsewhere on the
   site, the reference's own FAQ for this page has none, so this is a new,
   simpler scoped treatment rather than reusing that shared component). */
/* Dark circuit-board backdrop (faq.webp) drawn edge to edge. The section
   paints the image; the `.itc-faq__fx` SVG overlays it with the slow light
   traces/pulses and shares its 1672x941 box and cover/centre crop. */
.itc-faq {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding-block: var(--space-section);
    color: #fff;
    background-color: #050b16;
    background-image: url("../img/services/managed-it-cloud/faq.bd24b4d46c86.webp");
    background-repeat: no-repeat;
    background-size: cover;
    background-position: center;
}
.itc-faq > .container { position: relative; z-index: 1; }
.itc-faq__fx { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
.itc-faq__trace { fill: none; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; opacity: 0; }
.itc-faq__trace--o1, .itc-faq__trace--o2, .itc-faq__trace--o3 { stroke: #ffb066; }
.itc-faq__trace--c1, .itc-faq__trace--c2, .itc-faq__trace--c3 { stroke: #7fe6ff; }
.itc-faq__traces { filter: drop-shadow(0 0 3px rgba(120, 220, 255, 0.55)); }
.itc-faq__l1 { display: none; }
.itc-faq__node { opacity: 0; transform-box: fill-box; transform-origin: center; }
.itc-faq__node--c { fill: #4fd8ff; }
.itc-faq__node--o { fill: #ff8a26; }
@media (prefers-reduced-motion: no-preference) {
    .itc-faq__trace { stroke-dasharray: 16 984; stroke-dashoffset: 16; animation: itc-faq-trace 11s linear infinite; }
    .itc-faq__trace--o1 { animation-delay: 1.4s; }
    .itc-faq__trace--o2 { animation-delay: 4.2s; animation-duration: 13s; }
    .itc-faq__trace--o3 { animation-delay: 2.8s; animation-duration: 10s; }
    .itc-faq__trace--c1 { animation-delay: 1.5s; animation-duration: 12s; }
    .itc-faq__trace--c2 { animation-delay: 5s; animation-duration: 8s; }
    .itc-faq__trace--c3 { animation-delay: 8s; animation-duration: 14s; }
    .itc-faq__node { animation: itc-faq-pulse 6s ease-out infinite; }
    .itc-faq__node:nth-child(2) { animation-delay: 1.4s; animation-duration: 7s; }
    .itc-faq__node:nth-child(3) { animation-delay: 3.1s; animation-duration: 8s; }
    .itc-faq__node:nth-child(4) { animation-delay: 4.6s; }
    .itc-faq__node:nth-child(5) { animation-delay: 2.2s; animation-duration: 7.5s; }
    .itc-faq__node:nth-child(6) { animation-delay: 5.3s; }
    .itc-faq__node:nth-child(7) { animation-delay: 0.7s; animation-duration: 9s; }
    .itc-faq__node:nth-child(8) { animation-delay: 3.8s; animation-duration: 8.5s; }
    /* Connection-point pulses: negative delays put each first peak where its line arrives. */
    .itc-faq__node--j1, .itc-faq__node--j2, .itc-faq__node--j3 { animation-duration: 8s; }
    .itc-faq__node--j1 { animation-delay: -4.5s; }
    .itc-faq__node--j2 { animation-delay: -4.4s; }
    .itc-faq__node--j3 { animation-delay: -4.3s; }
    /* Line-drawing formation: armed (hold everything back) by JS, released
       once by IntersectionObserver (.is-formed). Without JS or under reduced
       motion none of this applies and the image shows as-is. */
    .itc-faq.is-armed:not(.is-formed) .itc-faq__trace,
    .itc-faq.is-armed:not(.is-formed) .itc-faq__node { animation-play-state: paused; }
    .itc-faq.is-armed .itc-faq__l1 { display: inline; }
    .itc-faq__hole { fill: none; stroke: #000; stroke-width: 16; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1000 1000; stroke-dashoffset: 1000; }
    .itc-faq__draw, .itc-faq__head { fill: none; stroke-linecap: round; stroke-linejoin: round; opacity: 0; }
    .itc-faq__draw { stroke: #ff8a26; stroke-width: 2.6; stroke-dasharray: 1000 1000; stroke-dashoffset: 1000; }
    .itc-faq__head { stroke: #ffd9b0; stroke-width: 4; stroke-dasharray: 10 1000; stroke-dashoffset: 10; }
    .itc-faq__draws { filter: drop-shadow(0 0 4px rgba(255, 138, 38, 0.85)); }
    .itc-faq__heads { filter: drop-shadow(0 0 5px rgba(255, 170, 90, 0.95)); }
    .itc-faq.is-formed .itc-faq__hole { animation: itc-faq-hole var(--d, 2.6s) cubic-bezier(0.45, 0, 0.25, 1) var(--s, 0s) forwards; }
    .itc-faq.is-formed .itc-faq__draw { animation: itc-faq-draw var(--d, 2.6s) cubic-bezier(0.45, 0, 0.25, 1) var(--s, 0s) forwards; }
    .itc-faq.is-formed .itc-faq__head { animation: itc-faq-head var(--d, 2.6s) cubic-bezier(0.45, 0, 0.25, 1) var(--s, 0s) forwards; }
    .itc-faq__hole--o1, .itc-faq__draw--o1, .itc-faq__head--o1 { --d: 1.3s; --s: 0.05s; }
    .itc-faq__hole--o2, .itc-faq__draw--o2, .itc-faq__head--o2 { --d: 1.2s; --s: 0.3s; }
    .itc-faq__hole--o3, .itc-faq__draw--o3, .itc-faq__head--o3 { --d: 1s; --s: 0.5s; }
    .itc-faq.is-formed .itc-faq__l1 { animation: itc-faq-unveil 0.8s ease-in-out 1.3s forwards; }
}
@keyframes itc-faq-hole { 0% { stroke-dashoffset: 1000; } 78%, 100% { stroke-dashoffset: 0; } }
@keyframes itc-faq-draw {
    0% { stroke-dashoffset: 1000; opacity: 1; }
    78% { stroke-dashoffset: 0; opacity: 1; }
    100% { stroke-dashoffset: 0; opacity: 0.28; }
}
@keyframes itc-faq-head {
    0% { stroke-dashoffset: 10; opacity: 1; }
    78% { stroke-dashoffset: -990; opacity: 1; }
    100% { stroke-dashoffset: -990; opacity: 0; }
}
@keyframes itc-faq-unveil { to { opacity: 0; } }
@keyframes itc-faq-trace {
    0% { stroke-dashoffset: 16; opacity: 0; }
    6% { opacity: 0.85; }
    40% { stroke-dashoffset: -1000; opacity: 0.85; }
    46%, 100% { stroke-dashoffset: -1000; opacity: 0; }
}
@keyframes itc-faq-pulse {
    0%, 55%, 100% { opacity: 0; transform: scale(1); }
    70% { opacity: 0.5; transform: scale(2.6); }
    85% { opacity: 0; transform: scale(3.4); }
}
/* Heading column: heading, a short lead and a contact link, its top
   lined up with the first card. */
.itc-faq-grid { --itc-faq-gap: 80px; display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.5fr); gap: var(--itc-faq-gap); align-items: start; }
.itc-faq-title { padding-top: 6px; }
.itc-faq-title h2 { margin: 0; color: #fff; font-size: clamp(34px, 3.4vw, 48px); font-weight: 700; letter-spacing: -0.025em; line-height: 1.1; }
.itc-faq-title h2 span { color: var(--color-accent); }
.itc-faq-title__lead { margin: 18px 0 0; max-width: 22rem; font-size: 16px; line-height: 1.6; color: rgba(255, 255, 255, 0.7); }
.itc-faq-title__ask { display: inline-flex; align-items: center; gap: 6px; margin-top: 26px; padding-top: 18px; border-top: 1px solid rgba(255, 255, 255, 0.14); font-size: 15px; color: rgba(255, 255, 255, 0.72); text-decoration: none; }
.itc-faq-title__ask span { color: #FF8A3D; font-weight: 600; transition: transform 0.25s var(--ease); }
.itc-faq-title__ask:hover span:last-child { transform: translateX(4px); }
/* Cards: dark glass (darker than before so the circuit art behind stays
   texture, not noise), a numbered chip, and a plus that turns into a minus. */
.itc-faq-item { background: rgba(7, 15, 25, 0.84); border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 14px; margin-bottom: 10px; -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); transition: background-color 0.25s var(--ease), border-color 0.25s var(--ease); }
.itc-faq-item:last-child { margin-bottom: 0; }
.itc-faq-item:hover { border-color: rgba(255, 255, 255, 0.24); }
.itc-faq-item[open] { background: rgba(10, 20, 32, 0.9); border-color: rgba(255, 138, 38, 0.55); box-shadow: inset 3px 0 0 var(--color-accent); }
.itc-faq-item summary { display: flex; align-items: center; gap: 16px; padding: 18px 56px 18px 18px; font-size: 17px; font-weight: 500; line-height: 1.4; color: #fff; list-style: none; position: relative; cursor: pointer; }
.itc-faq-item summary::-webkit-details-marker { display: none; }
.itc-faq-item__no { flex: none; display: grid; place-items: center; width: 36px; height: 36px; border-radius: 10px; border: 1px solid rgba(255, 138, 61, 0.35); background: rgba(255, 101, 11, 0.1); color: #FF8A3D; font-size: 13px; font-weight: 600; letter-spacing: 0.04em; transition: background-color 0.25s var(--ease), color 0.25s var(--ease); }
.itc-faq-item[open] .itc-faq-item__no { background: var(--color-accent); border-color: var(--color-accent); color: #fff; }
/* Plus/minus icon built from two small bars (summary's own ::before/::after)
   so it can rotate smoothly into a minus. */
.itc-faq-item summary::before,
.itc-faq-item summary::after {
    content: "";
    position: absolute;
    right: 22px;
    background: var(--color-accent);
    transition: transform 0.3s var(--ease);
}
.itc-faq-item summary::before { top: calc(50% - 7px); right: 28px; width: 2px; height: 14px; }
.itc-faq-item summary::after { top: calc(50% - 1px); width: 14px; height: 2px; }
.itc-faq-item[open] summary::before { transform: rotate(90deg); }
.itc-faq-item p { padding: 0 24px 22px 70px; line-height: 1.65; font-size: 15px; margin: 0; color: rgba(255, 255, 255, 0.74); }
@media (prefers-reduced-motion: reduce) {
    .itc-faq-item summary::before, .itc-faq-item summary::after { transition: none; }
}
@media (max-width: 1100px) {
    .itc-faq-grid { --itc-faq-gap: 48px; }
}
@media (max-width: 900px) {
    .itc-faq-grid { --itc-faq-gap: 28px; grid-template-columns: 1fr; }
    .itc-faq-title__lead { max-width: 34rem; }
}
@media (max-width: 600px) {
    .itc-faq-item summary { gap: 12px; font-size: 16px; padding: 15px 48px 15px 14px; }
    .itc-faq-item__no { width: 32px; height: 32px; font-size: 12px; }
    .itc-faq-item summary::after { right: 16px; }
    .itc-faq-item summary::before { right: 22px; }
    .itc-faq-item p { padding: 0 16px 18px; font-size: 15px; }
}

/* ============================================================================
   CYBERSECURITY (#services/cybersecurity/) -- a brand new page built from
   reference/Valin-Services-Cybersecurity.html, a self-contained static
   export (same format as the Managed IT & Cloud reference). Colour tokens
   are this reference's own literal values (navy #071e2f, deep #031723,
   orange #ff6907 -- close to but not identical to this project's existing
   var(--color-accent) #ff650b, kept separate/scoped rather than merged so
   this page matches its own source exactly), scoped entirely to `.cs-*`.
   Breakpoints (1100/800/480) are this reference's own.

   Two of its sections (approach, enquiry) are implemented in the reference
   as a single baked "exact" image with real form/accessible text layered on
   top via absolute positioning over one wide photo -- same technique as
   the Managed IT & Cloud reference's art, just a different compositing
   method (explicit pixel `data-crop` + a `fitOriginal()` cover-fit script,
   vs that reference's oversized-%-image hack). Reused this project's
   established counter-approach instead of the reference's own positioning
   mechanics: real HTML headings/paragraphs (this reference's own img `alt`
   text was the source for the copy, confirming it's unchanged from the
   live DOM) + small pre-cropped .webp art, with the approach section's own
   connecting-line SVG path data and aura/flow animation reused verbatim
   (it's already pure vector markup in the reference, nothing to re-derive).
   The reference's own live DOM has no kicker-dash element on any of this
   page's section intros (confirmed against its CSS -- no `h2:before` /
   `.intro:before` rule exists anywhere in its stylesheet) even though its
   baked mockup images show one as a design illustration; followed the
   live CSS/DOM as authoritative and omitted it here too, rather than the
   screenshot-only decoration. */

.cs-btn { color: #09202d; }
.cs-kicker { display: block; width: 44px; height: 3px; background: #ff6907; margin-bottom: 1rem; border-radius: 2px; }

/* -- hero: full-bleed photo bg (bleeds from the right, dark gradient wash
   fading to solid navy on the left where the text sits), matching the
   reference's own `.hero`/`.hero-photo`/`.hero:before` exactly. */
.cs-hero { position: relative; isolation: isolate; overflow: hidden; min-height: 33.75rem; display: flex; align-items: center; background: #041924; color: #fff; }
.cs-hero__media { position: absolute; inset: 0 0 0 auto; z-index: -2; width: 58%; height: 100%; }
.cs-hero__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cs-hero::before { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(90deg, #041924 0%, #041924 38%, rgba(4, 25, 36, 0.93) 45%, rgba(4, 25, 36, 0.47) 57%, transparent 75%); }
.cs-hero__copy { position: relative; z-index: 2; padding-block: 5.625rem; max-width: 43.75rem; }
.cs-hero h1 { font-size: var(--fs-h1); font-weight: 400; line-height: 1.13; letter-spacing: -0.035em; }
.cs-hero .btn { margin-top: 2rem; }
@media (prefers-reduced-motion: no-preference) {
    .cs-hero .btn { animation: cs-rise-soft 1s 0.35s var(--ease) both; }
}
@keyframes cs-rise-soft { from { transform: translateY(22px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@media (max-width: 1100px) { .cs-hero__media { width: 55%; } }
@media (max-width: 800px) { .cs-hero { min-height: 31.25rem; } .cs-hero h1 { max-width: 37.5rem; } }
@media (max-width: 480px) {
    .cs-hero { min-height: 28.75rem; }
    .cs-hero__copy { padding-block: 4.375rem; }
    .cs-hero h1 { font-size: var(--fs-h1); max-width: 22.2rem; line-height: 1.18; }
    .cs-hero__media { width: 85%; right: -15%; opacity: 0.5; }
    .cs-hero::before { background: linear-gradient(90deg, #041924 0%, rgba(4, 25, 36, 0.88) 30%, rgba(4, 25, 36, 0.21) 70%); }
}

/* -- cybersecurity: service console --------------------------------------------------
   Intro, then one navy "security console" panel: the four services as a list
   on the left (number, icon, title; the active one expands to show its text
   and an orange progress bar), and on the right a framed screen showing the
   active service's photo with scanner overlays -- corner brackets, a sweeping
   scan line and an 01 / 04 status chip. app.js ("cyber console") switches
   services on click / Enter and auto-advances when the progress bar finishes;
   the bar only runs while the console is in view and not hovered. */
.cs-services { background: linear-gradient(#fff, #fbfaf7); }
.cs-intro { margin-bottom: 2.375rem; }
.cs-intro .lead { max-width: 44.375rem; margin-top: 1.125rem; font-size: 1.0625rem; color: #627586; }

.cs-console {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    gap: clamp(1.5rem, 3vw, 2.5rem);
    padding: clamp(1.25rem, 2.5vw, 2rem);
    border-radius: 28px;
    overflow: hidden;
    background: radial-gradient(ellipse 60% 80% at 100% 0%, rgba(255, 101, 11, 0.16), rgba(255, 101, 11, 0) 60%), linear-gradient(160deg, var(--color-primary), var(--color-ink));
    box-shadow: 0 40px 80px -40px rgba(9, 30, 48, 0.6);
}
.cs-console::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px), linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
    background-size: 36px 36px;
    -webkit-mask-image: radial-gradient(ellipse 70% 80% at 25% 50%, #000, transparent 75%);
    mask-image: radial-gradient(ellipse 70% 80% at 25% 50%, #000, transparent 75%);
}
.cs-console__list { position: relative; display: flex; flex-direction: column; justify-content: center; }
.cs-console__item {
    position: relative;
    display: grid;
    grid-template-columns: 30px 44px minmax(0, 1fr);
    column-gap: 16px;
    align-items: start;
    padding: 20px 18px 20px 14px;
    border-radius: 16px;
    color: #FFFFFF;
    cursor: pointer;
    outline: none;
    transition: background-color 0.35s var(--ease);
}
.cs-console__item + .cs-console__item { margin-top: 4px; }
.cs-console__item:hover { background: rgba(255, 255, 255, 0.04); }
.cs-console__item.is-active { background: rgba(255, 255, 255, 0.07); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1); }
.cs-console__item:focus-visible { box-shadow: inset 0 0 0 2px var(--color-accent); }
.cs-console__no { padding-top: 12px; font-size: 13px; font-weight: 700; letter-spacing: 0.06em; color: rgba(255, 255, 255, 0.35); transition: color 0.35s; }
.cs-console__item.is-active .cs-console__no { color: var(--color-accent); }
.cs-console__icon { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 13px; background: rgba(255, 255, 255, 0.06); color: rgba(255, 255, 255, 0.7); border: 1px solid rgba(255, 255, 255, 0.1); transition: background-color 0.35s, color 0.35s, border-color 0.35s; }
.cs-console__icon svg { width: 21px; height: 21px; }
.cs-console__item.is-active .cs-console__icon { background: var(--color-accent); color: #FFFFFF; border-color: var(--color-accent); box-shadow: 0 8px 20px -8px rgba(255, 101, 11, 0.8); }
.cs-console__body h3 { margin: 10px 0 0; font-size: 19px; line-height: 1.3; letter-spacing: -0.01em; color: rgba(255, 255, 255, 0.72); transition: color 0.35s; }
.cs-console__item.is-active .cs-console__body h3 { color: #FFFFFF; }
/* description collapses to 0 height except on the active item */
.cs-console__more { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.45s var(--ease); }
.cs-console__more > p { overflow: hidden; margin: 0; font-size: 14.5px; line-height: 1.6; color: rgba(255, 255, 255, 0.68); }
.cs-console__item.is-active .cs-console__more { grid-template-rows: 1fr; }
.cs-console__item.is-active .cs-console__more > p { padding-top: 8px; }
.cs-console__progress { position: absolute; left: 18px; right: 18px; bottom: 0; height: 2px; border-radius: 2px; background: var(--color-accent); transform: scaleX(0); transform-origin: left; opacity: 0; }

.cs-console__screen { position: relative; display: flex; align-items: stretch; }
.cs-console__frame { position: relative; width: 100%; min-height: 420px; border-radius: 20px; overflow: hidden; background: #071521; border: 1px solid rgba(255, 255, 255, 0.12); }
.cs-console__shot { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transform: scale(1.06); transition: opacity 0.7s var(--ease), transform 1.2s var(--ease); }
.cs-console__shot.is-active { opacity: 1; transform: none; }
.cs-console__frame::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: linear-gradient(180deg, rgba(7, 21, 33, 0) 55%, rgba(7, 21, 33, 0.55)); }
.cs-console__corner { position: absolute; z-index: 2; width: 26px; height: 26px; border: 2px solid var(--color-accent); pointer-events: none; }
.cs-console__corner--tl { top: 16px; left: 16px; border-right: 0; border-bottom: 0; border-radius: 6px 0 0 0; }
.cs-console__corner--tr { top: 16px; right: 16px; border-left: 0; border-bottom: 0; border-radius: 0 6px 0 0; }
.cs-console__corner--bl { bottom: 16px; left: 16px; border-right: 0; border-top: 0; border-radius: 0 0 0 6px; }
.cs-console__corner--br { bottom: 16px; right: 16px; border-left: 0; border-top: 0; border-radius: 0 0 6px 0; }
.cs-console__scan { position: absolute; z-index: 1; left: 0; right: 0; top: 0; height: 90px; pointer-events: none; opacity: 0; background: linear-gradient(180deg, rgba(255, 140, 50, 0) 0%, rgba(255, 140, 50, 0.16) 85%, rgba(255, 170, 90, 0.75) 100%); }
.cs-console__status { position: absolute; z-index: 2; left: 32px; bottom: 30px; display: inline-flex; align-items: center; gap: 8px; padding: 7px 14px; border-radius: 999px; background: rgba(7, 21, 33, 0.7); border: 1px solid rgba(255, 255, 255, 0.15); color: #FFFFFF; font-size: 13px; letter-spacing: 0.06em; -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.cs-console__status i { width: 8px; height: 8px; border-radius: 50%; background: #3DDC84; box-shadow: 0 0 0 3px rgba(61, 220, 132, 0.25); }
.cs-console__status b { font-weight: 700; }
.cs-console__status em { font-style: normal; color: rgba(255, 255, 255, 0.55); }

/* One clock: each service shows for exactly one pass of the scan line
   (--cs-step), the line restarting at the top with every change (app.js). Both
   run only while the console is in view, not hovered and not frozen -- a
   click freezes it on the chosen service until the visitor scrolls on. */
.cs-console { --cs-step: 4.2s; }
@media (prefers-reduced-motion: no-preference) {
    .cs-console__item.is-active .cs-console__progress { opacity: 1; animation: cs-console-progress var(--cs-step) linear both; animation-play-state: paused; }
    .cs-console__scan { animation: cs-console-scan var(--cs-step) linear both; animation-play-state: paused; }
    .cs-console.is-running:not(:hover):not(.is-frozen) .cs-console__item.is-active .cs-console__progress,
    .cs-console.is-running:not(:hover):not(.is-frozen) .cs-console__scan { animation-play-state: running; }
    .cs-console.is-frozen .cs-console__progress { opacity: 0; }
    .cs-console.is-frozen .cs-console__scan { opacity: 0; }
    .cs-console__status i { animation: cs-console-blink 1.6s steps(1, end) infinite; }
}
@keyframes cs-console-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes cs-console-scan { 0% { opacity: 0; top: -90px; } 6% { opacity: 1; } 92% { opacity: 1; } 100% { opacity: 0; top: 100%; } }
@keyframes cs-console-blink { 0%, 60% { opacity: 1; } 60.01%, 100% { opacity: 0.35; } }

@media (max-width: 900px) {
    .cs-console { grid-template-columns: 1fr; }
    .cs-console__screen { order: -1; }
    .cs-console__frame { min-height: 0; aspect-ratio: 16 / 10; }
}
@media (max-width: 600px) {
    .cs-console { border-radius: 20px; }
    .cs-console__item { grid-template-columns: 38px minmax(0, 1fr); padding: 16px 12px; }
    .cs-console__no { display: none; }
    .cs-console__icon { width: 38px; height: 38px; }
    .cs-console__body h3 { margin-top: 7px; font-size: 17px; }
}
@media (max-width: 480px) {
    .cs-service { grid-template-columns: 1.35fr 1fr; }
    .cs-service__copy { padding: 1.3125rem 1.0625rem; }
    .cs-service h3 { font-size: var(--fs-h3); }
    .cs-service p { font-size: 14px; line-height: 1.6; }
    .cs-service__photo { min-height: 16.25rem; }
    .cs-service__meta { margin-bottom: 0.875rem; gap: 0.75rem; }
    .cs-service__icon { width: 2rem; height: 2rem; }
}

/* -- approach: full-bleed dark office photo as the section background
   (`understand-bg.webp`), heading+lead pinned top-left over it, then one
   compact row of 3 real circular photos (assess/prioritise/strengthen --
   each supplied pre-cropped to a circle with its own baked ring already
   on it, so no extra CSS ring/shadow is added on top) connected by a thin
   curved orange line with 3 small glowing points, labels left-aligned
   directly beneath each circle. Rebuilt from scratch per the user's
   reference screenshot -- the previous version (a 1983x793 "scene" with
   absolutely-positioned circles/labels and a separate background-less
   dark band) read nothing like it: huge gap under the heading, labels far
   below in their own disconnected row. This version keeps everything --
   heading, row, labels -- inside one compact panel on top of the photo. */
.cs-approach { position: relative; isolation: isolate; overflow: hidden; background: #031723; color: #fff; padding-block: var(--space-section); }
.cs-approach__media { position: absolute; inset: 0; z-index: -1; }
.cs-approach__media img { width: 100%; height: 100%; object-fit: cover; object-position: top right; display: block; }
.cs-approach__media::after { content: ""; position: absolute; inset: 0; background: linear-gradient(100deg, #031723 0%, rgba(3, 23, 35, 0.9) 30%, rgba(3, 23, 35, 0.42) 60%, rgba(3, 23, 35, 0.1) 100%); }
.cs-approach__intro { max-width: 34rem; }
/* #cyber-approach-scoped (not just .cs-approach__intro h2): the shared
   "body.service-page h2" rule is a class + two element selectors, out-
   specifying a single-class-plus-element selector here. */
#cyber-approach .cs-approach__intro h2 { font-size: var(--fs-h2); font-weight: 700; letter-spacing: -0.035em; }
.cs-approach__intro .lead { color: #c3d0d8; margin-top: 0.75rem; font-size: 1rem; }
.cs-approach__row { position: relative; display: grid; grid-template-columns: repeat(3, 1fr); column-gap: 1.5rem; margin-top: 2.5rem; max-width: 72rem; }
.cs-approach__connector { position: absolute; left: 0; width: 100%; top: 0; height: 10.25rem; overflow: visible; pointer-events: none; z-index: 0; }
.cs-flow__core, .cs-flow__halo, .cs-flow__spark { fill: none; stroke-linecap: round; }
.cs-flow__core { stroke: #ff9a45; stroke-width: 1.25; }
.cs-flow__halo { stroke: #ff8a26; stroke-width: 4; opacity: 0.25; filter: blur(2px); }
/* Travelling highlight: the same path, drawn as one short dash (butt caps,
   so it can't poke past either end) whose offset runs it from fully before
   the start to fully past the end -- it exists only on the line. */
.cs-flow__spark { stroke: #fff1dc; stroke-width: 3; stroke-linecap: butt; stroke-dasharray: 80 1000; stroke-dashoffset: 80; opacity: 0; }
.cs-approach__dot { fill: #ffb067; transform-box: fill-box; transform-origin: center; filter: drop-shadow(0 0 5px rgba(255, 138, 38, 0.8)); }
@media (prefers-reduced-motion: no-preference) {
    .cs-approach__row.is-visible .cs-flow__spark { opacity: 1; animation: cs-flow-travel 4s linear infinite; }
    .cs-approach__row.is-visible .cs-flow--second .cs-flow__spark { animation-delay: 2s; }
    .cs-approach__row.is-visible .cs-approach__dot { animation: cs-approach-pulse 2.6s ease-in-out infinite; }
    .cs-approach__row.is-visible .cs-approach__dot:nth-of-type(2) { animation-delay: 0.6s; }
    .cs-approach__row.is-visible .cs-approach__dot:nth-of-type(3) { animation-delay: 1.2s; }
    .cs-approach__row.is-visible .cs-approach__dot:nth-of-type(4) { animation-delay: 1.8s; }
}
@keyframes cs-flow-travel { 0% { stroke-dashoffset: 80; } 45% { stroke-dashoffset: -1000; } 100% { stroke-dashoffset: -1000; } }
@keyframes cs-approach-pulse { 0%, 100% { opacity: 0.6; transform: scale(1); } 50% { opacity: 1; transform: scale(1.5); } }
.cs-approach__step { position: relative; z-index: 1; text-align: left; }
/* The photo box includes the thin outline ring (border + padding), so the
   box edge -- which the connector's dots are measured from -- is the ring. */
.cs-approach__photo { position: relative; display: block; box-sizing: border-box; width: 10.25rem; height: 10.25rem; margin: 0 0 1.25rem 2.25rem; padding: 0.4rem; border: 1px solid rgba(255, 176, 103, 0.5); border-radius: 50%; box-shadow: 0 0 18px rgba(255, 138, 38, 0.12); }
.cs-approach__photo img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 50%; transform: scale(1.02); transition: transform 0.4s var(--ease); }
.cs-approach__step:hover .cs-approach__photo img { transform: scale(1.07); }
.cs-approach__badge { position: absolute; left: -1.1rem; bottom: 1.1rem; display: flex; align-items: center; justify-content: center; width: 3.1rem; height: 3.1rem; border-radius: 50%; background: #06182a; border: 1.5px solid #ff8a26; color: #ff9a45; box-shadow: 0 0 14px rgba(255, 138, 38, 0.45); }
.cs-approach__badge svg { width: 1.35rem; height: 1.35rem; }
.cs-approach__step h3 { font-size: var(--fs-h3); font-weight: 600; margin-bottom: 0.5rem; color: #fff; }
.cs-approach__step p { font-size: 14px; line-height: 1.55; color: #b4c3d0; max-width: 21.5rem; }
@media (max-width: 900px) {
    .cs-approach__row { grid-template-columns: 1fr; row-gap: 2.25rem; max-width: 26rem; }
    .cs-approach__connector { display: none; }
    .cs-approach__photo { width: 8.5rem; height: 8.5rem; margin-left: 1.1rem; }
    .cs-approach__badge { width: 2.6rem; height: 2.6rem; left: -0.9rem; bottom: 0.8rem; }
    .cs-approach__badge svg { width: 1.15rem; height: 1.15rem; }
    .cs-approach__step p { max-width: none; }
}

/* -- review: intro + 4 rows (icon, heading, paragraph), per reference's
   `.review-row`. Icons are inline SVG (this project's established icon
   convention) rather than the reference's own raster crops of its baked
   mockup, same substitution already made for Managed IT & Cloud and every
   earlier service page's own simple line icons. */
/* -- cybersecurity: review shield -----------------------------------------------------
   Two columns: the intro over a shield emblem (below), and the four changes as
   signal cards on a vertical track. As the emblem's orange arc reaches each
   change's icon, the icon lights and the matching card lights (orange edge,
   filled icon, track dot) -- one 8s clock with delays at the icons' angles.
   Static under reduced motion. */
.cs-review { background: #fbfaf7; }
.cs-review .cs-intro { margin-bottom: 0; }
.cs-review .cs-intro .lead { margin-top: 1.125rem; }
.cs-review__grid { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
/* the shield emblem: a navy shield core, a dashed outer ring turning slowly,
   a fine orbit with the four change icons on it (60/150/240/330 deg), and an
   orange arc sweeping the orbit once every 8s -- each icon lights as the arc
   reaches it (same 8s clock and delays as the cards). */
.cs-shield { position: relative; width: min(100%, 380px); aspect-ratio: 1; margin-top: 2.5rem; }
.cs-shield__ring { position: absolute; inset: 2%; border-radius: 50%; border: 1.5px dashed rgba(30, 58, 95, 0.22); }
.cs-shield__orbit { position: absolute; inset: 12%; border-radius: 50%; border: 1px solid rgba(30, 58, 95, 0.14); background: radial-gradient(circle, rgba(255, 101, 11, 0.06), rgba(255, 101, 11, 0) 70%); }
.cs-shield__arc {
    position: absolute;
    inset: 12%;
    border-radius: 50%;
    background: conic-gradient(from 0deg, rgba(255, 101, 11, 0) 0deg, rgba(255, 101, 11, 0) 280deg, rgba(255, 101, 11, 0.55) 355deg, #FF8A3D 360deg);
    -webkit-mask: radial-gradient(circle, transparent calc(50% - 4px), #000 calc(50% - 3px), #000 50%, transparent calc(50% + 1px));
    mask: radial-gradient(circle, transparent calc(50% - 4px), #000 calc(50% - 3px), #000 50%, transparent calc(50% + 1px));
}
.cs-shield__core {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 34%;
    aspect-ratio: 1;
    translate: -50% -50%;
    display: grid;
    place-items: center;
    border-radius: 50%;
    color: #FFFFFF;
    background: radial-gradient(circle at 35% 30%, #2A4E77, var(--color-ink));
    box-shadow: 0 20px 40px -18px rgba(9, 30, 48, 0.7), 0 0 0 8px rgba(30, 58, 95, 0.08), inset 0 0 0 1px rgba(255, 255, 255, 0.12);
}
.cs-shield__core svg { width: 46%; height: 46%; }
.cs-shield__core svg path:last-child { stroke: #FF8A3D; }
.cs-shield__node {
    position: absolute;
    width: 48px;
    height: 48px;
    margin: -24px 0 0 -24px;
    display: grid;
    place-items: center;
    border-radius: 14px;
    background: #FFFFFF;
    color: var(--color-ink);
    border: 1px solid #E3DDD4;
    box-shadow: 0 10px 22px -14px rgba(9, 30, 48, 0.4);
}
.cs-shield__node svg { width: 24px; height: 24px; }
/* icon accents follow the node colour, so they stay visible when it lights orange */
.cs-shield__node .cs-accent-stroke { stroke: currentColor; }
.cs-shield__node--1 { left: 82.9%; top: 31%; }
.cs-shield__node--2 { left: 69%; top: 82.9%; }
.cs-shield__node--3 { left: 17.1%; top: 69%; }
.cs-shield__node--4 { left: 31%; top: 17.1%; }

.cs-review-rows { position: relative; margin: 0; padding-left: 28px; }
.cs-review-rows::before { content: ""; position: absolute; left: 6px; top: 12px; bottom: 12px; width: 2px; border-radius: 2px; background: linear-gradient(180deg, rgba(255, 101, 11, 0.5), rgba(9, 30, 48, 0.1)); }
.cs-review-row {
    position: relative;
    display: grid;
    grid-template-columns: 48px minmax(0, 1fr);
    column-gap: 18px;
    align-items: start;
    padding: 20px 22px;
    border: 1px solid #E7E2DA;
    border-radius: 18px;
    background: #FFFFFF;
    box-shadow: 0 14px 30px -24px rgba(9, 30, 48, 0.35);
    transition: border-color 0.4s var(--ease), box-shadow 0.4s var(--ease), transform 0.4s var(--ease);
}
.cs-review-row + .cs-review-row { margin-top: 14px; }
.cs-review-row::before { content: ""; position: absolute; left: -27px; top: 34px; width: 12px; height: 12px; border-radius: 50%; background: #FFFFFF; border: 2px solid rgba(255, 101, 11, 0.55); }
.cs-review-row__icon { grid-row: 1 / 3; display: grid; place-items: center; width: 48px; height: 48px; border-radius: 14px; background: #F3F5F8; color: var(--color-ink); transition: background-color 0.4s, color 0.4s; }
.cs-review-row__icon svg { width: 24px; height: 24px; }
.cs-accent-stroke { stroke: #ff6907; }
.cs-review-row h3 { margin: 2px 0 6px; font-size: 20px; line-height: 1.3; letter-spacing: -0.01em; }
.cs-review-row p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--color-muted); }
@media (hover: hover) and (pointer: fine) {
    .cs-review-row:hover { transform: translateX(4px); border-color: rgba(255, 101, 11, 0.4); }
}

@media (prefers-reduced-motion: no-preference) {
    .cs-shield__arc { animation: cs-shield-turn 8s linear infinite; }
    .cs-shield__ring { animation: cs-shield-turn 60s linear infinite reverse; }
    .cs-shield__core { animation: cs-shield-pulse 4s ease-in-out infinite; }
    .cs-shield__node { animation: cs-shield-node 8s ease-out infinite; }
    .cs-shield__node--1 { animation-delay: 1.33s; }
    .cs-shield__node--2 { animation-delay: 3.33s; }
    .cs-shield__node--3 { animation-delay: 5.33s; }
    .cs-shield__node--4 { animation-delay: 7.33s; }
    .cs-review-row { animation: cs-review-lit 8s ease-out infinite; }
    .cs-review-row__icon { animation: cs-review-icon 8s ease-out infinite; }
    .cs-review-row::before { animation: cs-review-dot 8s ease-out infinite; }
    .cs-review-row:nth-child(1), .cs-review-row:nth-child(1) .cs-review-row__icon, .cs-review-row:nth-child(1)::before { animation-delay: 1.33s; }
    .cs-review-row:nth-child(2), .cs-review-row:nth-child(2) .cs-review-row__icon, .cs-review-row:nth-child(2)::before { animation-delay: 3.33s; }
    .cs-review-row:nth-child(3), .cs-review-row:nth-child(3) .cs-review-row__icon, .cs-review-row:nth-child(3)::before { animation-delay: 5.33s; }
    .cs-review-row:nth-child(4), .cs-review-row:nth-child(4) .cs-review-row__icon, .cs-review-row:nth-child(4)::before { animation-delay: 7.33s; }
}
@keyframes cs-shield-turn { to { rotate: 360deg; } }
@keyframes cs-shield-node { 0%, 22% { background: var(--color-accent); color: #FFFFFF; border-color: var(--color-accent); scale: 1.1; box-shadow: 0 0 0 6px rgba(255, 101, 11, 0.18), 0 12px 24px -10px rgba(255, 101, 11, 0.6); } 30%, 100% { background: #FFFFFF; color: var(--color-ink); border-color: #E3DDD4; scale: 1; box-shadow: 0 10px 22px -14px rgba(9, 30, 48, 0.4); } }
@keyframes cs-shield-pulse { 0%, 100% { box-shadow: 0 20px 40px -18px rgba(9, 30, 48, 0.7), 0 0 0 8px rgba(30, 58, 95, 0.08), inset 0 0 0 1px rgba(255, 255, 255, 0.12); } 50% { box-shadow: 0 20px 40px -18px rgba(9, 30, 48, 0.7), 0 0 0 16px rgba(255, 101, 11, 0.08), inset 0 0 0 1px rgba(255, 255, 255, 0.12); } }
@keyframes cs-review-lit { 0%, 22% { border-color: rgba(255, 101, 11, 0.55); box-shadow: inset 3px 0 0 var(--color-accent), 0 18px 36px -24px rgba(255, 101, 11, 0.45); } 30%, 100% { border-color: #E7E2DA; box-shadow: 0 14px 30px -24px rgba(9, 30, 48, 0.35); } }
@keyframes cs-review-icon { 0%, 22% { background: #FFF0E5; color: var(--color-accent); } 30%, 100% { background: #F3F5F8; color: var(--color-ink); } }
@keyframes cs-review-dot { 0%, 22% { background: var(--color-accent); box-shadow: 0 0 0 5px rgba(255, 101, 11, 0.2); } 30%, 100% { background: #FFFFFF; box-shadow: none; } }

@media (max-width: 991.98px) {
    .cs-review__grid { grid-template-columns: 1fr; }
    .cs-shield { width: min(100%, 280px); margin: 2rem auto 0; }
}
@media (max-width: 480px) {
    .cs-review-rows { padding-left: 22px; }
    .cs-review-row { grid-template-columns: 40px minmax(0, 1fr); padding: 16px; }
    .cs-review-row::before { left: -21px; }
    .cs-review-row__icon { width: 40px; height: 40px; }
    .cs-review-row h3 { font-size: 18px; }
}

/* -- enquiry: solid burnt-orange band, copy (with a bottom-bleeding room
   photo) left, real form card right -- per reference's own colour recipe
   (`.enquiry:before`'s gradient, preserved from its CSS even though that
   rule's own layout class is otherwise unused by the live page) and the
   bottom-bleeding "room-art" concept its CSS also already describes;
   its live "exact" markup bakes this same photo wholesale behind an
   absolutely-positioned form instead -- reused the plain two-column
   approach already established for the Managed IT & Cloud page's own
   enquiry section so the real interactive form isn't glued on top of a
   flat image via %-based absolute positioning. */
.cs-enquiry { position: relative; isolation: isolate; overflow: hidden; padding-block: var(--space-section-sm); background: #331104; color: #fff; }
.cs-enquiry > .container { position: relative; z-index: 1; }
.cs-contact-grid { display: grid; grid-template-columns: 1fr 1.06fr; gap: 4.375rem; align-items: center; }
.cs-contact-copy { position: relative; padding-top: 1.25rem; padding-bottom: 9.375rem; }
.cs-kicker--light { background: #ffca9a; }
.cs-contact-copy h2 { max-width: 25.625rem; font-size: var(--fs-h2); }
.cs-contact-copy__accent { color: #ffca9a; }
.cs-contact-copy p { color: #ffe7d7; max-width: 24.375rem; margin-top: 1.375rem; }
.cs-btn--light { background: #fff9f2; color: #132337; border-radius: 30px; margin-top: 1.75rem; gap: 1.5625rem; }
/* Bootstrap's generic ".btn:hover" rule (bootstrap.min.css) matches this
   plain .btn (no .btn-primary/.btn-light variant sets the --bs-btn-hover-*
   custom properties it reads), so `color` was resolving to its base .btn
   default of white -- on this button's own near-white background that
   washed the label/icon out to the point of being unreadable. Restating
   this button's own text colour here, plus a soft white glow instead of a
   hard colour change (same fix already applied to this button's :active
   state just below), keeps the label/icon fully visible on hover. */
.cs-btn--light:hover { background: #fff; color: #132337; box-shadow: 0 0 0 0.2rem rgba(255, 255, 255, 0.35); }
/* Bootstrap's generic ":not(.btn-check) + .btn:active" rule (bootstrap.min.css)
   matches this plain .btn (no .btn-primary/.btn-light variant sets the
   --bs-btn-active-* custom properties it reads), so on click/tap it was
   overriding color/background/border with those undefined properties --
   visually washing the button out to white. Restating this button's own
   colours at the same :active state, plus a subtle glow instead of a hard
   colour change, keeps the click feedback without the wash-out. */
.btn.cs-btn--light:active { background: #fff9f2; color: #132337; border-color: transparent; box-shadow: 0 0 0 0.2rem rgba(255, 255, 255, 0.35); }
/* Same backdrop as the Data Solutions & Digital Marketing enquiry section
   (.dm-contact__media, shared enquiry-scene.webp): full-bleed photo, a fixed
   left-side scrim for text contrast, and -- on phones -- the photo is
   dropped so the solid brown base (#331104) shows instead. */
.cs-enquiry__media { position: absolute; inset: 0; z-index: 0; }
.cs-enquiry__media img { width: 100%; height: 100%; object-fit: cover; object-position: center; }
.cs-enquiry__media::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(8, 5, 2, 0.62) 0%, rgba(8, 5, 2, 0.4) 32%, rgba(8, 5, 2, 0) 62%); }
.cs-enquiry-form { background: #fbfaf6; border-radius: 12px; box-shadow: 0 10px 30px rgba(99, 54, 28, 0.06); padding: 2rem; }
.cs-contact-form .form-label { font-size: 14px; font-weight: 600; color: #102339; margin-bottom: 0.4375rem; }
.cs-required { color: #ff6907; }
.cs-contact-form .form-control,
.cs-contact-form .form-select,
.cs-contact-form textarea.form-control {
    width: 100%;
    border: 1px solid #d8dbd9;
    border-radius: 5px;
    background: transparent;
    padding: 0.625rem 0.6875rem;
    color: #102339;
    font-size: 14px;
    min-height: 2.5rem;
}
.cs-contact-form .form-control::placeholder { color: #8996a4; }
.cs-contact-form textarea.form-control { min-height: 3rem; resize: vertical; }
.cs-contact-form .form-control:focus,
.cs-contact-form .form-select:focus { border-color: #ff6900; box-shadow: 0 0 0 0.1875rem rgba(255, 105, 0, 0.08); }
.cs-submit { display: inline-flex; align-items: center; justify-content: center; gap: 1.375rem; border: 0; border-radius: 28px; background: #ff6907; color: #fff; font-size: 14px; font-weight: 600; min-height: 2.75rem; padding: 0.6875rem 1.25rem; transition: background 0.25s, box-shadow 0.25s; }
.cs-submit:hover { background: #ed5c00; box-shadow: 0 5px 18px rgba(255, 105, 0, 0.15); color: #fff; }
@media (max-width: 1100px) { .cs-contact-grid { gap: 2.5rem; } .cs-enquiry-form { padding: 1.625rem; } }
@media (max-width: 800px) {
    .cs-contact-grid { grid-template-columns: 1fr; gap: 2.5rem; }
    .cs-contact-copy { padding: 0; }
    .cs-contact-copy h2, .cs-contact-copy p { max-width: 35rem; }
    .cs-enquiry-form { padding: 1.875rem; }
}
@media (max-width: 680px) { .cs-enquiry__media { display: none; } }
@media (max-width: 480px) {
    .cs-enquiry { padding-block: var(--space-section-sm); }
    .cs-enquiry-form { padding: 1.5rem 1.25rem; }
}

/* -- faq: shares the Data & Marketing design (#faq.dm-faq, see there). */

/* ==========================================================================
   Training page (reference/Valin-Training.html), scoped entirely to `.tr-*`
   and the section ids below. Photography is cropped straight from the
   reference's own flattened scene images (static/img/services/training/);
   headings/body copy/numbers are real markup (not baked into the images)
   so they stay selectable, accessible and consistent with every other
   already-built service page, matching that page's own section background
   colours exactly (#faf6ef/#08212f/#fafafa/#fff/#ef6819 -- taken directly
   from the reference's own inline CSS).
   ========================================================================== */

/* --- hero: see "training hero (dark scroll hero)" further down. */

/* --- training tracks ("Choose Your Technology"): intro + 5 photo-top cards,
   3 then 2 centred (flex-wrap + justify-content:center centres the short
   last row on its own, no separate markup needed) ------------------------ */
#training-tracks { background: #faf6ef; }
.tr-tracks-intro { max-width: 40rem; margin: 0 auto 2.5rem; text-align: center; }
.tr-tracks-intro .lead { margin-top: 0.875rem; }
.tr-tracks-grid { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.5rem; }
/* The whole card is a real <a> (click anywhere -> scrolls to the enquiry
   form + preselects this card's training option, see data-training-link in
   app.js) -- reset link defaults so it still looks/sizes like a card. */
.tr-track-card { display: block; flex: 1 1 28%; min-width: 16.5rem; max-width: 23rem; background: #fff; color: inherit; text-decoration: none; border: 1px solid #eee8de; border-radius: 14px; overflow: hidden; box-shadow: 0 1px 2px rgba(15, 30, 55, 0.04); transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease); }
/* Thin bright-orange outline (following the card's own rounded corners) +
   a soft orange glow on hover/focus -- border turned transparent first so
   the box-shadow ring doesn't double up against it. */
.tr-track-card:hover, .tr-track-card:focus-visible {
    transform: translateY(-4px);
    border-color: transparent;
    box-shadow: 0 0 0 1.5px rgba(255, 130, 8, 0.9), 0 0 22px rgba(255, 130, 8, 0.3), 0 12px 28px rgba(15, 30, 55, 0.08);
}
.tr-track-card:focus-visible { outline: none; }
.tr-track-card__photo { aspect-ratio: 436 / 193; overflow: hidden; }
/* The reference's own card art has a curved (not straight) lower edge --
   clipPathUnits=objectBoundingBox (defined once in training.html) scales
   the same curve to every card regardless of width/breakpoint. */
.tr-track-card__photo img { width: 100%; height: 100%; object-fit: cover; display: block; clip-path: url(#tr-card-clip); transition: transform 0.5s var(--ease); }
.tr-track-card:hover .tr-track-card__photo img { transform: scale(1.04); }
.tr-track-card__body { padding: 1rem 1.375rem 1.5rem; }
.tr-track-card__heading-row { display: flex; align-items: baseline; gap: 0.6rem; margin-bottom: 0.4rem; }
.tr-track-card h3 { font-size: var(--fs-h3); font-weight: 700; line-height: 1.3; margin: 0; color: var(--color-ink); }
.tr-track-card p { font-size: 0.875rem; line-height: 1.55; color: var(--color-muted); margin: 0; }

/* --- certifications (dark): compact banner -- the section's own photo
   (a dim navy server hall, quiet on the left for the heading) spans the *whole*
   section as one background, darkened just enough for the heading to read;
   each card then layers its own photo + a stronger scrim directly in its
   own `background` (no extra wrapper/blur layer) -- matches the reference's
   own compact proportions (much shorter than this section's first pass:
   less padding, tighter intro margin, smaller card padding/type). --------- */
#certifications { position: relative; isolation: isolate; overflow: hidden; background: #050C14; color: #fff; padding-block: var(--space-section); }
#certifications::before { content: ""; position: absolute; inset: 0; z-index: -2; background: url("/static/img/services/training/cert-section-bg.3d643c8fe5ba.webp?v=2") right center / cover no-repeat; }
/* Much lighter than the first pass -- that wash was darkening the whole
   photo (including the vertical glass-panel/light-strip detail at the top
   right the client specifically called out); this only needs to dim the
   very top (where the heading sits) and bottom (the transition into the
   next section), leaving the middle of the photo at full brightness. */
#certifications::after { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(180deg, rgba(5, 12, 20, 0.45) 0%, rgba(5, 12, 20, 0) 22%, rgba(5, 12, 20, 0) 70%, rgba(5, 12, 20, 0.6) 100%); }
/* Self-contained bottom-left wedge (same clip-path/gradient technique as
   .tr-credentials-accent below) -- independent of the next section so this
   reads correctly even on its own, not just where the two sections meet. */
.tr-certs-corner { position: absolute; left: 0; bottom: 0; width: 9rem; height: 9rem; z-index: 0; pointer-events: none; background: linear-gradient(45deg, #04141e 42%, var(--color-accent) 46%, var(--color-accent-light) 50%, transparent 53%); clip-path: polygon(0 100%, 0 0, 100% 100%); }
.tr-certs-glow { position: absolute; left: -10%; bottom: -25%; width: 55%; aspect-ratio: 1; border-radius: 50%; background: radial-gradient(circle, rgba(255, 130, 8, 0.22), transparent 70%); pointer-events: none; z-index: 0; }
.tr-certs-intro { position: relative; z-index: 1; max-width: 34rem; margin-bottom: 1.5rem; }
.tr-certs-intro h2 { font-size: var(--fs-h2); }
.tr-certs-intro .lead { margin-top: 0.5rem; font-size: 0.9375rem; color: rgba(255, 255, 255, 0.78); }
.tr-certs-grid { position: relative; z-index: 1; display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.125rem; }
.tr-cert-card {
    display: block;
    position: relative;
    color: #fff;
    text-decoration: none;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 12px;
    overflow: hidden;
    padding: 1.25rem 1.25rem 1.375rem;
    min-height: 13.5rem;
    transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
/* Text sits in a left-hand column; the gradient only needs to darken that
   column (left-to-right, not a flat wash over the whole card) so the photo
   itself -- laptop, cap, gear, the OpenShift container -- stays bright and
   clear on the right. The previous stops (opaque to only 32%, clear by 78%)
   left the laptop screens/gear/logo -- which start around 28-30% across
   each of these particular photos -- only lightly dimmed exactly where the
   72%-wide text column still sat, so the heading visually collided with the
   busy screen/gear content behind it. Fixed two ways together: the text
   column is narrower (so it never reaches into the fully-bright zone) and
   the dark stop now holds through the text's own width before fading out,
   so whatever little of the subject's left edge sits behind the text is
   still fully readable, while the subject's main, recognisable two-thirds
   (cap, gear, the OpenShift logo) stays untouched and bright. */
.tr-cert-card__rhcsa { background: linear-gradient(100deg, rgba(3, 9, 14, 0.94) 0%, rgba(3, 9, 14, 0.88) 30%, rgba(3, 9, 14, 0.5) 50%, rgba(3, 9, 14, 0.1) 66%, rgba(3, 9, 14, 0.02) 76%), url("/static/img/services/training/cert-rhcsa-bg.d0739bfcbf28.webp") center / cover no-repeat; }
.tr-cert-card__rhce { background: linear-gradient(100deg, rgba(3, 9, 14, 0.94) 0%, rgba(3, 9, 14, 0.88) 30%, rgba(3, 9, 14, 0.5) 50%, rgba(3, 9, 14, 0.1) 66%, rgba(3, 9, 14, 0.02) 76%), url("/static/img/services/training/cert-rhce-bg.efdbf5ad841c.webp") center / cover no-repeat; }
.tr-cert-card__openshift { background: linear-gradient(100deg, rgba(3, 9, 14, 0.94) 0%, rgba(3, 9, 14, 0.88) 30%, rgba(3, 9, 14, 0.5) 50%, rgba(3, 9, 14, 0.1) 66%, rgba(3, 9, 14, 0.02) 76%), url("/static/img/services/training/cert-openshift-bg.c817dba28f1b.webp") center / cover no-repeat; }
/* Quiet layer over every card photo (the section background went calm, the
   bright cap/gear/container photos were now the loudest thing in it): a navy
   wash that also pulls the saturation and brightness down. Hover/focus lifts
   most of it, so the photo comes back to life on the card being pointed at. */
.tr-cert-card::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background: rgba(5, 12, 20, 0.38);
    backdrop-filter: saturate(0.55) brightness(0.8);
    transition: opacity 0.4s var(--ease);
}
.tr-cert-card:hover::before, .tr-cert-card:focus-visible::before { opacity: 0.35; }
/* Orange glow ring on hover/focus, same technique as .tr-track-card. */
.tr-cert-card:hover, .tr-cert-card:focus-visible {
    transform: translateY(-3px);
    border-color: transparent;
    box-shadow: 0 0 0 1.5px rgba(255, 130, 8, 0.9), 0 0 22px rgba(255, 130, 8, 0.35), 0 12px 28px rgba(0, 0, 0, 0.3);
}
.tr-cert-card:focus-visible { outline: none; }
.tr-cert-card__text { position: relative; z-index: 1; max-width: 54%; }
.tr-cert-card__logo { height: 1.375rem; width: auto; margin-bottom: 0.875rem; display: block; }
.tr-cert-card h3 { font-size: var(--fs-h3); font-weight: 700; margin-bottom: 0.25rem; color: #fff; }
.tr-cert-card__subtitle { font-size: 14px; color: rgba(255, 255, 255, 0.85); line-height: 1.4; margin-bottom: 0.75rem; }
.tr-cert-card p { font-size: 14px; line-height: 1.5; color: rgba(255, 255, 255, 0.72); margin: 0; }
.tr-certs-foot { position: relative; z-index: 1; margin-top: 1.5rem; text-align: center; max-width: 46rem; margin-inline: auto; font-size: 14px; color: rgba(255, 255, 255, 0.65); }
@media (max-width: 900px) {
    .tr-certs-grid { grid-template-columns: 1fr; }
    .tr-cert-card { min-height: 11rem; }
    /* Was 82% -- fine for a narrow mobile card, but once cards stack to a
       single column they stay just as wide as a 3-up desktop row (minus the
       gutters), so the subject (laptop/cap/gear/logo) still starts around
       the same ~28-30% mark it does on desktop; 82% let the text's last
       line run out past where the gradient had already cleared, straight
       across the cap/container. Same ~54% share as desktop keeps it inside
       the still-dark part of the gradient at every stacked width. */
    .tr-cert-card__text { max-width: 54%; }
}
/* Phones: the section photo is bright behind the heading/lead, so white text
   blended in. A soft dark panel (fading out at the bottom, before the cards)
   sits behind just the intro; negative margin = padding keeps the text where
   it was, and type sizes/colours (orange accent line included) are untouched. */
@media (max-width: 767.98px) {
    /* Closing paragraph: its own dark backing (white .65 text on the bright
       photo was unreadable), stronger text colour + a soft shadow, and the
       diagonal corner wedge shrunk with extra section bottom padding so the
       paragraph sits clear above it instead of running across the orange line. */
    #certifications { padding-bottom: var(--space-section); }
    .tr-certs-corner { width: 5rem; height: 5rem; }
    .tr-certs-foot { margin-inline: -0.75rem; padding: 1rem 1.125rem; font-size: 0.875rem; line-height: 1.6; color: rgba(255, 255, 255, 0.95); text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6); background: linear-gradient(180deg, rgba(3, 12, 20, 0.82), rgba(3, 12, 20, 0.7)); border-radius: 0.75rem; }
    .tr-certs-intro { margin-inline: -0.75rem; padding: 1rem 0.75rem 1.25rem; border-radius: 0.75rem; background: linear-gradient(180deg, rgba(3, 12, 20, 0.82) 0%, rgba(3, 12, 20, 0.7) 70%, rgba(3, 12, 20, 0) 100%); }
}

/* --- credentials band: light card, Red Hat partner badge + three stats,
   diagonal corner accents reusing the same clip-path technique as
   .approach-media__stripe elsewhere on the site ---------------------------- */
#credentials { background: linear-gradient(135deg, #fdfaf5, #fff); padding-block: var(--space-section); position: relative; overflow: hidden; }
.tr-credentials-accent { position: absolute; width: 9rem; height: 9rem; pointer-events: none; z-index: 0; }
.tr-credentials-accent--tl { top: 0; left: 0; background: linear-gradient(135deg, #0b1b26 45%, var(--color-accent) 48%, var(--color-accent-light) 52%, transparent 55%); clip-path: polygon(0 0, 100% 0, 0 100%); }
.tr-credentials-accent--br { bottom: 0; right: 0; background: linear-gradient(-45deg, #0b1b26 45%, var(--color-accent) 48%, var(--color-accent-light) 52%, transparent 55%); clip-path: polygon(100% 100%, 100% 0, 0 100%); }
/* Split card: a navy Red Hat partner panel on the left (Red Hat red glow and
   faint concentric rings in its corner), the three stats as rows on the right. */
.tr-credentials-card { position: relative; z-index: 1; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); overflow: hidden; background: #FFFFFF; border: 1px solid rgba(9, 30, 48, 0.07); border-radius: 24px; box-shadow: 0 30px 60px -34px rgba(9, 30, 48, 0.35); }
.tr-credentials-partner { position: relative; isolation: isolate; overflow: hidden; display: flex; flex-direction: column; justify-content: center; padding: clamp(2rem, 4vw, 3.25rem); color: #FFFFFF; background: radial-gradient(ellipse 70% 60% at 100% 100%, rgba(238, 0, 0, 0.28), rgba(238, 0, 0, 0) 70%), linear-gradient(150deg, #10263A 0%, #091E30 100%); }
.tr-credentials-partner::before { content: ""; position: absolute; right: -90px; bottom: -90px; z-index: -1; width: 300px; height: 300px; border-radius: 50%; background: repeating-radial-gradient(circle, rgba(255, 255, 255, 0.09) 0 1px, transparent 1px 26px); -webkit-mask-image: radial-gradient(circle, #000 40%, transparent 72%); mask-image: radial-gradient(circle, #000 40%, transparent 72%); }
.tr-credentials-partner img { height: 2.4rem; width: auto; display: block; margin-bottom: 1.75rem; }
.tr-credentials-partner__eyebrow { font-size: 12.5px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: #FF8A80; }
#credentials .tr-credentials-partner__title { margin: 8px 0 0; font-size: clamp(26px, 2.4vw, 34px); font-weight: 700; line-height: 1.12; letter-spacing: -0.02em; color: #FFFFFF; }
.tr-credentials-partner p { margin: 14px 0 0; max-width: 24rem; font-size: 15.5px; line-height: 1.6; color: rgba(255, 255, 255, 0.72); }
.tr-credentials-stats { display: flex; flex-direction: column; justify-content: center; padding: clamp(1.25rem, 2.5vw, 2rem) clamp(1.75rem, 3.5vw, 3rem); }
.tr-credentials-stat { display: grid; grid-template-columns: 52px auto minmax(0, 1fr); align-items: center; column-gap: 20px; padding: 22px 0; border-top: 1px solid #ECE6DC; }
.tr-credentials-stat:first-child { border-top: 0; }
.tr-credentials-stat__icon { display: grid; place-items: center; width: 52px; height: 52px; border-radius: 14px; background: #FFF0E4; color: var(--color-accent); }
.tr-credentials-stat__icon svg { width: 26px; height: 26px; }
.tr-credentials-stat__num { min-width: 7.5ch; font-weight: 700; font-size: clamp(28px, 2.6vw, 38px); line-height: 1; color: var(--color-ink); letter-spacing: -0.025em; }
.tr-credentials-stat__label { margin: 0; font-size: 15px; color: var(--color-muted); line-height: 1.45; }
@media (max-width: 900px) {
    .tr-credentials-card { grid-template-columns: 1fr; }
}
@media (max-width: 520px) {
    .tr-credentials-stat { grid-template-columns: 44px minmax(0, 1fr); row-gap: 6px; }
    .tr-credentials-stat__icon { grid-row: span 2; width: 44px; height: 44px; }
    .tr-credentials-stat__icon svg { width: 22px; height: 22px; }
}
}

/* --- practice: three connected steps. Rebuilt against the reference's own
   decoded scene image (reference/Valin-Training.html bakes this section as
   one raster + an invisible SVG motion path -- decoded its embedded PNG
   to see the actual intended composition, since there's no live CSS to
   read for it). Icon artwork/colour-split already matched the reference
   exactly from an earlier pass -- untouched here. What changed: the
   connector's curve shape (now derived from the reference's own path
   geometry, re-anchored to this layout's actual icon positions instead of
   a generic double-hump wave), the step number (was a small "01 --" inline
   label; the reference shows a large pale numeral + a short solid orange
   line beside it), and the bead/glow animation (was three independent CSS
   keyframes with hand-estimated delays approximating where the SMIL bead
   might be; now one JS loop -- see app.js's "Training page: practice
   section" block -- drives the bead's path position and each icon's glow
   from the same progress value every frame, ported from the reference's
   own journeyState()/paintJourney() timing). ------------------------- */
#practice { position: relative; isolation: isolate; overflow: hidden; background: #fff; padding-block: var(--space-section); }
/* Soft curved peach tint low in the section -- subtle, matching the
   reference's own shallow white-to-peach fade near the bottom. */
#practice::after { content: ""; position: absolute; inset: auto 0 0 0; z-index: -1; height: 55%; background: radial-gradient(ellipse 75% 100% at 50% 100%, rgba(255, 145, 55, 0.22), transparent 78%); pointer-events: none; }
.tr-practice-intro { max-width: 44rem; margin: 0 auto 2.75rem; text-align: center; }
.tr-practice-intro .lead { margin-top: 0.875rem; }
.tr-practice-row { position: relative; display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; max-width: 64rem; margin-inline: auto; }
/* top:0/height:4.5rem (== the icon's own height) so the viewBox's baseline
   (y=22.5 of 0 0 640 72, i.e. the icon's own radius) lands exactly on the
   icon circle's centre. viewBox width (640) and the three path endpoints
   (22.5, 240.8, 459.2) are the icon centres' own x-position in this exact
   3-column/4.5rem-icon/1.5rem-gap/64rem-row layout, converted to the same
   units (1 unit = 0.1rem) -- not the reference's own raw pixel path (its
   layout -- a single baked image -- has entirely different proportions),
   but the reference's *relative* curve shape (dip down from the icon,
   flatten, rise, then a short straight run into the next icon) re-derived
   against these endpoints, so the curve still touches both icons dead
   centre regardless of viewport width (preserveAspectRatio="none" stretches
   it to the row's actual box every time). */
/* width:100% is load-bearing: an <svg> is a replaced element, so
   position:absolute + left:0/right:0 alone does *not* stretch it -- without
   an explicit width it just renders at its own viewBox's intrinsic size
   (640px here) regardless of how wide the row actually is, silently
   misaligning every path/icon pairing below a certain width.
   height:7.5rem (120px) is deliberately *not* 4.5rem (the icon's own
   height) any more: with preserveAspectRatio="none" the box height and the
   viewBox height (120) must match 1:1 in px for the path's y-coordinates to
   mean what they say (icon anchors really sit at y=36 = 2.25rem, the icon's
   true centre) -- 120 gives enough room for the dip (down to y=108) to
   clear a step's full icon+heading+description height at every width this
   row actually renders at (measured 75.8px-98.3px across 760-1280px; 108
   plus z-index:0 below .tr-practice-step keeps a safety margin either way).
   Stays absolutely positioned/out of flow, so this taller box never affects
   the row's own auto height. */
.tr-practice-connector { position: absolute; left: 0; right: 0; top: 0; width: 100%; height: 7.5rem; overflow: visible; pointer-events: none; z-index: 0; }
/* Bead: default hidden (JS fades it in once the section is in view and
   fades it out at the end of each lap, matching the reference's own
   traveller/arrivals starting at opacity 0). Two-layer bead (soft orange
   outer blur + a bright core with a light edge) -- same recipe and colours
   as the reference's own `.traveller` (`#ff842b`/`#ff7819`/`#fff9ee`). */
.tr-practice-traveller { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
    .tr-practice-traveller { display: none; }
}
/* Icon + text side by side (text to the right of the icon). */
.tr-practice-step { position: relative; z-index: 1; display: flex; align-items: flex-start; gap: 0.875rem; text-align: left; }
.tr-practice-step__icon {
    position: relative;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 4.5rem;
    height: 4.5rem;
    border-radius: 50%;
    background: #fff;
    color: var(--color-ink);
    --halo: 0;
    box-shadow:
        0 0 0 1px #f3e9dc,
        0 6px 16px rgba(15, 30, 55, 0.06),
        0 0 0 calc(1px + var(--halo) * 3px) rgba(255, 130, 8, var(--halo)),
        0 0 calc(var(--halo) * 22px) rgba(255, 130, 8, calc(var(--halo) * 0.4));
}
/* Soft light-orange halo, bigger/softer than a box-shadow can give -- sits
   behind the white circle on its own layer so it doesn't tint the icon.
   Opacity is the *same* --halo custom property the ring above reads, set
   once per animation frame by app.js from the bead's own progress -- so the
   soft glow and the crisp ring always move together, and only ever on the
   one icon the bead has actually reached. */
.tr-practice-step__icon::before { content: ""; position: absolute; inset: -42%; z-index: -1; border-radius: 50%; background: radial-gradient(circle, rgba(255, 140, 40, 0.35), transparent 72%); opacity: var(--halo); }
.tr-practice-step__icon svg { width: 44%; height: 44%; }
.tr-practice-step__text { min-width: 0; }
/* Large pale numeral + a short solid orange line beside it, replacing the
   old small "01 --" inline label -- matches the reference's own treatment
   (no hyphen character; the "dash" is a drawn line, not a glyph). */
.tr-practice-step__meta { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.25rem; line-height: 1; }
.tr-practice-step__num { font-size: 1.875rem; font-weight: 700; color: rgba(255, 141, 83, 0.4); letter-spacing: -0.02em; }
.tr-practice-step__dash { display: block; width: 1.375rem; height: 2px; background: var(--color-accent); border-radius: 2px; }
.tr-practice-step h3 { font-size: var(--fs-h3); font-weight: 700; margin-bottom: 0.35rem; color: var(--color-ink); }
.tr-practice-step p { font-size: 0.9375rem; color: var(--color-muted); margin: 0; }
@media (max-width: 900px) and (min-width: 751px) {
    .tr-practice-row { gap: 1rem; }
    .tr-practice-step { gap: 0.625rem; }
}
@media (max-width: 750px) {
    .tr-practice-row { grid-template-columns: 1fr; gap: 2.25rem; max-width: 24rem; }
    .tr-practice-connector { display: none; }
}

/* --- enquiry: reproduces reference/Valin-Training.html's own #enquiry
   scene exactly -- one full-bleed image at its native aspect ratio (not a
   fixed-height crop: the previous pass nested the image inside the
   Bootstrap .container, which capped it to the container's own max-width
   instead of the full section/viewport, and gave the section a fixed
   min-height instead of locking to the photo's own proportions, so the
   image was both too narrow and cropped). The copy and the form card are
   positioned with the reference's own exact left/top/width(/height)
   percentages (the form's are read straight from its `.form{}` rule),
   anchored to this same aspect-ratio-locked box so they land in exactly
   the same place the reference's own absolutely-positioned overlays do,
   at any viewport width. container-type/cqw-sized type keeps every field
   legible as that box scales, same technique the reference's own
   `clamp(..,.84cqw,..)` rules use. ---------------------------------------- */
#training-enquiry { background: #ef6819; color: #fff; }
.tr-enquiry-scene { position: relative; isolation: isolate; width: 100%; aspect-ratio: 1991 / 790; min-height: 30rem; overflow: hidden; container-type: inline-size; }
.tr-enquiry-bg { position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }
.tr-enquiry-copy { position: absolute; left: 20%; top: 19%; width: 34%; z-index: 1; }
/* #training-enquiry (ID beats the shared body.service-page h2 rule's
   specificity) -- white text on the section's own photo background. */
#training-enquiry .tr-enquiry-copy h2 { font-size: var(--fs-h2); font-weight: 700; line-height: 1.15; letter-spacing: -0.03em; color: #fff; }
/* Second line is dark ink, not white or the site's usual orange accent --
   matches the reference's own two-tone heading exactly. */
.tr-enquiry-copy__dark { color: var(--color-ink); }
.tr-enquiry-copy p { font-size: clamp(14px, 1cqw, 1.0625rem); line-height: 1.5; color: rgba(255, 255, 255, 0.92); margin-bottom: 0.6cqw; }
/* The card sits on the scene's bottom edge and takes the height its form
   needs (growing upwards, capped at the scene), so the submit button is
   always visible without an internal scrollbar; the scene's min-height keeps
   room for it on narrower desktops. Left/width stay as the reference
   specifies since those line it up with the photo. */
.tr-enquiry-form-card { position: absolute; left: 62.6%; bottom: 0.8%; width: 32.7%; max-height: 98%; z-index: 1; background: #fcfaf8; border-radius: 1.3cqw; box-shadow: var(--shadow-lg); padding: 1.8cqw 2cqw; overflow: auto; }
/* sized so the heading stays on one line and the submit button fits in the
   card without scrolling */
.tr-enquiry-form-card h3 { font-size: clamp(19px, 1.45cqw, 24px); line-height: 1.2; margin-bottom: 0.9cqw; color: var(--color-ink); }
.tr-contact-form .form-label { font-size: clamp(14px, 0.72cqw, 0.8125rem); font-weight: 600; color: var(--color-ink); margin-bottom: 0.2cqw; }
.tr-contact-form .row { --bs-gutter-x: 1.6cqw; --bs-gutter-y: 0.6cqw; }
.tr-contact-form .form-control, .tr-contact-form .form-select { font-size: clamp(14px, 0.75cqw, 0.875rem); padding-block: 0.4cqw; }
.tr-contact-form textarea.form-control { min-height: 3.2cqw; height: 4.5rem; }
.tr-submit.mt-4 { margin-top: 0.8cqw !important; }
.tr-required { color: var(--color-accent); }
/* Small decorative glyphs inside each field, matching the reference --
   plain currentColor-free data-URIs so they don't need extra markup. */
.tr-contact-form .form-control, .tr-contact-form .form-select { background-repeat: no-repeat; background-position: 0.8rem center; background-size: 1.1rem; padding-left: 2.5rem; }
.tr-contact-form textarea.form-control { background-position: 0.8rem 0.9rem; }
.tr-contact-form #tr-contact-name { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c77a3f' stroke-width='1.6'%3E%3Ccircle cx='12' cy='8' r='3.2'/%3E%3Cpath d='M5 20c0-3.5 3.1-6.3 7-6.3s7 2.8 7 6.3'/%3E%3C/svg%3E"); }
.tr-contact-form #tr-contact-email { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c77a3f' stroke-width='1.6'%3E%3Crect x='3' y='5' width='18' height='14' rx='2'/%3E%3Cpath d='m4 7 8 6 8-6'/%3E%3C/svg%3E"); }
.tr-contact-form #tr-contact-phone { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c77a3f' stroke-width='1.6'%3E%3Cpath d='M5 4h3.2l1.3 4.5L7.5 10a11 11 0 0 0 6.5 6.5l1.5-2 4.5 1.3V19a2 2 0 0 1-2.2 2A16 16 0 0 1 3 6.2 2 2 0 0 1 5 4Z'/%3E%3C/svg%3E"); }
.tr-contact-form #tr-contact-org { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c77a3f' stroke-width='1.6'%3E%3Crect x='4' y='3' width='16' height='18'/%3E%3Cpath d='M9 7h2M13 7h2M9 11h2M13 11h2M9 15h2M13 15h2'/%3E%3C/svg%3E"); }
.tr-contact-form #tr-contact-regarding { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c77a3f' stroke-width='1.6'%3E%3Cpath d='M12 4 2 9l10 5 8-4.2V15'/%3E%3Cpath d='M6 11.5V16c0 1.4 2.7 2.5 6 2.5s6-1.1 6-2.5v-4.5'/%3E%3C/svg%3E"), var(--select-chevron-dark); background-position: 0.8rem center, right 0.75rem center; background-size: 1.1rem, 12px 12px; padding-right: 2.25rem; }
.tr-contact-form #tr-contact-message { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23c77a3f' stroke-width='1.6'%3E%3Cpath d='M7 3h8l4 4v14H7Z'/%3E%3Cpath d='M9 11h6M9 15h6'/%3E%3C/svg%3E"); }
.tr-submit { background: linear-gradient(110deg, #ff9115, #ff4d08); border: 0; color: #fff; width: 100%; justify-content: center; font-size: clamp(14px, 0.9cqw, 1rem); }
.tr-submit:hover { filter: brightness(1.06); color: #fff; }
/* Below ~900px the reference's own mobile rules abandon the absolute scene
   entirely for a plain stacked flow (its own `#enquiry .form{position:
   relative;...}` override) -- same here: image becomes a shorter banner,
   copy and form stack underneath in normal flow. */
@media (max-width: 900px) {
    .tr-enquiry-scene { aspect-ratio: auto; min-height: 0; display: flex; flex-direction: column; }
    .tr-enquiry-bg { position: relative; inset: auto; aspect-ratio: 1991 / 790; z-index: 0; }
    .tr-enquiry-copy { position: relative; left: auto; top: auto; width: auto; max-width: none; padding: 1.75rem 1.25rem 0; }
    #training-enquiry .tr-enquiry-copy h2 { font-size: var(--fs-h2); }
    .tr-enquiry-copy p { font-size: 0.9375rem; }
    .tr-enquiry-form-card { position: relative; left: auto; top: auto; bottom: auto; max-height: none; width: auto; height: auto; margin: 1.5rem 1.25rem; padding: 1.5rem; }
    .tr-enquiry-form-card h3 { font-size: var(--fs-h3); }
    .tr-contact-form .form-label, .tr-contact-form .form-control, .tr-contact-form .form-select, .tr-submit { font-size: 0.875rem; }
}
/* Phones: heading/copy first, then the photo, then the form (the stacked
   layout above had the photo first). The copy is white-on-photo by design, so
   on its own it gets a matching sunset-orange backing to stay readable. */
@media (max-width: 767.98px) {
    .tr-enquiry-copy { order: 1; background: linear-gradient(180deg, #a63f08, #d1601a); padding: 1.75rem 1.25rem 1.5rem; }
    .tr-enquiry-bg { order: 2; }
    .tr-enquiry-form-card { order: 3; }
}

/* =============================================================================
   About page (.abt-*). Own design system (not reusing .svc-, .cs- or .itc-),
   matching the supplied v0 reference mockup: white-fade photo hero, a
   two-tone orange timeline on a navy "story" band, a 6-card capabilities
   grid, a navy 4-column "approach" band and a photo "perspective" panel,
   closing with the shared .cta-band--contact enquiry component (its own
   background photo only -- form markup/behaviour untouched). */

/* --- hero ------------------------------------------------------------------- */
.abt-hero { position: relative; isolation: isolate; overflow: hidden; min-height: 37.5rem; display: flex; align-items: center; background: #fff; }
.abt-hero__media { position: absolute; inset: 0; z-index: -2; }
.abt-hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: center right; display: block; }
.abt-hero::before { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(90deg, #fff 0%, rgba(255, 255, 255, 0.92) 28%, rgba(255, 255, 255, 0.45) 52%, rgba(255, 255, 255, 0) 68%); }
.abt-hero .container { position: relative; padding-block: clamp(5rem, 9vw, 8.75rem); }
.abt-hero__copy { max-width: 37.5rem; }
.abt-hero__copy h1 { font-size: var(--fs-h1); line-height: 1.04; letter-spacing: -0.03em; margin-bottom: 1.375rem; }
.abt-hero__sub { font-size: 1.125rem; font-weight: 600; margin-bottom: 1rem; color: var(--color-text); }
.abt-hero__copy > p { max-width: 35rem; margin-bottom: 1.75rem; color: var(--color-muted); }
.abt-hero__tags { position: absolute; right: 7.5rem; bottom: 5.625rem; color: #fff; font-size: 14px; font-weight: 600; letter-spacing: 0.14em; line-height: 2.1; text-transform: uppercase; text-shadow: 0 1px 8px rgba(0, 0, 0, 0.4); }

/* --- who we are --------------------------------------------------------------- */
.abt-who__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 4.375rem; align-items: center; }
.abt-who__visual { position: relative; padding: 0 3.75rem 1.875rem 0; }
.abt-who__frame { position: absolute; left: -1.25rem; top: 2.5rem; right: 1.875rem; bottom: 0; border-radius: 1.875rem; background: linear-gradient(135deg, var(--color-accent-light), var(--color-accent)); z-index: 0; }
.abt-who__visual img { position: relative; z-index: 1; border-radius: 1.625rem; width: 100%; aspect-ratio: 1.3 / 1; object-fit: cover; }
.abt-who__card { position: absolute; z-index: 2; right: 0; bottom: 0; width: 14.375rem; background: #fff; border-radius: 1rem; padding: 1.125rem 1.125rem 1.25rem; box-shadow: 0 1.25rem 2.5rem -1rem rgba(11, 26, 46, 0.3); }
.abt-who__card-title { color: var(--color-ink); font-size: var(--fs-h4); font-weight: 600; line-height: 1.3; margin: 0.375rem 0 0.875rem; }
.abt-who__card-title svg { width: 1.375rem; height: 1.375rem; color: var(--color-accent); display: inline-block; vertical-align: -0.1875rem; margin-right: 0.25rem; }
.abt-who__card p { font-size: 14px; line-height: 1.45; margin: 0; }
.abt-who__copy h2 { margin-bottom: 1.125rem; }
.abt-who__copy p { margin-bottom: 1rem; font-size: 14px; }

/* --- wave helpers (shared by story/approach/contact) ------------------------- */
.abt-wave { display: block; width: 100%; height: 3.125rem; position: absolute; left: 0; z-index: 1; }
.abt-wave--top { top: -1px; }
.abt-wave--bottom { bottom: -1px; }

/* --- story / timeline --------------------------------------------------------- */
.abt-story { position: relative; color: #fff; background: var(--color-ink) url("../img/Aboutus/story-bg.9ef7a43d28cd.webp") center / cover no-repeat; padding: var(--space-section) 0; overflow: hidden; }
.abt-story::before { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(9, 30, 48, 0.96) 0%, rgba(9, 30, 48, 0.85) 40%, rgba(9, 30, 48, 0.2) 75%); }
.abt-story .container { position: relative; z-index: 1; }
.abt-story__grid { display: grid; grid-template-columns: 1fr 1.1fr; gap: 2.5rem; align-items: center; }
.abt-story__copy h2 { color: #fff; margin-bottom: 2.125rem; font-size: var(--fs-h2); }
.abt-story__copy p { color: #c6cedb; font-size: 0.875rem; margin-bottom: 1rem; max-width: 29.375rem; }
.abt-story__copy p strong { color: #fff; font-weight: 600; }
.abt-timeline { position: relative; display: grid; grid-template-columns: repeat(3, 1fr); align-items: end; min-height: 20rem; }
.abt-timeline__path { position: absolute; left: 0; right: 0; top: 2.5rem; width: 100%; height: 12.5rem; pointer-events: none; }
.abt-t-item { position: relative; text-align: center; display: flex; flex-direction: column; align-items: center; }
.abt-t-item--2 { margin-bottom: 1.875rem; }
.abt-t-item--3 { align-self: center; transform: translateY(-3.125rem); }
.abt-t-img { width: 5.125rem; height: 5.125rem; border-radius: 50%; border: 3px solid rgba(255, 255, 255, 0.9); overflow: hidden; box-shadow: 0 0 0 6px rgba(255, 101, 11, 0.15), 0 0 1.875rem rgba(255, 101, 11, 0.5); }
.abt-t-img img { width: 100%; height: 100%; object-fit: cover; }
.abt-t-dot { width: 0.75rem; height: 0.75rem; border-radius: 50%; background: var(--color-accent); box-shadow: 0 0 0 4px rgba(255, 101, 11, 0.3), 0 0 1rem var(--color-accent); margin: 0.875rem 0 0.375rem; transition: box-shadow 0.3s var(--ease), transform 0.3s var(--ease); }
.abt-t-year { font-size: 1.125rem; font-weight: 700; transition: text-shadow 0.3s var(--ease); }
.abt-t-year--small { font-size: 14px; color: var(--color-accent); transition: text-shadow 0.3s var(--ease); }
/* Hovering a timeline entry gives its year a subtle glow to match the dot
   marking it -- purely a hover affordance (no idle motion), so it isn't
   gated behind prefers-reduced-motion, same convention as this site's
   other hover-only transforms (e.g. .cp-cap:hover). */
.abt-t-item:hover .abt-t-dot { box-shadow: 0 0 0 6px rgba(255, 101, 11, 0.4), 0 0 1.5rem var(--color-accent); transform: scale(1.15); }
.abt-t-item:hover .abt-t-year, .abt-t-item:hover .abt-t-year--small { text-shadow: 0 0 10px rgba(255, 101, 11, 0.6), 0 0 20px rgba(255, 101, 11, 0.3); }
.abt-t-item p { font-size: 14px; color: #e2e7ef; line-height: 1.4; max-width: 10rem; margin: 0.25rem auto 0; }

/* --- capabilities -------------------------------------------------------------- */
.abt-caps { background: #faf8f3; }
.abt-caps__head { display: flex; justify-content: space-between; align-items: center; gap: 1.875rem; margin-bottom: 1.875rem; flex-wrap: wrap; }
.abt-caps__head h2 { margin-bottom: 1.125rem; }
.abt-caps__head p { font-size: 0.875rem; max-width: 35rem; margin: 0 0 0.5rem; color: var(--color-muted); }
.abt-caps__cta { flex-shrink: 0; }
.abt-cap-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1rem; }
.abt-cap { display: block; color: inherit; text-decoration: none; background: #fff; border-radius: 0.75rem; padding: 1.625rem 0.75rem 1.25rem; text-align: center; box-shadow: 0 10px 30px -14px rgba(11, 26, 46, 0.25); border: 1px solid #f1f2f5; transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease); }
.abt-cap:hover { transform: translateY(-4px); box-shadow: 0 18px 34px -14px rgba(255, 101, 11, 0.4); color: inherit; }
.abt-cap svg { width: 2.125rem; height: 2.125rem; color: var(--color-accent); margin: 0 auto 1.125rem; }
.abt-cap h3 { font-size: 14px; font-weight: 600; line-height: 1.35; margin: 0; color: var(--color-text); }

/* --- approach -------------------------------------------------------------------- */
.abt-approach { position: relative; background: var(--color-ink); color: #fff; padding: var(--space-section) 0; overflow: hidden; }
.abt-approach__glow { position: absolute; right: -3.75rem; top: 1.25rem; width: 60%; height: 13.75rem; opacity: 0.9; z-index: 0; }
.abt-approach .container { position: relative; z-index: 1; }
.abt-approach h2 { color: #fff; margin-bottom: 2.75rem; }
.abt-ap-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2.5rem; }
.abt-ap svg { width: 1.625rem; height: 1.625rem; color: var(--color-accent); margin-bottom: 0.75rem; filter: drop-shadow(0 0 4px rgba(255, 101, 11, 0.35)); }
/* Gentle idle float + glow pulse, each icon out of phase with the others
   so the row doesn't bob in lockstep. Reduced motion keeps the static
   glow set above (drop-shadow isn't motion) and just drops the loop. */
@media (prefers-reduced-motion: no-preference) {
    .abt-ap svg { animation: abt-ap-icon-float 4.5s ease-in-out infinite; }
    .abt-ap:nth-child(2) svg { animation-delay: -1.1s; }
    .abt-ap:nth-child(3) svg { animation-delay: -2.2s; }
    .abt-ap:nth-child(4) svg { animation-delay: -3.3s; }
}
@keyframes abt-ap-icon-float {
    0%, 100% { transform: translateY(0); filter: drop-shadow(0 0 4px rgba(255, 101, 11, 0.35)); }
    50% { transform: translateY(-4px); filter: drop-shadow(0 0 10px rgba(255, 101, 11, 0.6)); }
}
.abt-ap h3 { font-size: 1rem; font-weight: 600; margin-bottom: 0.5rem; color: #fff; }
.abt-ap p { font-size: 14px; color: #c6cedb; line-height: 1.5; margin: 0; }

/* --- perspective ------------------------------------------------------------------ */
.abt-persp__grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: 2.5rem; align-items: center; }
.abt-persp h2 { margin-bottom: 1.125rem; }
.abt-persp p { font-size: 0.875rem; margin-bottom: 0.75rem; max-width: 32.5rem; color: var(--color-muted); }
.abt-persp__visual { display: flex; align-items: center; align-self: stretch; gap: 1.5rem; }
/* Image grows to the left column's full height (min-height is the floor for
   the stacked/mobile layouts, where there's no sibling to stretch against). */
.abt-blob { position: relative; width: min(19rem, 100%); min-height: 16.75rem; align-self: stretch; flex-shrink: 0; }
.abt-blob::before { content: ""; position: absolute; inset: -0.5rem -0.75rem -0.625rem -0.375rem; border-radius: 48% 40% 46% 42% / 40% 44% 50% 52%; background: linear-gradient(135deg, #f1f2f4, #cfd3da); transform: rotate(-6deg); }
.abt-blob img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 44% 36% 42% 40% / 36% 40% 46% 48%; }
.abt-persp__tags { font-size: 14px; letter-spacing: 0.14em; text-transform: uppercase; font-weight: 600; color: #374151; line-height: 2; }

/* --- contact: shared .cta-band--contact, own background photo only ------------- */
#contact.abt-contact { background: linear-gradient(90deg, rgba(9, 30, 48, 0.85) 0%, rgba(9, 30, 48, 0.5) 45%, rgba(9, 30, 48, 0.1) 100%), var(--color-ink) url("../img/Aboutus/contact-bg.9e2305e44ec4.webp") center / cover no-repeat; }

/* --- responsive -------------------------------------------------------------------- */
@media (max-width: 1100px) {
    .abt-who__grid, .abt-story__grid, .abt-persp__grid { grid-template-columns: 1fr; }
    .abt-cap-grid { grid-template-columns: repeat(3, 1fr); }
    .abt-ap-grid { grid-template-columns: repeat(2, 1fr); }
    .abt-caps__head { flex-direction: column; align-items: flex-start; }
    .abt-hero__tags { right: 1.5rem; bottom: 1.875rem; }
}
@media (max-width: 680px) {
    .abt-hero { min-height: 33.75rem; }
    .abt-hero::before { background: linear-gradient(180deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.8) 55%, rgba(255, 255, 255, 0) 100%); }
    /* The copy column's natural height at this width exceeds the section's
       own min-height, so the absolutely-positioned tag list (anchored to
       the section's own bottom edge) would otherwise sit on top of the CTA
       button -- hidden here, same as other pages' decorative side content
       below their own narrow breakpoints. */
    .abt-hero__tags { display: none; }
    .abt-cap-grid { grid-template-columns: repeat(2, 1fr); }
    .abt-ap-grid { grid-template-columns: 1fr; }
    .abt-timeline { grid-template-columns: 1fr; min-height: auto; gap: 1.875rem; }
    .abt-timeline__path { display: none; }
    .abt-t-item, .abt-t-item--2, .abt-t-item--3 { transform: none; margin: 0; }
    .abt-who__visual { padding-right: 0; }
    .abt-who__card { position: relative; width: auto; margin-top: -2.5rem; margin-left: 1.25rem; }
    .abt-persp__visual { flex-direction: column; align-items: flex-start; }
    .abt-hero__copy h1 { font-size: var(--fs-h1); }
}

/* =============================================================================
   Contact page (.cp-*). Own design system (not reusing .svc-, .cs-, .itc- or
   .abt-), matching the supplied screenshot: a dark navy/orange hero that
   doubles as the enquiry-form section, three info cards, a reused six-card
   solutions grid (same cards/links as the About page, independently scoped
   per that page's own convention), a dark "expertise" band with the globe
   visual, and a closing photo CTA. Background pan/glow-drift animations
   reuse the exact keyframes already shipped for the shared
   .cta-band--contact component (cta-band-bg-pan / cta-band-glow-drift) --
   no new keyframes, no new library, prefers-reduced-motion respected via
   the same site-wide [data-reveal] gate plus its own explicit override
   below. */

/* --- hero + form ------------------------------------------------------------ */
.cp-hero { position: relative; isolation: isolate; overflow: hidden; min-height: 40rem; display: flex; align-items: center; color: #fff; background: var(--color-ink); padding-block: clamp(3rem, 7vw, 5rem); }
.cp-hero__media { position: absolute; inset: -6%; z-index: -2; background: url("../img/Contact/hero_contact.fd5802f845c0.webp") center / cover no-repeat; animation: cta-band-bg-pan 22s ease-in-out infinite alternate; will-change: transform; }
.cp-hero::before { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(100deg, rgba(5, 20, 34, 0.93) 0%, rgba(5, 20, 34, 0.75) 42%, rgba(5, 20, 34, 0.35) 68%, rgba(5, 20, 34, 0.55) 100%); }
.cp-hero::after { content: ""; position: absolute; inset: 0; z-index: -1; background: radial-gradient(45rem 28rem at 15% 15%, rgba(255, 150, 60, 0.28), transparent 55%); animation: cta-band-glow-drift 17s ease-in-out infinite alternate; }
.cp-hero .container { position: relative; }
.cp-hero__grid { display: grid; grid-template-columns: 1.15fr 1fr; gap: 3rem; align-items: start; }
.cp-hero__copy h1 { font-size: var(--fs-h1); line-height: 1.08; letter-spacing: -0.02em; margin-bottom: 1.125rem; }
.cp-hero__copy > p { max-width: 32rem; color: rgba(255, 255, 255, 0.82); margin-bottom: 1.5rem; }
.cp-hero__values { display: flex; align-items: flex-start; gap: 0.875rem; font-size: 14px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; line-height: 2; color: rgba(255, 255, 255, 0.9); }
.cp-hero__values::before { content: ""; width: 2px; align-self: stretch; background: var(--color-accent); flex-shrink: 0; }
.cp-hero__form-col { padding-top: 0.25rem; }
.cp-hero__form { background: #fff; color: var(--color-text); border-radius: 1rem; padding: 1.75rem; box-shadow: 0 30px 60px -20px rgba(0, 0, 0, 0.5); }
.cp-hero__form h3 { font-size: var(--fs-h3); font-weight: 700; margin-bottom: 0.375rem; color: var(--color-ink); }
.cp-hero__form .meta { font-size: 14px; margin-bottom: 1.125rem; }
.cp-hero__form .form-label { font-size: 14px; font-weight: 600; }

/* --- intro + info cards ------------------------------------------------------ */
/* Own section, own (plain, light) background -- a distinct colour plus a
   compact, content-sized padding (not the full .section clamp) is what
   actually separates this from "How Can We Help?" below; that section's
   own background/decoration is untouched. */
.cp-intro { position: relative; overflow: hidden; background: #fdf8f3; padding-block: var(--space-section); }
/* Globe art as a section-wide backdrop (not a boxed column image): pinned to
   the right edge and faded into the section's own background colour on the
   left via a mask, so it reads as one continuous surface behind the copy
   rather than a separate picture. Clipped by .cp-intro's own overflow:hidden,
   so it never bleeds past this section into "How Can We Help?" below. */
.cp-intro::before { content: ""; position: absolute; inset: 0; z-index: 0; background: url("../img/Contact/help.3914cbbd68f3.webp") right center / contain no-repeat; -webkit-mask-image: linear-gradient(to right, transparent 0%, transparent 30%, #000 60%); mask-image: linear-gradient(to right, transparent 0%, transparent 30%, #000 60%); }
.cp-intro .container { position: relative; z-index: 1; }
.cp-intro__grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: 2.5rem; align-items: center; }
.cp-intro__copy { max-width: 34rem; text-align: left; }
.cp-intro__copy .lead { font-size: 0.9375rem; color: var(--color-muted); margin-top: 0.75rem; margin-bottom: 0; }
/* The visual column itself now carries no image -- it only reserves the same
   grid-column width it always did, so the layout/spacing is unchanged while
   the globe (painted by .cp-intro::before above) shows through naturally. */
.cp-intro__visual { width: 100%; }
.cp-info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 1.75rem; }
.cp-info-card--wide { grid-column: 1 / -1; }
.cp-info-card { display: flex; align-items: center; gap: 1rem; background: #fff; border: 1px solid #f1e8dc; border-radius: 0.875rem; padding: 1.125rem 1.25rem; box-shadow: 0 10px 25px -16px rgba(11, 26, 46, 0.2); }
.cp-info-card__icon { display: flex; align-items: center; justify-content: center; flex-shrink: 0; width: 2.75rem; height: 2.75rem; border-radius: 50%; background: var(--color-accent); color: #fff; }
.cp-info-card__icon svg { width: 1.25rem; height: 1.25rem; }
.cp-info-card__body { display: flex; flex-direction: column; gap: 0.125rem; flex: 1 1 auto; min-width: 0; }
.cp-info-card__label { font-size: 0.875rem; font-weight: 700; color: var(--color-ink); }
.cp-info-card__body a { color: var(--color-muted); font-size: 14px; text-decoration: none; }
.cp-info-card__body a:hover { color: var(--color-accent); }
.cp-info-card__arrow { color: var(--color-accent); flex-shrink: 0; }

/* --- six-card solutions grid (independently scoped from the About page's) ---
   Warm ivory base plus two purely decorative layers behind the content
   (flowing gradient-stroke lines reusing the same inline-SVG-with-
   linearGradient technique as .abt-approach__glow/.cp-hero::after, and a
   faint dot-grid via a tiled radial-gradient background -- no new asset,
   no new technique). */
.cp-caps { position: relative; background: #fdf8f3; overflow: hidden; }
.cp-caps::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: radial-gradient(rgba(255, 101, 11, 0.16) 1px, transparent 1.5px);
    background-size: 22px 22px;
    background-position: 4% 12%, 92% 70%;
    -webkit-mask-image: radial-gradient(ellipse 60% 70% at 10% 20%, #000 0%, transparent 60%), radial-gradient(ellipse 55% 65% at 92% 80%, #000 0%, transparent 60%);
    mask-image: radial-gradient(ellipse 60% 70% at 10% 20%, #000 0%, transparent 60%), radial-gradient(ellipse 55% 65% at 92% 80%, #000 0%, transparent 60%);
    pointer-events: none;
}
.cp-caps__lines { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.cp-caps > .container { position: relative; z-index: 1; }
.cp-caps__head { position: relative; max-width: 38rem; text-align: center; margin: 0 auto 2rem; }
.cp-caps__head p { font-size: 0.875rem; color: var(--color-muted); margin: 0.5rem 0 0; }
/* Zigzag accent replacing the usual straight .eyebrow--rule dash. The line
   itself (.cp-caps__zigzag-base) is always fully drawn and never moves --
   only a short "light" segment travels along a second, identical path
   (.cp-caps__zigzag-glow) laid on top of it, via an animated
   stroke-dashoffset loop (dash+gap length matches the path's own length,
   so the loop has no visible seam). Starts only once the section's
   existing [data-reveal] (.cp-caps__head) gets its .is-visible class from
   the sitewide IntersectionObserver-based observeReveals() in app.js --
   reused as-is, no new JS -- and since that observer unobserves an element
   the moment it's first revealed (never toggling back off), the loop
   can't restart or flicker on later small scrolls; it simply keeps
   running once started. Reduced-motion gets the plain static orange line
   only (the glow overlay is hidden), same progressive-enhancement
   convention as the rest of the site. */
.cp-caps__zigzag { display: block; width: 4rem; height: 0.625rem; margin: 0.5rem auto 0; overflow: visible; }
.cp-caps__zigzag path { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.cp-caps__zigzag-base { stroke: var(--color-accent); stroke-width: 1.5; }
.cp-caps__zigzag-glow { stroke: #fff; stroke-width: 1.5; opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
    .cp-caps__zigzag-glow { stroke-dasharray: 14 56; }
    .cp-caps__head.is-visible .cp-caps__zigzag-glow { opacity: 0.85; animation: cp-zigzag-glow 2.4s linear infinite; }
}
@keyframes cp-zigzag-glow {
    to { stroke-dashoffset: -70; }
}
.cp-cap-grid { position: relative; display: grid; grid-template-columns: repeat(6, 1fr); gap: 1rem; }
.cp-cap { display: block; color: inherit; text-decoration: none; background: #fff; border-radius: 0.75rem; padding: 1.625rem 1rem 1.5rem; text-align: center; box-shadow: 0 10px 30px -14px rgba(11, 26, 46, 0.25); border: 1px solid #f1f2f5; transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease), border-color 0.2s var(--ease); }
/* Hover AND keyboard focus share the same highlight (same convention as
   .tr-track-card elsewhere) -- purely presentational state, not tied to
   any card being "selected"/active by default, so it moves freely between
   cards and never sticks to one. The sitewide :focus-visible outline
   (site.css:725) still applies on top of this, unsuppressed. */
.cp-cap:hover, .cp-cap:focus-visible { transform: translateY(-4px); border-color: var(--color-accent); box-shadow: 0 0 0 1px var(--color-accent), 0 18px 34px -14px rgba(255, 101, 11, 0.45); color: inherit; }
.cp-cap__icon { display: flex; align-items: center; justify-content: center; width: 3.25rem; height: 3.25rem; margin: 0 auto 1.125rem; border-radius: 50%; background: #fdeadb; }
.cp-cap__icon svg { width: 1.5rem; height: 1.5rem; color: var(--color-accent); }
.cp-cap h3 { font-size: 0.875rem; font-weight: 700; line-height: 1.35; margin: 0; color: var(--color-ink); }
.cp-cap p { font-size: 14px; line-height: 1.45; color: var(--color-muted); margin: 0.5rem 0 0; }
.cp-cap__arrow { display: flex; align-items: center; justify-content: center; width: 2rem; height: 2rem; margin: 1rem auto 0; border-radius: 50%; background: #fdeadb; color: var(--color-accent); font-size: 0.9375rem; transition: background-color 0.2s var(--ease), color 0.2s var(--ease); }
.cp-cap:hover .cp-cap__arrow, .cp-cap:focus-visible .cp-cap__arrow { background: var(--color-accent); color: #fff; }

/* --- start a conversation CTA -------------------------------------------------- */
/* Now the page's closing band (the dark "Why Contact Valin" section above it
   was removed), so it takes the extra height itself: taller, with the copy
   vertically centred and more generous padding. */
.cp-cta { position: relative; isolation: isolate; overflow: hidden; color: #fff; display: flex; align-items: center; min-height: 32rem; padding: var(--space-section-sm) 0; }
.cp-cta > .container { width: 100%; }
.cp-cta__media { position: absolute; inset: 0; z-index: -2; }
.cp-cta__media img { width: 100%; height: 100%; object-fit: cover; object-position: center 35%; }
.cp-cta::after { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(100deg, rgba(5, 20, 34, 0.88) 0%, rgba(5, 20, 34, 0.55) 50%, rgba(5, 20, 34, 0.3) 100%); }
.cp-cta__copy { max-width: 34rem; }
.cp-cta__copy h2 { color: #fff; margin-bottom: 1rem; }
.cp-cta__copy p { color: rgba(255, 255, 255, 0.85); font-size: 0.9375rem; margin-bottom: 1.5rem; }
.cp-cta__btn { background: linear-gradient(90deg, var(--color-accent), var(--color-accent-dark)); color: #fff; border: 0; }

/* --- wave helpers (scoped copy of the About page's own helper) --------------- */
.cp-wave { display: block; width: 100%; height: 3.125rem; position: absolute; left: 0; z-index: 1; }
.cp-wave--top { top: -1px; }
.cp-wave--bottom { bottom: -1px; z-index: 2; }

@media (prefers-reduced-motion: reduce) {
    .cp-hero__media, .cp-hero::after { animation: none; }
}

/* --- responsive ---------------------------------------------------------------- */
@media (max-width: 1100px) {
    .cp-hero__grid, .cp-intro__grid { grid-template-columns: 1fr; }
    .cp-hero__form-col { max-width: 32rem; }
    /* Below the two-column layout the backdrop has no second column to sit
       behind, so it would otherwise show through right behind the stacked
       copy/cards instead of being "naturally visible on the right" -- off
       here, same as the image having no mobile treatment before. */
    .cp-intro::before { display: none; }
    .cp-intro__copy { max-width: none; }
    .cp-intro__visual { order: -1; max-width: 26rem; margin-inline: auto; }
    .cp-cap-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 680px) {
    .cp-hero { min-height: auto; }
    .cp-cta { min-height: 24rem; padding: var(--space-section-sm) 0; }
    .cp-info-grid { grid-template-columns: 1fr; }
    .cp-info-card--wide { grid-column: auto; }
    .cp-cap-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ============================================================================
   Enquiry-form dropdowns: one arrow everywhere. Same chevron as Home's
   "What do you need help with?" select (12px, 0.75rem from the right edge,
   vertically centred); white on the dark/glass forms, dark on the light ones.
   The pages' own field rules use the `background:` shorthand (which wipes
   Bootstrap's chevron, and does so again on :focus), so the arrow is re-supplied
   here as background-image only, with the right padding that keeps it clear of
   the selected text. Placed last so it follows those rules. */
:root {
    --select-chevron-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E");
    --select-chevron-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3E%3C/svg%3E");
}
.itc-contact-form .form-select,
.itc-contact-form .form-select:focus,
#abt-contact-regarding,
#abt-contact-regarding:focus {
    background-image: var(--select-chevron-light);
    background-repeat: no-repeat;
    background-position: right 0.75rem center;
    background-size: 12px 12px;
    padding-right: 2.25rem;
}
#contact.dm-contact .contact-form .form-select,
#contact.dm-contact .contact-form .form-select:focus,
.cs-contact-form .form-select,
.cs-contact-form .form-select:focus,
#ct-contact-type {
    background-image: var(--select-chevron-dark);
    background-repeat: no-repeat;
    background-position: right 0.75rem center;
    background-size: 12px 12px;
    padding-right: 2.25rem;
}
/* About's select was the odd one out: Bootstrap's 16px text and padding next to 13px fields, so it rendered shorter
   with larger text. Same size / padding / height as its sibling inputs (which go to 16px under 680px). */
#abt-contact-regarding { font-size: 14px; min-height: 43px; padding-block: 12px; padding-left: 12px; }
@media (max-width: 680px) { #abt-contact-regarding { font-size: 16px; min-height: 46px; } }



/* --- inner page hero (templates/partials/page_hero.html) --------------------
   One layout for the four service pages, Training, About and Contact: copy on
   the left (heading, intro, up to two buttons), the page's media on the right,
   stacked under the copy below 992px. Same height, padding and left
   alignment everywhere; visible on first paint (no reveal). Media fits:
     --cover  the image cropped into a 4:3 frame
     --art    the image at its own proportions, so its traced animation
              overlay (.svc-hero__fx / .itc-hero__fx) stays on the drawing
     --form   the Contact page's enquiry form */
.page-hero { position: relative; background: #FAF8F3; padding-block: var(--space-section-sm); overflow: hidden; }
.page-hero__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; gap: 64px; min-height: 520px; }
.page-hero__copy { max-width: 560px; }
body .page-hero__title { margin: 0; color: #091E30; font-size: var(--fs-h1); line-height: 1.08; letter-spacing: -0.025em; }
.page-hero__intro { margin: 24px 0 0; max-width: 52ch; color: #3E4D57; font-size: var(--fs-body); line-height: 1.6; }
.page-hero__intro--more { margin-top: 12px; }
.page-hero__actions { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 36px; }
.page-hero__copy .cp-hero__values { margin-top: 28px; color: #091E30; }
/* The media is part of the section, not a framed photo: no card, radius or
   shadow. "bleed" fills the whole hero; "cover" fills the right half to the
   page edge with a soft fade into the ivory on its left; "art" keeps its
   proportions and feathers out at the edges. */
.page-hero__media { position: relative; overflow: hidden; }
.page-hero__media--bleed,
.page-hero__media--cover { position: absolute; top: 0; bottom: 0; right: 0; z-index: 0; }
.page-hero__media--bleed { left: 0; }
.page-hero__media--cover { left: 46%; -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 28%); mask-image: linear-gradient(90deg, transparent 0%, #000 28%); }
.page-hero__media--bleed > img,
.page-hero__media--cover > img { display: block; width: 100%; height: 100%; object-fit: cover; }
.page-hero__media--art { -webkit-mask-image: radial-gradient(ellipse 62% 64% at 50% 50%, #000 60%, transparent 100%); mask-image: radial-gradient(ellipse 62% 64% at 50% 50%, #000 60%, transparent 100%); }
.page-hero__media--art > img { display: block; width: 100%; height: auto; }
.page-hero__copy { position: relative; z-index: 1; }
/* full-bleed photo: a gentle ivory wash behind the copy keeps the heading crisp */
.page-hero:has(.page-hero__media--bleed)::before { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; background: linear-gradient(90deg, rgba(250, 248, 243, 0.85) 0%, rgba(250, 248, 243, 0.55) 32%, rgba(250, 248, 243, 0) 52%); }
.page-hero:has(.page-hero__media--cover) .page-hero__grid { min-height: 560px; }
/* full-bleed photo: the hero takes the photo's own proportions (1024x430) so
   the photo shows whole instead of being zoomed in to fill a taller box; it
   only grows taller (and crops slightly) if the copy needs more room. */
@media (min-width: 992px) {
    .page-hero:has(.page-hero__media--bleed) { display: flex; align-items: center; aspect-ratio: 1024 / 430; }
    .page-hero:has(.page-hero__media--bleed) .page-hero__grid { min-height: 0; width: 100%; }
}
.page-hero__media--art .svc-hero__fx,
.page-hero__media--art .itc-hero__fx { position: absolute; inset: 0; width: 100%; height: 100%; }
.page-hero__media--form { overflow: visible; border-radius: 0; }
.page-hero__media .abt-hero__tags { right: 24px; bottom: 24px; }
@media (max-width: 991.98px) {
    .page-hero__grid { grid-template-columns: minmax(0, 1fr); gap: 40px; min-height: 0; }
    .page-hero:has(.page-hero__media--bleed) .page-hero__grid,
    .page-hero:has(.page-hero__media--cover) .page-hero__grid { min-height: 0; }
    .page-hero__copy { max-width: none; }
    /* stacked: the image runs edge to edge under the copy */
    .page-hero { padding-bottom: 0; }
    .page-hero__media--bleed,
    .page-hero__media--cover { position: relative; inset: auto; margin-inline: -24px; aspect-ratio: 4 / 3; -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 18%); mask-image: linear-gradient(180deg, transparent 0%, #000 18%); }
    .page-hero:has(.page-hero__media--bleed)::before { content: none; }
    .page-hero__media--art,
    .page-hero__media--form { margin-bottom: var(--space-section-sm); }
}
@media (max-width: 575.98px) {
    .page-hero__actions .btn { width: 100%; justify-content: center; }
}

/* --- data & marketing banner hero ---------------------------------------------
   fit="bleed": hero-banner.webp (2000x783, scene on the right, plain ivory
   on the left for the copy) fills the hero. On load the photo fades in and
   the heading and button rise in; the photo itself then stays still (no
   drift, so it is never resampled and stays sharp). A "live data" sequence
   is traced onto it in a 2000x783 stage (.wd-screens, scaled by app.js like
   the web dev hero), one step at a time on a 12s loop:
     0-2.4s   the laptop's trend line draws itself along its path, tip pings
     2.8-6.3s the map pins light up one by one, like typing
     6.6-10.6s a highlight steps down the Team Performance rows
   All of it is behind prefers-reduced-motion: no-preference. */
.page-hero--data-marketing .page-hero__media--bleed > img { object-position: 100% 50%; filter: saturate(0.88); }
/* Zoomed out from 992px: the whole banner layer (photo + its traced
   overlay, so they stay aligned) is scaled down towards its right edge and
   its top/bottom edges fade into the section's ivory, so the scene sits in
   the frame instead of filling it edge to edge. */
@media (min-width: 992px) {
    .page-hero--data-marketing .page-hero__media--bleed {
        transform: scale(0.86);
        transform-origin: 100% 55%;
        -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 9%, #000 91%, transparent 100%), linear-gradient(90deg, transparent 0%, #000 14%);
        -webkit-mask-composite: source-in;
        mask-image: linear-gradient(180deg, transparent 0%, #000 9%, #000 91%, transparent 100%), linear-gradient(90deg, transparent 0%, #000 14%);
        mask-composite: intersect;
    }
}
/* The banner's floating panels start ~40% across, so from 992px the heading
   is kept to a narrower column (and a touch smaller) to wrap before them. */
@media (min-width: 992px) {
    .page-hero--data-marketing .page-hero__copy { max-width: 25rem; }
    body .page-hero--data-marketing .page-hero__title { font-size: clamp(38px, 3.5vw, 54px); }
}
.wd-screens__stage.dm-hero__stage { width: 2000px; height: 783px; }
.dm-hero__stage svg { display: block; width: 100%; height: 100%; overflow: visible; }
.dm-hero__fx { display: none; }
@media (max-width: 991.98px) {
    .page-hero--data-marketing .page-hero__media--bleed { aspect-ratio: 16 / 10; }
}
@media (prefers-reduced-motion: no-preference) {
    .dm-hero__fx { display: block; }
    .page-hero--data-marketing .page-hero__media--bleed { animation: dm-hero-in 1.4s ease-out both; }
    .page-hero--data-marketing .page-hero__title { animation: dm-hero-rise 0.9s cubic-bezier(0.22, 0.7, 0.2, 1) 0.15s both; }
    .page-hero--data-marketing .page-hero__actions { animation: dm-hero-rise 0.9s cubic-bezier(0.22, 0.7, 0.2, 1) 0.45s both; }

    .dm-trend { fill: none; stroke: #FFC27A; stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; filter: drop-shadow(0 0 6px rgba(255, 140, 40, 0.95)); animation: dm-trend-draw 12s ease-in-out 1.6s infinite; }
    .dm-ring { fill: none; stroke: #FFB066; stroke-width: 2; transform-box: fill-box; transform-origin: center; opacity: 0; animation: dm-ping 12s ease-out 4s infinite; }
    .dm-ring--late { animation-delay: 4.35s; }
    .dm-pin { opacity: 0; transform-box: fill-box; transform-origin: center; animation: dm-pin-on 12s ease-out infinite; }
    .dm-pin:nth-child(1) { animation-delay: 4.4s; }
    .dm-pin:nth-child(2) { animation-delay: 4.75s; }
    .dm-pin:nth-child(3) { animation-delay: 5.1s; }
    .dm-pin:nth-child(4) { animation-delay: 5.45s; }
    .dm-pin:nth-child(5) { animation-delay: 5.8s; }
    .dm-pin:nth-child(6) { animation-delay: 6.15s; }
    .dm-pin:nth-child(7) { animation-delay: 6.5s; }
    .dm-pin:nth-child(8) { animation-delay: 6.85s; }
    .dm-pin:nth-child(9) { animation-delay: 7.2s; }
    .dm-pin:nth-child(10) { animation-delay: 7.55s; }
    .dm-row { fill: rgba(255, 140, 50, 0.26); stroke: rgba(255, 110, 20, 0.85); stroke-width: 2; opacity: 0; animation: dm-row-on 12s ease-in-out infinite; }
    .dm-row:nth-child(1) { animation-delay: 8.2s; }
    .dm-row:nth-child(2) { animation-delay: 9s; }
    .dm-row:nth-child(3) { animation-delay: 9.8s; }
    .dm-row:nth-child(4) { animation-delay: 10.6s; }
    .dm-row:nth-child(5) { animation-delay: 11.4s; }
}
@keyframes dm-hero-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes dm-hero-rise {
    from { opacity: 0; transform: translateY(26px); filter: blur(6px); }
    to { opacity: 1; transform: none; filter: none; }
}
/* 12s cycles; each element's own delay places it in the sequence. */
@keyframes dm-trend-draw {
    0% { stroke-dashoffset: 1; opacity: 1; }
    20% { stroke-dashoffset: 0; opacity: 1; }
    80% { stroke-dashoffset: 0; opacity: 1; }
    88%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes dm-ping {
    0% { opacity: 0.9; transform: scale(0.6); }
    9%, 100% { opacity: 0; transform: scale(2.8); }
}
@keyframes dm-pin-on {
    0% { opacity: 0; transform: scale(0.3); }
    3% { opacity: 1; transform: scale(1.35); }
    6% { opacity: 0.9; transform: scale(1); }
    55% { opacity: 0.9; transform: scale(1); }
    62%, 100% { opacity: 0; transform: scale(1); }
}
@keyframes dm-row-on {
    0% { opacity: 0; }
    2% { opacity: 1; }
    6.5% { opacity: 1; }
    8.5%, 100% { opacity: 0; }
}

/* --- dm-page serif headings ------------------------------------------------------
   Data & Marketing page only (body.dm-page): every section heading (h2) in
   the editorial serif from the "Useful AI" design; card and item titles
   (h3/h4) and the hero h1 stay in Inter. ID-scoped h2 rules elsewhere only
   set size/colour, so this class+element selector is enough. */
body.dm-page main h2 { font-family: var(--font-serif); font-weight: 600; letter-spacing: -0.015em; line-height: 1.1; }

/* --- #faq.dm-faq: patterns + motion -----------------------------------------------
   Patterns: a fine dot grid fading in behind the accordion panel, two large
   faint concentric rings (the outer one dashed, turning very slowly) at the
   panel's bottom right, and an orange-to-clear hairline along the panel's
   top edge. Motion: items lift and warm on hover; opening one grows an
   orange bar down its left edge, spins the +/- toggle a quarter turn and
   fades/slides the answer in. Static under reduced motion. */
#faq.dm-faq::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-image: radial-gradient(rgba(190, 120, 60, 0.18) 1px, transparent 1.2px);
    background-size: 24px 24px;
    -webkit-mask-image: radial-gradient(ellipse 45% 60% at 72% 45%, #000 0%, transparent 75%);
    mask-image: radial-gradient(ellipse 45% 60% at 72% 45%, #000 0%, transparent 75%);
}
#faq.dm-faq::after {
    content: "";
    position: absolute;
    z-index: 0;
    right: -14vw;
    bottom: -22vw;
    width: 46vw;
    height: 46vw;
    border-radius: 50%;
    border: 1px dashed rgba(255, 101, 11, 0.25);
    outline: 1px solid rgba(255, 101, 11, 0.12);
    outline-offset: 5vw;
    pointer-events: none;
}
.dm-faq__panel { position: relative; }
/* The FAQ heading uses the editorial serif on every page that uses this design
   (the Data & Marketing page gets it from body.dm-page too). */
#faq.dm-faq h2 { font-family: var(--font-serif); font-weight: 600; letter-spacing: -0.015em; line-height: 1.1; }
/* Type and colour, shared by both FAQ pages: the heading's second line in
   orange, a regular-weight intro, serif question numbers, 17px questions and
   15px answers in a readable slate. */
#faq.dm-faq h2 { font-size: clamp(32px, 3vw, 44px); color: var(--color-ink); }
#faq.dm-faq h2 span { color: var(--color-accent); }
#faq.dm-faq .lead { margin-top: 18px; font-size: 17px; font-weight: 400; line-height: 1.65; color: #4A5A68; }
#faq.dm-faq .svc-faq-item summary { font-size: 17px; font-weight: 600; line-height: 1.45; color: var(--color-ink); }
#faq.dm-faq .svc-faq-item__no { font-family: var(--font-serif); font-size: 24px; font-weight: 600; letter-spacing: 0; }
#faq.dm-faq .svc-faq-item:not([open]) .svc-faq-item__no { color: #B7C0C8; }
#faq.dm-faq .svc-faq-item p { font-size: 15px; line-height: 1.7; color: #4A5A68; }
@media (max-width: 991.98px) {
    #faq.dm-faq .svc-faq-item summary { font-size: 15px; }
    #faq.dm-faq .svc-faq-item__no { font-size: 20px; }
    #faq.dm-faq .svc-faq-item p { font-size: 14.5px; }
}
.dm-faq__panel::before {
    content: "";
    position: absolute;
    left: 1.75rem;
    right: 1.75rem;
    top: 0;
    height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--color-accent), rgba(255, 101, 11, 0));
}
#faq.dm-faq .svc-faq-item { position: relative; overflow: hidden; transition: transform 0.3s var(--ease), border-color 0.3s var(--ease), box-shadow 0.3s var(--ease), background-color 0.3s var(--ease); }
#faq.dm-faq .svc-faq-item::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: linear-gradient(180deg, var(--color-accent), #FFB066);
    transform: scaleY(0);
    transform-origin: top;
    transition: transform 0.45s var(--ease);
}
#faq.dm-faq .svc-faq-item[open]::before { transform: scaleY(1); }
#faq.dm-faq .svc-faq-item[open] { box-shadow: 0 16px 32px -22px rgba(200, 90, 20, 0.45); }
#faq.dm-faq .svc-faq-item__no { transition: color 0.3s var(--ease); }
#faq.dm-faq .svc-faq-item__toggle::before { display: inline-block; transition: transform 0.35s var(--ease); }
#faq.dm-faq .svc-faq-item[open] .svc-faq-item__toggle::before { transform: rotate(180deg); }
@media (hover: hover) and (pointer: fine) {
    #faq.dm-faq .svc-faq-item:not([open]):hover { transform: translateY(-2px); border-color: #F3C7A6; box-shadow: 0 12px 26px -20px rgba(150, 80, 30, 0.4); }
    #faq.dm-faq .svc-faq-item:not([open]):hover .svc-faq-item__toggle { border-color: var(--color-accent); color: var(--color-accent); }
}
@media (prefers-reduced-motion: no-preference) {
    #faq.dm-faq::after { animation: dm-faq-turn 90s linear infinite; }
    #faq.dm-faq .svc-faq-item[open] > p { animation: dm-faq-answer 0.45s var(--ease) both; }
}
@keyframes dm-faq-turn { to { rotate: 360deg; } }
@keyframes dm-faq-answer {
    from { opacity: 0; transform: translateY(-6px); }
    to { opacity: 1; transform: none; }
}
@media (max-width: 991.98px) {
    #faq.dm-faq::after { width: 80vw; height: 80vw; right: -40vw; bottom: -40vw; }
}

/* --- managed IT banner hero ----------------------------------------------------------
   fit="bleed": hero-banner.webp (2048x840, a calm real-looking desk with a
   router, a drive and a laptop on the right, plain wall on the left) fills
   the hero. The technology feel comes from restrained effects traced onto the
   actual hardware in a 2048x840 stage (.wd-screens, scaled by app.js like the
   other banner heroes), not from the picture: status lights flicker like live
   hardware, packets run along the real cables (router -> drive -> laptop),
   the laptop's chart redraws and its status dot pulses. Over the empty wall
   a fine engineering grid fades in behind the copy. The photo stays still.
   All motion is behind prefers-reduced-motion: no-preference. */
.page-hero--managed-it-cloud .page-hero__media--bleed > img { object-position: 100% 50%; }
.page-hero--managed-it-cloud::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-image:
        linear-gradient(rgba(9, 30, 48, 0.085) 1px, transparent 1px),
        linear-gradient(90deg, rgba(9, 30, 48, 0.085) 1px, transparent 1px);
    background-size: 44px 44px;
    -webkit-mask-image: radial-gradient(ellipse 45% 75% at 22% 50%, #000 0%, transparent 72%);
    mask-image: radial-gradient(ellipse 45% 75% at 22% 50%, #000 0%, transparent 72%);
}
.wd-screens__stage.itc-bh__stage { width: 2048px; height: 840px; }
.itc-bh__stage svg { display: block; width: 100%; height: 100%; overflow: visible; }
.itc-bh__fx { display: none; }
@media (max-width: 991.98px) {
    .page-hero--managed-it-cloud .page-hero__media--bleed { aspect-ratio: 16 / 10; }
    .page-hero--managed-it-cloud::after { display: none; }
}
@media (prefers-reduced-motion: no-preference) {
    .itc-bh__fx { display: block; }
    .page-hero--managed-it-cloud .page-hero__media--bleed { animation: itc-bh-in 1.4s ease-out both; }
    .page-hero--managed-it-cloud .page-hero__title { animation: itc-bh-rise 0.9s cubic-bezier(0.22, 0.7, 0.2, 1) 0.15s both; }
    .page-hero--managed-it-cloud .page-hero__actions { animation: itc-bh-rise 0.9s cubic-bezier(0.22, 0.7, 0.2, 1) 0.45s both; }
    .page-hero--managed-it-cloud::after { animation: itc-bh-in 2.4s ease-out 0.6s both; }

    /* status lights: irregular flicker, each on its own rhythm */
    .itc-bh__led { opacity: 0.25; mix-blend-mode: screen; animation: itc-bh-led 1.9s steps(1, end) infinite; }
    .itc-bh__led:nth-child(2) { animation-duration: 0.9s; animation-delay: -0.3s; }
    .itc-bh__led:nth-child(3) { animation-duration: 1.3s; animation-delay: -0.8s; }
    .itc-bh__led:nth-child(4) { animation-duration: 0.7s; animation-delay: -0.1s; }
    .itc-bh__led:nth-child(5) { animation-duration: 2.3s; animation-delay: -1.2s; }
    .itc-bh__led:nth-child(6) { animation-duration: 2.8s; animation-delay: -0.5s; }
    .itc-bh__led:nth-child(7) { animation-duration: 1.1s; animation-delay: -0.9s; }
    .itc-bh__led:nth-child(8) { animation-duration: 1.6s; animation-delay: -1.4s; }

    /* data links on the real cables; a packet runs router -> drive, then drive -> laptop */
    .itc-bh__link { fill: none; stroke: rgba(255, 140, 60, 0.28); stroke-width: 2.5; stroke-linecap: round; }
    .itc-bh__packet { fill: none; stroke: #FFD9AE; stroke-width: 4; stroke-linecap: round; stroke-dasharray: 0.12 1; stroke-dashoffset: 0.12; opacity: 0; filter: drop-shadow(0 0 5px rgba(255, 140, 40, 0.95)); animation: itc-bh-packet 3.2s ease-in-out 1.5s infinite; }
    .itc-bh__packet--2 { animation-delay: 2.5s; }

    /* laptop: the chart line redraws every 6s; the app's status dot pulses */
    .itc-bh__chart { fill: none; stroke: #FFB066; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; filter: drop-shadow(0 0 4px rgba(255, 140, 40, 0.8)); animation: itc-bh-chart 6s ease-in-out 2s infinite; }
    .itc-bh__status { fill: none; stroke: #FFB066; stroke-width: 2; transform-box: fill-box; transform-origin: center; animation: itc-bh-ping 2.4s ease-out 1s infinite; }
}
.itc-bh__link, .itc-bh__packet, .itc-bh__chart, .itc-bh__status { fill: none; }
@keyframes itc-bh-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes itc-bh-rise {
    from { opacity: 0; transform: translateY(26px); filter: blur(6px); }
    to { opacity: 1; transform: none; filter: none; }
}
@keyframes itc-bh-led {
    0% { opacity: 0.25; }
    18% { opacity: 1; }
    33% { opacity: 0.4; }
    52% { opacity: 0.95; }
    71% { opacity: 0.3; }
    86% { opacity: 0.85; }
}
@keyframes itc-bh-packet {
    0% { stroke-dashoffset: 0.12; opacity: 0; }
    8% { opacity: 1; }
    30% { stroke-dashoffset: -0.88; opacity: 1; }
    34%, 100% { stroke-dashoffset: -0.88; opacity: 0; }
}
@keyframes itc-bh-chart {
    0% { stroke-dashoffset: 1; opacity: 1; }
    35% { stroke-dashoffset: 0; opacity: 1; }
    80% { stroke-dashoffset: 0; opacity: 1; }
    92%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes itc-bh-ping {
    0% { opacity: 0.9; transform: scale(0.6); }
    60%, 100% { opacity: 0; transform: scale(2.6); }
}

/* --- data & marketing hero headline ------------------------------------------------
   One tight, consistent block: the two
   statements in the same Inter weight and size, each breaking before its
   keyword, the keywords in orange. The statements rise in one after the other. */
.page-hero__eyebrow { display: inline-flex; align-items: center; gap: 14px; margin-bottom: 18px; font-size: 13px; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-accent); }
body .page-hero--data-marketing .page-hero__title { position: relative; font-size: clamp(36px, 3.3vw, 48px); line-height: 1.08; letter-spacing: -0.03em; }
.page-hero--data-marketing .page-hero__actions { margin-top: 48px; }
.page-hero--data-marketing .dm-ht__pair { display: block; }
.page-hero--data-marketing .dm-ht__pair + .dm-ht__pair { margin-top: 0.3em; }
.page-hero--data-marketing .dm-ht__word { display: block; color: var(--color-accent); }
@media (min-width: 992px) {
    .page-hero--data-marketing .page-hero__copy { max-width: 31rem; }
}
@media (prefers-reduced-motion: no-preference) {
    .page-hero--data-marketing .page-hero__title { animation: none; }
    .page-hero--data-marketing .dm-ht__pair { animation: dm-hero-rise 0.9s cubic-bezier(0.22, 0.7, 0.2, 1) 0.2s both; }
    .page-hero--data-marketing .dm-ht__pair + .dm-ht__pair { animation-delay: 0.42s; }
}
@media (max-width: 575.98px) {
    body .page-hero--data-marketing .page-hero__title { font-size: 34px; }
    .page-hero__eyebrow { font-size: 12px; letter-spacing: 0.1em; }
}

/* --- "One Environment Managed as a Whole": refinement --------------------------------
   Same pattern, tidier: from 1101px every card is the same height with its
   title, text and icon on one grid; the arcs are thinner and the ripple rings
   fainter, so the cards lead; the number badges are slightly smaller with a
   white ring; cards are plain white with one soft shadow and a hairline
   border, and lift evenly on hover. The closing line gets an orange rule. */
@media (min-width: 1101px) {
    .itc-card {
        display: flex;
        flex-direction: column;
        min-height: 15.7cqw;
        padding: 1.4cqw 1.3cqw 1.3cqw 3.2cqw;
        background: #FFFFFF;
        border: 1px solid rgba(9, 30, 48, 0.08);
        box-shadow: 0 1.6cqw 3cqw -1.6cqw rgba(9, 30, 48, 0.28);
    }
    .itc-card__head { align-items: flex-start; margin-bottom: 0.7cqw; }
    .itc-card__icon { color: #8193A3; margin-top: 0.2cqw; }
    .itc-card__badge { width: 3.2cqw; height: 3.2cqw; left: -1.6cqw; top: 1.4cqw; border: 0.22cqw solid #FFFFFF; box-shadow: 0 0.5cqw 1.2cqw -0.3cqw rgba(255, 106, 19, 0.55); font-size: clamp(13px, 1.2cqw, 16px); }
    .itc-ring { border-width: 0.42cqw; }
    .itc-flow { margin-bottom: 3.5cqw; }
    .itc-flow__ripples circle { opacity: 0.16; }
}
@media (min-width: 1101px) and (hover: hover) and (pointer: fine) {
    .itc-card:hover { transform: translateY(-5px); box-shadow: 0 2.2cqw 3.6cqw -1.6cqw rgba(9, 30, 48, 0.32); }
}
/* closing line: a puzzle-piece chip ("fit") with a soft ping, instead of a dash */
.itc-closing--light { position: relative; padding-left: 62px; min-height: 46px; display: flex; flex-wrap: wrap; align-items: center; column-gap: 0.28em; }
.itc-closing__icon { position: absolute; left: 0; top: 50%; translate: 0 -50%; display: grid; place-items: center; width: 46px; height: 46px; border-radius: 14px; background: #FFF0E5; color: var(--color-accent); border: 1px solid rgba(255, 101, 11, 0.22); }
.itc-closing__icon svg { width: 23px; height: 23px; }
@media (prefers-reduced-motion: no-preference) {
    .itc-closing__icon::after { content: ""; position: absolute; inset: -1px; border-radius: 14px; border: 1.5px solid rgba(255, 101, 11, 0.45); animation: itc-issue-ping 3.2s ease-out infinite; }
    .itc-closing__icon svg { animation: itc-closing-fit 3.2s ease-in-out infinite; }
}
@keyframes itc-closing-fit { 0%, 100% { translate: 0 0; } 40% { translate: 3px -3px; } 55% { translate: 0 0; } }

/* --- training hero (dark scroll hero, after halo-lab.com) ---------------------------
   A deep navy starfield banner. On desktop the section is taller than the
   screen and its stage is sticky, so scrolling plays a short scene (app.js
   "training hero" sets the orb's position and .is-flipped on the cards): a
   glowing orb drops from above the heading to the row of six tech cards and
   travels across them, each card turning from its back (Valin mark) to its
   front (icon + name) as the orb reaches it; scrolling back reverses it.
   Phones / reduced motion (.is-static): normal height, orb above the
   heading, cards flip in once in sequence. */
.tr-hero { position: relative; height: 230vh; background: #0B1B2B; color: #FFFFFF; }
.tr-hero__stage {
    position: sticky;
    top: 0;
    height: 100vh;
    min-height: 640px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: clamp(2rem, 5vh, 3.5rem);
    padding: 110px 0 6vh;
    overflow: hidden;
    background:
        radial-gradient(ellipse 60% 45% at 50% 100%, rgba(72, 104, 136, 0.4), rgba(72, 104, 136, 0) 70%),
        radial-gradient(ellipse 40% 35% at 50% 25%, rgba(255, 101, 11, 0.08), rgba(255, 101, 11, 0) 70%),
        linear-gradient(180deg, #08131D 0%, #0F2131 100%);
}
.tr-hero__stars {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0.5;
    background-image:
        radial-gradient(1.2px 1.2px at 12% 18%, rgba(255, 255, 255, 0.8), transparent),
        radial-gradient(1px 1px at 28% 62%, rgba(255, 255, 255, 0.6), transparent),
        radial-gradient(1.4px 1.4px at 44% 12%, rgba(255, 255, 255, 0.7), transparent),
        radial-gradient(1px 1px at 63% 38%, rgba(255, 255, 255, 0.55), transparent),
        radial-gradient(1.3px 1.3px at 78% 22%, rgba(255, 255, 255, 0.75), transparent),
        radial-gradient(1px 1px at 90% 58%, rgba(255, 255, 255, 0.6), transparent),
        radial-gradient(1px 1px at 8% 82%, rgba(255, 255, 255, 0.5), transparent),
        radial-gradient(1.2px 1.2px at 55% 78%, rgba(255, 255, 255, 0.5), transparent),
        radial-gradient(1px 1px at 36% 32%, rgba(255, 255, 255, 0.45), transparent),
        radial-gradient(1px 1px at 84% 84%, rgba(255, 255, 255, 0.5), transparent);
    background-size: 520px 420px;
}
.tr-hero__copy { position: relative; z-index: 2; text-align: center; }
body .tr-hero .tr-hero__title, #training-hero.tr-hero h1 { margin: 0 auto; max-width: 22ch; font-size: clamp(38px, 4.4vw, 64px); line-height: 1.08; letter-spacing: -0.03em; color: #FFFFFF; }
.tr-hero__title span { color: var(--color-accent); }
.tr-hero__intro { max-width: 40rem; margin: 20px auto 0; font-size: 17px; line-height: 1.6; color: rgba(255, 255, 255, 0.72); }
.tr-hero .btn { margin-top: 28px; }

/* the orb: the gear-and-shield cut-out, positioned by app.js (translate3d)
   inside the stage, with an orange glow so it reads on the dark stage */
.tr-hero__orb {
    position: absolute;
    left: 0;
    top: 0;
    z-index: 3;
    width: 64px;
    height: 67px;
    margin: -33px 0 0 -32px;
    pointer-events: none;
    will-change: transform;
}
.tr-hero__orb img { position: relative; z-index: 1; width: 100%; height: 100%; display: block; filter: drop-shadow(0 0 10px rgba(255, 140, 60, 0.55)) drop-shadow(0 10px 14px rgba(0, 0, 0, 0.5)); }
.tr-hero__orb::before { content: ""; position: absolute; inset: -20%; border-radius: 50%; background: radial-gradient(circle, rgba(255, 122, 26, 0.35), rgba(255, 122, 26, 0) 70%); }
.tr-hero__orb::after { content: ""; position: absolute; inset: -30%; border-radius: 50%; border: 1px solid rgba(255, 178, 122, 0.35); animation: tr-orb-ring 2.6s ease-out infinite; }
@keyframes tr-orb-ring { 0% { opacity: 0.9; scale: 0.7; } 100% { opacity: 0; scale: 1.5; } }

/* the six flip cards */
.tr-hero__cards { position: relative; z-index: 2; display: flex; justify-content: center; gap: clamp(10px, 1.6vw, 22px); perspective: 1100px; }
.tr-card { flex: 0 1 178px; aspect-ratio: 486 / 559; }
.tr-card__inner { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transform: rotateY(180deg); transition: transform 0.9s cubic-bezier(0.16, 1, 0.3, 1); }
.tr-card.is-flipped .tr-card__inner { transform: rotateY(0deg) translateZ(30px); }
.tr-card__face { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 14px; border-radius: 20px; backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.tr-card__face--back { align-items: flex-start; justify-content: flex-start; padding: 18px 16px; transform: rotateY(180deg); background: linear-gradient(160deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)); border: 1px solid rgba(255, 255, 255, 0.12); }
/* back: a faint dot grid (fading towards the bottom), the track name as a
   heading at the top, its number in the top-right corner and an orange ring
   with a glowing core below, so the row reads before the cards flip */
.tr-card__face--back::before { content: ""; position: absolute; inset: 0; border-radius: inherit; background: radial-gradient(circle, rgba(255, 255, 255, 0.16) 1px, transparent 1.5px) 0 0 / 14px 14px; -webkit-mask-image: linear-gradient(180deg, #000, transparent 85%); mask-image: linear-gradient(180deg, #000, transparent 85%); pointer-events: none; }
.tr-card__no { position: absolute; top: 18px; right: 16px; font-size: 12px; font-weight: 600; letter-spacing: 0.12em; color: rgba(255, 178, 122, 0.75); }
.tr-card__mark { position: absolute; left: 33%; top: 56%; translate: 0 -50%; width: 34%; aspect-ratio: 1; border-radius: 50%; border: 1.5px solid rgba(255, 178, 122, 0.45); box-shadow: inset 0 0 0 8px rgba(255, 178, 122, 0.08); }
.tr-card__mark::after { content: ""; position: absolute; inset: 38%; border-radius: 50%; background: #FF8A3D; box-shadow: 0 0 12px 3px rgba(255, 122, 26, 0.55); }
.tr-card__name { position: relative; max-width: calc(100% - 26px); text-align: left; font-size: 17px; font-weight: 700; line-height: 1.2; letter-spacing: -0.01em; color: #FFFFFF; }
.tr-card__face--front { background: linear-gradient(160deg, #FFFFFF, #F3EEE7); color: var(--color-ink); box-shadow: 0 24px 50px -20px rgba(255, 120, 40, 0.55), 0 0 0 1px rgba(255, 255, 255, 0.6); }
/* front: the technology illustration filling the card, its name on a soft
   white fade along the bottom */
.tr-card__face--front { padding: 0; overflow: hidden; justify-content: flex-end; }
.tr-card__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.tr-card__face--front::after { content: ""; position: absolute; inset: 55% 0 0; background: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.92) 55%); }
.tr-card__label { position: relative; z-index: 1; padding: 0 10px 14px; font-size: 14.5px; font-weight: 700; line-height: 1.25; text-align: center; letter-spacing: -0.01em; color: var(--color-ink); }

/* static: phones and reduced motion -- no pinning, orb above the heading */
.tr-hero.is-static { height: auto; }
.tr-hero.is-static .tr-hero__stage { position: relative; height: auto; min-height: 0; padding: 120px 0 64px; }
.tr-hero.is-static .tr-hero__orb { position: relative; left: auto; top: auto; display: block; margin: 0 auto 26px; transform: none !important; }
@media (prefers-reduced-motion: no-preference) {
    .tr-hero.is-static .tr-card .tr-card__inner { animation: tr-card-in 0.9s cubic-bezier(0.16, 1, 0.3, 1) both; }
    .tr-hero.is-static .tr-card:nth-child(2) .tr-card__inner { animation-delay: 0.15s; }
    .tr-hero.is-static .tr-card:nth-child(3) .tr-card__inner { animation-delay: 0.3s; }
    .tr-hero.is-static .tr-card:nth-child(4) .tr-card__inner { animation-delay: 0.45s; }
    .tr-hero.is-static .tr-card:nth-child(5) .tr-card__inner { animation-delay: 0.6s; }
    .tr-hero.is-static .tr-card:nth-child(6) .tr-card__inner { animation-delay: 0.75s; }
}
.tr-hero.is-static .tr-card__inner { transform: none; }
@keyframes tr-card-in { from { transform: rotateY(180deg); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) { .tr-hero__orb::after { animation: none; } }
@media (max-width: 991.98px) {
    .tr-hero__cards { flex-wrap: wrap; }
    .tr-card { flex: 0 1 calc(33.333% - 14px); }
    .tr-card__label { font-size: 13px; padding-bottom: 10px; }
    .tr-card__name { font-size: 14px; }
}
