/* ==========================================================================
   Cloud Propeller — Marketing Site CSS
   Loads AFTER bootstrap.min.css. Cherry-picks the design tokens and nav
   treatments from cp-twenty-one/custom.css that the marketing site needs,
   then layers on hero / services / footer styles written for this site.
   ========================================================================== */

/* 1. Design tokens ------------------------------------------------------ */
:root {
    --cp-pink:       #de3580;
    --cp-pink-dark:  #c02870;
    --cp-pink-light: #ff5aa0;

    --cp-bg:         #ffffff;
    --cp-bg-alt:     #f6f8fb;
    --cp-bg-footer:  #0f1826;

    --cp-text:         #2c3e50;
    --cp-text-heading: #0f1826;
    --cp-text-muted:   #5a6b82;

    --cp-border:         rgba(26, 34, 51, 0.08);
    --cp-border-strong:  rgba(26, 34, 51, 0.16);

    --cp-gradient-default: linear-gradient(135deg, #1a3050 0%, #4d1230 18%, #de3580 38%, #bf6bb4 58%, #7a9dbe 78%, #2d4a6b 100%);
    --cp-gradient-mcc:     linear-gradient(135deg, #1a3050 0%, #4d1230 45%, #de3580 100%);
    --cp-gradient-gpc:     linear-gradient(135deg, #a0558a 0%, #5a7a9a 60%, #1d3a5b 100%);

    --cp-shadow-card:        0 4px 20px rgba(222, 53, 128, 0.10);
    --cp-shadow-card-hover:  0 12px 36px rgba(222, 53, 128, 0.18);

    --cp-r-sm: 8px;
    --cp-r:    12px;
    --cp-r-lg: 20px;

    --font-heading: 'Exo 2', 'Segoe UI', sans-serif;
    --font-body:    'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --font-tech:    'Share Tech', 'Exo 2', monospace;

    /* Shared shrink variable, 0→1 over the first 44px of scroll.
       Set on :root (not on header) so the breadcrumb — a sibling
       of header, not a descendant — can also inherit it and animate
       its own sticky top in lock-step. site.js writes this on
       document.documentElement for the same reason. */
    --scroll-shrink: 0;
}

/* 2. Body + typography (Bootstrap overrides) ---------------------------- */
/* Always reserve scrollbar gutter so toggling scroll-locked states
   (like the hero intro overlay) doesn't visibly narrow the viewport
   when the scrollbar appears/disappears. Supported in modern browsers;
   older browsers ignore this gracefully and fall back to their default
   scrollbar behavior.
   ---
   `overflow-anchor: none` disables the browser's scroll-anchoring
   behavior, which would otherwise fight the header's scroll-linked
   progressive shrink: as the header shrinks, document layout shifts
   up, scroll anchoring adjusts scrollY down to compensate, that
   adjustment fires another scroll event, which shrinks the header
   again, etc. — a feedback loop that made scroll near the top feel
   stuck. Disabling anchoring lets the scroll position be whatever
   the user actually scrolled to, period. */
/* Global smooth scroll. Covers in-page anchor clicks (e.g. clicking
   nav links to #section), JS scrollIntoView calls, and any user-
   triggered scroll-into-view from devtools. Initial page-load hash
   navigation (loading /page#anchor from another origin) still jumps
   instantly per browser default — site.js handles that case manually. */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}

html {
    /* Black fills the iPhone-landscape "safe-area gutter" — the strips
       on the sides of the viewport that iOS excludes to avoid the
       Dynamic Island / notch. Without this, those strips render
       white (the HTML element's default backdrop) and clash with
       the site's content. The body has its own white background
       that covers html's content area, so this black is only
       visible in the inset gutters. */
    background: #000;
    /* scrollbar-gutter: stable reserves the scrollbar's space even when
       the page is short and no scrollbar is needed, so layout never
       shifts horizontally as content grows past the viewport. This is
       primarily here to keep the hero-intro welcome animation stable
       (the orbit logos compute positions based on a fixed viewport
       width — a mid-animation scrollbar appearance would re-layout
       everything). If the welcome animation is ever removed/disabled
       permanently ($welcomeAnimation = false in includes/config.php),
       this `scrollbar-gutter: stable` rule and the Lightbox3 escape
       below can both go too — the page tolerates scrollbar-induced
       layout shift fine in static contexts. */
    scrollbar-gutter: stable;
    overflow-anchor: none;
}
/* When Lightbox3 is open, it sets body.style.overflow = 'hidden' to lock
   page scroll. Our scrollbar-gutter: stable above keeps the gutter
   reserved even when the scrollbar disappears, which leaves a white
   strip on the right while the lightbox covers the rest of the
   viewport. Dropping the gutter only while the lightbox overlay is in
   the DOM lets Lightbox3's own padding-right compensation handle layout
   shift cleanly. Uses :has() — supported in all evergreen browsers. */
html:has(.lightbox3-overlay) {
    scrollbar-gutter: auto;
}
body {
    font-family: var(--font-body);
    color: var(--cp-text);
    background: var(--cp-bg);
    line-height: 1.6;
    /* Don't let the layout compress below iPhone 12/13 mini (and SE
       2nd/3rd gen, and iPhone 6/7/8) CSS-pixel width. At anything
       narrower the page gets a horizontal scrollbar instead of
       squeezing into unreadable density. On real small iPhones the
       viewport is exactly 375, so no scroll appears — the floor
       only activates for unusual devices or aggressively narrow
       desktop browser windows. */
    min-width: 375px;
    /* Safe-area-inset handling for iPhone landscape. viewport-fit=
       cover on the <meta> tag (header.php) lets the webpage extend
       into the notch/Dynamic-Island gutters. Padding = env insets
       keeps actual content inside the safe area. background-clip:
       content-box makes body's white background stop at the padding
       edge — inside the padding, html's black background
       (declared above) shows through, turning the gutter zones
       black. Portrait inset values are usually 0, so this only
       activates in landscape. */
    padding-left:  env(safe-area-inset-left, 0);
    padding-right: env(safe-area-inset-right, 0);
    background-clip: content-box;
    /* Body content keeps `antialiased` — main sections (hero, services,
       testimonials, final-cta) stay clean and thin like modern hero
       pages. The header chrome (nav, breadcrumb) and footer override
       this below to use subpixel rendering for extra weight — they
       match the WHMCS chrome that way. */
    -webkit-font-smoothing: antialiased;
}
/* Chrome override — heavier text in header + breadcrumb + footer */
header.header,
.master-breadcrumb,
footer.cp-footer {
    -webkit-font-smoothing: subpixel-antialiased;
}
h1, h2, h3, h4, h5 {
    font-family: var(--font-heading);
    color: var(--cp-text-heading);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.01em;
    margin-top: 0;
}
h1 { font-size: clamp(2.4rem, 5vw, 4.25rem); }
h2 { font-size: clamp(1.85rem, 3.2vw, 2.75rem); }
h3 { font-size: 1.375rem; }
h4 { font-size: 1.05rem; }

a { color: var(--cp-pink); }
a:hover, a:focus { color: var(--cp-pink-dark); text-decoration: none; }

/* 3. Layout helpers ----------------------------------------------------- */
.section { padding: 96px 0; position: relative; }
@media (max-width: 768px) { .section { padding: 64px 0; } }

/* Wider container at lg+ to match the visual width of my.cloudpropeller.com.
   Bootstrap's default is 1140 at ≥1200; measurement of WHMCS shows content
   spanning ~1208 CSS px at the same viewport. Bumping to 1220 restores the
   breathing room so both sites feel like siblings rather than the marketing
   site being cramped.

   Applied at ≥992 (not just ≥1200): below viewport 1220, max-width doesn't
   actually cap anything — the container grows to viewport-padding. So
   extending this rule down to 992 only affects the 992–1199 range, where
   it replaces Bootstrap's hard 960px cap with viewport-based sizing
   (container fills ~viewport-30px at any viewport ≥992). This eliminates
   the sudden 260px container narrowing that used to happen at 1200→1199,
   which was cramping cards in the Data Protection section and forcing
   the center card's title to wrap to 2 lines. Above viewport 1220, the
   cap still holds. */
@media (min-width: 992px) {
    .container,
    .container-lg,
    .container-md,
    .container-sm,
    .container-xl {
        max-width: 1220px;
    }
}

/* 4. Background watermark logo ----------------------------------------- */
.bg-logo-watermark {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(70vmin, 720px);
    height: min(70vmin, 720px);
    pointer-events: none;
    z-index: 0;
    opacity: 0.05;
    background: url('../img/logos/cp-logo.svg') center / contain no-repeat;
}
.site-wrap { position: relative; z-index: 1; }

/* ==========================================================================
   5. Header + primary navbar (cp-twenty-one overrides)
   ========================================================================== */
header.header {
    position: sticky;
    top: 0;
    z-index: 1030;
    /* Glass effect — semi-transparent white with backdrop blur. On light
       backgrounds this reads as a soft frosted pane, reminiscent of the
       below0day aesthetic adapted to a light theme. */
    background: rgba(255, 255, 255, 0.82);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    backdrop-filter: saturate(180%) blur(14px);
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
    transition: background 0.2s ease, box-shadow 0.25s ease,
                border-color 0.2s ease;
    /* --scroll-shrink is declared on :root (above), not here — that
       lets .master-breadcrumb (a sibling of header) also see it and
       animate its own sticky top in the same rAF frame as the
       header's shrinkage. See :root for the declaration and
       site.js for the writer. */
}
header.header .navbar {
    /* At rest: 8px top/bottom padding. Fully shrunk: 4px. Linearly
       interpolated via --scroll-shrink. */
    padding-top:    calc(8px - var(--scroll-shrink) * 4px);
    padding-bottom: calc(8px - var(--scroll-shrink) * 4px);
}

/* Logo — explicit height + width:auto so the PNG (or sizeless SVG, if we
   ever swap back) has a concrete dimension to scale from. Height shrinks
   from 88px (at rest) to 52px (fully scrolled), linearly.
   display: block eliminates the inline-image line-box descender gap
   (Bootstrap's `img { vertical-align: middle }` doesn't fully remove it
   when the img is taller than the parent's line-height). Without this,
   navbar-brand renders ~2px taller than logo + its own padding, which
   caused the breadcrumb's sticky top to fall short of the actual header
   bottom by 2px on mobile — visible as a 2px slide before the
   breadcrumb catches its sticky threshold. */
header.header .logo-img {
    display: block;
    height:     calc(88px - var(--scroll-shrink) * 36px);
    width: auto;
    max-height: calc(88px - var(--scroll-shrink) * 36px);
    max-width: 500px;
    padding: 0;
    box-sizing: border-box;
}

/* Scrolled state — discrete visual changes that don't interpolate well
   (background opacity, shadow, logo image swap). site.js toggles the
   class at progress >= 0.5 so the swap lands around mid-shrink. */
header.header.scrolled {
    background: rgba(255, 255, 255, 0.96);
    border-bottom-color: rgba(0, 0, 0, 0.1);
    box-shadow: 0 2px 16px rgba(26, 34, 51, 0.08);
}
/* Logo swap: two <img> elements layered inside the navbar-brand
   anchor. The --full one stays in normal flow so it sizes the
   navbar-brand; the --compact one is absolute-positioned on top
   of it. Both fade in/out via opacity so the transition reads as
   a quick crossfade instead of a hard cut. The class toggle fires
   at progress >= 0.95 in site.js, so the swap only happens near
   the very end of the shrink — full logo is visible during
   almost all of the transition, compact only at the final min
   height. */
.navbar-brand {
    position: relative;
}
header.header .logo-img {
    transition: opacity 0ms ease;
}
header.header .logo-img--full {
    opacity: 1;
}
header.header .logo-img--compact {
    position: absolute;
    /* top:50% + translateY(-50%) vertically centers the compact
       logo within .navbar-brand. Can't use top:0 because Bootstrap's
       .navbar-brand has 5px top padding, which pushes the full logo
       (normal flow) down by 5px but not the absolute compact — they'd
       be misaligned. Centering both to the same axis avoids that. */
    top: 50%;
    left: 0;
    transform: translateY(-50%);
    opacity: 0;
    pointer-events: none;
}
header.header.scrolled .logo-img--full { opacity: 0; }
header.header.scrolled .logo-img--compact { opacity: 1; }

/* Desktop nav: Exo 2 font, underline-draw hover, pink active */
@media (min-width: 992px) {
    .navbar-light #nav {
        align-items: center;
    }
    .navbar-light #nav > li > a {
        padding: 8px 14px !important;
        font-family: var(--font-heading);
        font-size: 17px;
        font-weight: 500;
        letter-spacing: 0.3px;
        color: var(--cp-text);
        position: relative;
        transition: color 0.3s ease;
        text-decoration: none;
    }
    .navbar-light #nav > li > a:hover {
        color: var(--cp-pink);
        text-decoration: none;
    }

    /* Underline draw-in — plain links use ::after */
    .navbar-light #nav > li > a:not(.dropdown-toggle)::after {
        content: '';
        position: absolute;
        bottom: 0;
        left: 14px;
        right: 14px;
        height: 2.5px;
        background: var(--cp-pink);
        border-radius: 2px;
        transform: scaleX(0);
        transform-origin: left;
        transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
    }
    .navbar-light #nav > li > a:not(.dropdown-toggle):hover::after {
        transform: scaleX(1);
    }

    /* Underline draw-in — dropdown toggles use ::before
       (Bootstrap's ::after is the caret) */
    .navbar-light #nav > li > a.dropdown-toggle {
        position: relative;
    }
    .navbar-light #nav > li > a.dropdown-toggle::before {
        content: '';
        position: absolute;
        bottom: 0;
        left: 14px;
        right: 14px;
        height: 2.5px;
        background: var(--cp-pink);
        border-radius: 2px;
        transform: scaleX(0);
        transform-origin: left;
        transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
    }
    .navbar-light #nav > li > a.dropdown-toggle:hover::before,
    .navbar-light #nav > li.show > a.dropdown-toggle::before {
        transform: scaleX(1);
    }

    /* Active section — pink text, full underline */
    .navbar-light #nav > li.cp-nav-active > a {
        color: var(--cp-pink) !important;
    }
    .navbar-light #nav > li.cp-nav-active > a:not(.dropdown-toggle)::after,
    .navbar-light #nav > li.cp-nav-active > a.dropdown-toggle::before {
        transform: scaleX(1);
    }

    .navbar-light #nav .dropdown-menu {
        font-family: var(--font-heading);
    }
}

/* Narrow-desktop nav (992–1199): the full nav now renders in this
   range (iPad landscape etc.) where the collapse used to kick in.
   Base 17px / 14px padding was tuned for 1200+; tighten font and
   horizontal padding a bit so everything fits without crowding.
   Underline offsets on ::after/::before mirror the new padding. */
@media (min-width: 992px) and (max-width: 1199px) {
    .navbar-light #nav > li > a {
        font-size: 15px;
        padding: 8px 10px !important;
    }
    .navbar-light #nav > li > a:not(.dropdown-toggle)::after,
    .navbar-light #nav > li > a.dropdown-toggle::before {
        left: 10px;
        right: 10px;
    }
}

/* Mobile nav (below lg) */
@media (max-width: 991px) {
    header.header .navbar { padding-top: 8px; padding-bottom: 8px; }
    header.header .logo-img { max-height: 56px; }
    /* Breadcrumb sticky top matches the mobile header's rendered
       height: 56px logo + 10px .navbar-brand padding (Bootstrap
       default 5+5) + 16px navbar padding (8+8) + 1px border-bottom
       on header.header = 83px. The border counts because the element
       has no explicit height, so box-sizing: border-box auto-grows
       to content+padding+border. Without this exact match, the
       breadcrumb either slides ~12px before sticking (if too low)
       or tucks 1px under the border (if off-by-one). */
    .master-breadcrumb { top: 83px; }
    #mainNavbar #nav { padding: 8px 0; }
    #mainNavbar #nav > li { border-bottom: 1px solid #eee; }
    #mainNavbar #nav > li:last-child { border-bottom: none; }
    header.header .navbar-nav#nav > li > a,
    #mainNavbar #nav > li > a {
        display: block !important;
        width: 100% !important;
        font-family: var(--font-heading);
        font-size: 18px !important;
        font-weight: 600 !important;
        padding: 14px 20px 14px 24px !important;
        color: var(--cp-text) !important;
        text-align: left;
    }
    header.header .navbar-nav#nav > li > a:hover,
    header.header .navbar-nav#nav > li > a:active,
    #mainNavbar #nav > li > a:hover,
    #mainNavbar #nav > li > a:active {
        color: var(--cp-pink) !important;
        background: rgba(222, 53, 128, 0.04);
    }
    #mainNavbar #nav > li.cp-nav-active > a {
        color: var(--cp-pink) !important;
        background: rgba(222, 53, 128, 0.04);
    }
}

/* Everything below full-desktop (≤1199px): strip the scroll
   grow/shrink animation and keep the FULL logo (with "Infrastructure
   you can rely on" subtitle) visible at all times. Applies to:
   phones, tablets, iPad portrait, iPad landscape, narrow desktop.
   Only full desktop (≥1200) keeps the original scroll-shrink
   animation.

   Without this lock the header shrinks 114→70px during scroll, which
   on anything narrower than a full desktop either creates a weirdly
   tall header at rest (iPad landscape) or tiny wiggly one
   (mobile/tablet with max-height cap). Locking to a steady compact
   state keeps the visual identity consistent across all "narrower
   than desktop" viewports. */
@media (max-width: 1199px) {
    /* Always wear the "scrolled" chrome — solid background + shadow
       from page load, no fade-in on scroll. */
    header.header {
        background: rgba(255, 255, 255, 0.96);
        border-bottom-color: rgba(0, 0, 0, 0.1);
        box-shadow: 0 2px 16px rgba(26, 34, 51, 0.08);
    }
    /* Freeze navbar padding too — base rule animates it 8→4px via
       --scroll-shrink, which would make the header subtly twitchier
       even with the logo locked. 8/8 static matches the ≤991 rule's
       mobile-nav block, so header height stays constant at any
       scroll position across the whole locked range. */
    header.header .navbar {
        padding-top: 8px !important;
        padding-bottom: 8px !important;
    }
    /* Freeze logo height — overrides the base calc(88 - shrink*36)
       AND its max-height counterpart. Without the max-height
       override, max-height starts clamping the height below 56 once
       --scroll-shrink drives calc(88 - shrink*36) below 56 (happens
       at shrink > ~0.89). That was the residual "logo still resizes
       on scroll" issue visible at iPad landscape where
       --scroll-shrink animates normally but we want the logo frozen. */
    header.header .logo-img {
        height:     56px !important;
        max-height: 56px !important;
    }
    /* Never swap to the compact logo on phones. Keep full visible
       even when site.js toggles the .scrolled class. */
    header.header .logo-img--full,
    header.header.scrolled .logo-img--full { opacity: 1 !important; }
    header.header .logo-img--compact,
    header.header.scrolled .logo-img--compact { opacity: 0 !important; }
    /* Matches ≤991 rule above — duplicated here so the value is
       obvious within the phones-only lock block. Same math: 56px
       logo + 10 brand padding + 16 navbar padding + 1 border = 83. */
    .master-breadcrumb {
        top: 83px;
    }
}

/* Mobile toolbar (cart + hamburger) lives in a .navbar-nav, which
   Bootstrap defaults to `flex-direction: column` below the expand
   breakpoint. Force row so the two icons sit side-by-side instead of
   stacking (cart above, hamburger underneath). Also align vertically
   centered so the hamburger doesn't float to the top of its own li. */
.navbar .navbar-nav.toolbar {
    flex-direction: row !important;
    align-items: center;
}

/* Cart button — darker than the rest so it reads as an icon, not a link */
.navbar-light .navbar-nav .nav-link.cart-btn,
.navbar .toolbar button.nav-link {
    color: var(--cp-text) !important;
}
header.header .toolbar .nav-link.cart-btn {
    padding-left: calc(1rem - 2px);
    padding-right: calc(1rem + 6px);
    position: relative;
}
.navbar-light .navbar-nav .nav-link.cart-btn:hover,
.navbar-light .navbar-nav .nav-link.cart-btn:active,
.navbar .toolbar button.nav-link:hover,
.navbar .toolbar button.nav-link:active {
    color: var(--cp-pink) !important;
}

/* Hamburger button — port WHMCS's boxed look. WHMCS's theme.min.css
   ships a default `header .toolbar .nav-link { border: 1px solid #e5e5e5;
   border-radius: .25rem; padding: .5rem 1rem }` that our marketing site
   never inherited. Applying it only to the <button> variant (hamburger)
   keeps the cart icon borderless as designed. The border stays the same
   gray on hover/active — only the bars tint pink. :focus states are
   deliberately excluded so the icon doesn't stay pink after clicking
   to close the menu (Bootstrap collapse keeps focus on the button,
   which was leaving the icon stuck in the pink state). */
.navbar .toolbar button.nav-link {
    border: 1px solid #e5e5e5;
    border-radius: 0.25rem;
    padding: 0.5rem 1rem;
    transition: color 0.15s ease;
}

/* Suppress Bootstrap's default blue focus glow on the toolbar buttons.
   Bootstrap 4 applies `.btn:focus { outline: 0; box-shadow: 0 0 0 .2rem
   rgba(51,102,153,.25) }` — the blue ring hangs around after clicking
   the hamburger or cart because the button keeps focus. WHMCS kills
   it the same way via `.btn:focus { box-shadow: none }` in theme.min.css;
   we only scope it to the toolbar buttons here (keeps the focus ring on
   every other .btn for a11y). Keyboard users still get a visible
   outline via :focus-visible. */
.navbar .toolbar button.nav-link:focus,
.navbar .toolbar .nav-link.cart-btn:focus {
    box-shadow: none;
    outline: 0;
}
.navbar .toolbar button.nav-link:focus-visible,
.navbar .toolbar .nav-link.cart-btn:focus-visible {
    outline: 2px solid var(--cp-pink);
    outline-offset: 2px;
}

/* Cart badge — green pill (not Bootstrap's info blue) */
#cartItemCount.badge-info,
#cartItemCountDesktop.badge-info,
.badge-info {
    background-color: #28a745 !important;
    border-color: #28a745 !important;
    color: #fff !important;
}

/* ==========================================================================
   6. Master breadcrumb bar
   ========================================================================== */
.master-breadcrumb {
    min-height: 48px;
    display: flex;
    align-items: center;
    background: linear-gradient(135deg, #1a3050 0%, #4d1230 40%, #de3580 100%);
    /* Sticky — `top` is set below in per-breakpoint rules, since the
       desktop value (114→70 calc animating with --scroll-shrink) and
       the mobile value (fixed 82px, since the mobile header doesn't
       appreciably shrink) need different formulas. z-index below
       header (1030) so header still paints over on any overlap. */
    position: sticky;
    z-index: 1029;
    padding-top: 6px;
    padding-bottom: 6px;
}
/* Full desktop only (≥1200): breadcrumb sticky top animates with
   --scroll-shrink in lockstep with the header's own shrinkage. Both
   read from the same :root variable in the same rAF frame, so they
   can never fall out of sync — eliminates the fast-scroll rAF-lag
   tuck that the old fixed top: 70px + scroll-ride-along design
   suffered from. At rest (shrink=0): top=114 (below full header).
   At full shrink (shrink=1): top=70 (below shrunk header).
   Scoped to ≥1200 because 992-1199 (iPad landscape / narrow desktop)
   now uses the locked-compact header from the ≤1199 block above, so
   no animation is needed there. */
@media (min-width: 1200px) {
    .master-breadcrumb {
        top: calc(114px - var(--scroll-shrink) * 44px);
    }
}
.master-breadcrumb .breadcrumb {
    background: transparent;
    padding: 0;
    margin: 0;
}
.master-breadcrumb .breadcrumb-item {
    display: flex;
    align-items: center;
    font-weight: 600;
    font-size: 15px;
    color: rgba(255, 255, 255, 0.6);
    font-family: var(--font-heading);
    letter-spacing: 0.3px;
}
/* Home page tagline variant — bold, reads as marketing copy next to
   the Ohio's badge image. */
.master-breadcrumb .breadcrumb-item.breadcrumb-tagline {
    font-weight: 700;
}
/* Icon/image that can prefix a breadcrumb label — used for the Ohio
   state logo on the home tagline. Sized large (36px) so it reads as
   a proper badge rather than a decoration. width:auto keeps the
   natural aspect ratio of the SVG source. */
.master-breadcrumb .breadcrumb-icon {
    height: 36px;
    width: auto;
    margin-right: 6px;
    flex-shrink: 0;
    vertical-align: middle;
}
/* State of Ohio logo — navy portions were recolored to white directly in
   the SVG source file (the CSS filter trick would have flattened red + gray
   into the same color). Red state outline stays red on the dark gradient.
   Drop-shadow keeps it feeling lifted, not pasted-on. */
.master-breadcrumb .breadcrumb-icon--ohio {
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
}
.master-breadcrumb .breadcrumb-item a {
    color: rgba(255, 255, 255, 0.88);
}
.master-breadcrumb .breadcrumb-item a:hover {
    color: #ffffff;
    text-decoration: none;
}
.master-breadcrumb .breadcrumb-item.active {
    color: #ffffff;
}
/* Chevron separator — unicode to avoid FA dependency */
.master-breadcrumb .breadcrumb-item + .breadcrumb-item::before {
    content: "\203A"; /* › */
    display: inline-block;
    padding: 0 0.6rem;
    color: rgba(255, 255, 255, 0.45);
    font-weight: 700;
    font-size: 14px;
    line-height: 1;
}

/* Responsive breadcrumb labels — each crumb renders `<span class="
   breadcrumb-full">…</span>` plus optionally a `<span class="breadcrumb-
   short">…</span>` (populated by header.php from the `short_label` key
   on the $BREADCRUMB entry, or auto-filled with a house icon for the
   "Home" crumb). The two span classes toggle via viewport: desktop
   shows the full label, mobile shows the short one.
   Spans always render in the markup so the source is identical across
   widths — the swap is pure CSS, no layout shift. */
.master-breadcrumb .breadcrumb-full { display: inline; }
.master-breadcrumb .breadcrumb-short { display: none; }
@media (max-width: 768px) {
    .master-breadcrumb .breadcrumb-item:has(.breadcrumb-short) .breadcrumb-full { display: none; }
    .master-breadcrumb .breadcrumb-item:has(.breadcrumb-short) .breadcrumb-short { display: inline; }
}

/* Phone pill — matches cp-twenty-one */
.cp-nav-phone {
    background: #ffffff;
    color: var(--cp-pink);
    border: 1px solid rgba(0, 0, 0, 0.08);
    padding: 5px 14px;
    border-radius: 20px;
    font-family: var(--font-heading);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.3px;
    line-height: 1;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    transition: all 0.2s ease;
    box-shadow: none;
}
.cp-nav-phone:hover {
    background: rgba(222, 53, 128, 0.25);
    color: #ffffff;
    border-color: #ffffff;
    text-decoration: none;
    box-shadow: 0 2px 8px rgba(222, 53, 128, 0.3);
}
.cp-nav-phone i {
    font-size: 10px;
    margin-left: 6px;
    transition: color 0.2s ease;
}
.cp-nav-phone:hover i { color: #ffffff; }

/* ==========================================================================
   7. Services mega dropdown (cp-mega-*) — lifted from custom.css
   ========================================================================== */

/* Kill Bootstrap's default dropdown card so we can use our own surface */
.cp-store-dropdown-wrap {
    background: transparent !important;
    border: none !important;
    box-shadow: none !important;
    padding: 0 !important;
    margin: 0 !important;
    min-width: 0;
}
@media (min-width: 992px) {
    .cp-store-dropdown-wrap {
        left: 50% !important;
        right: auto !important;
        transform: translateX(-50%);
        /* Push the visible mega card down so its top lands right under the
           navbar (and OVER the breadcrumb, not past it). At rest the
           padding is 45px (navbar-bottom + small breadcrumb overshoot);
           fully-scrolled it's 22px (navbar is 44px shorter). Interpolated
           via the same --scroll-shrink custom property that drives the
           logo and navbar padding, so the mega card slides up smoothly
           as the header shrinks. */
        padding-top: calc(45px - var(--scroll-shrink, 0) * 22.5px) !important;
    }
}

.cp-mega-clip {
    overflow: hidden;
    margin: 0 -50px -80px;
    padding: 0 50px 80px;
}

.cp-mega-dropdown {
    background: #ffffff;
    border-radius: 0 0 12px 12px;
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.22), 0 6px 16px rgba(0, 0, 0, 0.08);
    overflow: hidden;
    width: 740px;
    max-width: calc(100vw - 40px);
}

.cp-mega-heroes {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0;
}

.cp-mega-hero {
    padding: 29px 28px 26px;
    position: relative;
    cursor: pointer;
    transition: all 0.3s ease;
    overflow: hidden;
    text-decoration: none !important;
    display: block;
    color: inherit !important;
}
.cp-mega-hero::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    opacity: 0;
    transition: opacity 0.3s ease;
    z-index: 0;
}
.cp-mega-hero:hover::before { opacity: 1; }
.cp-mega-hero > * {
    position: relative;
    z-index: 1;
}

.cp-mega-hero--gen3 {
    background: var(--cp-gradient-gpc);
    box-shadow: inset 0 8px 12px -6px rgba(0, 0, 0, 0.25);
}
.cp-mega-hero--gen3::before {
    background: linear-gradient(135deg, #b060a0 0%, #6a8cac 60%, #253f60 100%);
    box-shadow: inset 0 8px 12px -6px rgba(0, 0, 0, 0.22);
}
.cp-mega-hero--gen4 {
    background: var(--cp-gradient-mcc);
    box-shadow: inset 0 8px 12px -6px rgba(0, 0, 0, 0.2);
}
.cp-mega-hero--gen4::before {
    background: linear-gradient(135deg, #2a4060 0%, #5d2240 45%, #ee4590 100%);
    box-shadow: inset 0 8px 12px -6px rgba(0, 0, 0, 0.15);
}

.cp-mega-hero__toprow {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 16px;
}
.cp-mega-hero__icon {
    width: 48px;
    height: 48px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    color: #fff;
    flex-shrink: 0;
}
.cp-mega-hero--gen3 .cp-mega-hero__icon {
    background: linear-gradient(135deg, #de3580, #bf6bb4);
    border: 2px solid rgba(255, 255, 255, 0.35);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}
.cp-mega-hero--gen4 .cp-mega-hero__icon {
    background: linear-gradient(135deg, #bf6bb4, #8e44ad);
    border: 2px solid rgba(255, 255, 255, 0.35);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}

.cp-mega-hero__features {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.cp-mega-hero__feat {
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.3px;
    text-transform: uppercase;
    padding: 2px 7px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.15);
    color: rgba(255, 255, 255, 0.8);
    white-space: nowrap;
    line-height: 1.4;
}

.cp-mega-hero__gen {
    font-family: var(--font-tech);
    font-size: 11px;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    margin-bottom: 4px;
    color: rgba(255, 255, 255, 0.85);
}

.cp-mega-hero__name,
a.cp-mega-hero__name {
    font-family: var(--font-heading);
    font-size: 17px;
    font-weight: 700;
    margin-bottom: 8px;
    color: #ffffff !important;
    text-decoration: none !important;
    display: block;
}
a.cp-mega-hero__name:hover {
    color: rgba(255, 255, 255, 0.85) !important;
    text-decoration: none !important;
}

.cp-mega-hero__desc {
    font-size: 13px;
    line-height: 1.5;
    color: #666;
    margin: 0 0 14px 0;
}

.cp-mega-hero__content {
    background: rgba(255, 255, 255, 0.20);
    border-radius: 10px;
    padding: 12px 14px;
    position: relative;
    z-index: 1;
}
.cp-mega-hero__content .cp-mega-hero__desc {
    color: rgba(255, 255, 255, 0.85);
    margin-bottom: 10px;
}

.cp-mega-hero__links {
    display: flex;
    gap: 6px;
    align-items: center;
}
.cp-mega-hero__links a {
    font-size: 12px !important;
    font-weight: 600;
    letter-spacing: 0.3px;
    text-decoration: none !important;
    padding: 3px 9px;
    border-radius: 20px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    background: #fff;
    color: var(--cp-pink) !important;
    transition: all 0.2s ease;
    white-space: nowrap;
}
.cp-mega-hero__links a:hover {
    color: #fff !important;
    background: linear-gradient(135deg, #de3580, #bf6bb4);
    border-color: transparent;
    box-shadow: 0 2px 8px rgba(222, 53, 128, 0.3);
}
.cp-mega-hero__links a i {
    font-size: 10px;
    margin-left: 4px;
}
.cp-mega-hero__links .cp-mega-hero__sep {
    color: #ccc;
    font-size: 12px;
}

.cp-mega-hero::after {
    content: '';
    position: absolute;
    border-radius: 50%;
    border: 2px solid;
    opacity: 0.18;
    pointer-events: none;
    z-index: 0;
}
.cp-mega-hero--gen3::after {
    border-color: rgba(255, 255, 255, 0.15);
    width: 100px; height: 100px;
    bottom: -20px; right: 30px;
}
.cp-mega-hero--gen4::after {
    border-color: rgba(255, 255, 255, 0.15);
    width: 120px; height: 120px;
    top: -30px; right: -20px;
}

/* Bottom row: secondary product + browse-all */
.cp-mega-bottom {
    display: flex;
    border-top: 1px solid #eee;
}
.cp-mega-secondary {
    flex: 1;
    padding: 18px 28px;
    display: flex;
    align-items: center;
    gap: 16px;
    cursor: pointer;
    transition: background 0.2s ease;
    text-decoration: none !important;
    color: var(--cp-text) !important;
    border-radius: 0 0 0 12px;
    background: #f0faf3;
}
.cp-mega-secondary:hover {
    background: #e0f2e6;
    color: var(--cp-text) !important;
}
.cp-mega-secondary__icon {
    width: 38px;
    height: 38px;
    border-radius: 8px;
    background: linear-gradient(135deg, #28a745, #20c997);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 17px;
    flex-shrink: 0;
}
.cp-mega-secondary__name {
    font-size: 14px;
    font-weight: 600;
    font-family: var(--font-heading);
}
.cp-mega-secondary__desc {
    font-size: 12px;
    color: #666;
}

.cp-mega-domain {
    padding: 18px 24px;
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    transition: background 0.2s ease, color 0.2s ease;
    text-decoration: none !important;
    color: #5b8db8 !important;
    border-left: 1px solid #eee;
    border-radius: 0 0 12px 0;
    white-space: nowrap;
}
.cp-mega-domain:hover {
    background: #edf4fa;
    color: #5b8db8 !important;
}
.cp-mega-domain i { font-size: 14px; }
.cp-mega-domain span {
    font-size: 14px;
    font-weight: 600;
    font-family: var(--font-heading);
}

.cp-store-mobile {
    font-family: var(--font-heading);
    background: #fff;
    border-radius: 0 0 8px 8px;
    margin: 0;
    padding: 8px 0;
    border: 1px solid var(--cp-border);
    border-top: 0;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
}
.cp-store-mobile .dropdown-item {
    font-size: 15px;
    padding: 8px 20px;
    color: var(--cp-text);
    white-space: normal;
}
.cp-store-mobile .dropdown-item:hover {
    color: var(--cp-pink);
    background: rgba(222, 53, 128, 0.04);
}

/* Submenu (Support, Account) — matches WHMCS cp-twenty-one exactly:
   16px items (Bootstrap default inherited from .dropdown-menu 1rem), with
   a neutral very-light-gray hover (#f8f9fa — Bootstrap's stock) instead
   of pink. Text stays dark on hover so the contrast/tone matches WHMCS. */
.navbar-light #nav .dropdown-menu:not(.cp-store-dropdown-wrap) {
    border: 1px solid var(--cp-border);
    border-radius: 0 0 var(--cp-r-sm) var(--cp-r-sm);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.12);
    padding: 8px 0;
    min-width: 200px;
    margin-top: 0;
}
.navbar-light #nav .dropdown-menu:not(.cp-store-dropdown-wrap) .dropdown-item {
    font-size: 16px;
    font-family: var(--font-heading);
    font-weight: 500;
    color: var(--cp-text);
    padding: 8px 20px;
}
.navbar-light #nav .dropdown-menu:not(.cp-store-dropdown-wrap) .dropdown-item:hover,
.navbar-light #nav .dropdown-menu:not(.cp-store-dropdown-wrap) .dropdown-item:focus {
    color: var(--cp-text-heading);
    background: #f8f9fa;
}

/* ==========================================================================
   8. Buttons (pink override of Bootstrap .btn-primary)
   ========================================================================== */
.btn-primary {
    background: var(--cp-pink);
    border-color: var(--cp-pink);
    color: #ffffff;
    font-family: var(--font-heading);
    font-weight: 600;
    /* Vertical padding bumped 10 → 11 to match .btn-secondary so the
       hero CTA row reads as one consistent height — was 1px shorter
       which is barely visible on desktop but obvious on iPhone
       portrait where buttons stack vertically. */
    padding: 11px 24px;
    border-radius: 6px;
    position: relative;
    overflow: hidden;
    transition: box-shadow 0.2s ease, transform 0.15s ease;
    /* Softer at-rest shadow — more enterprise, less marketing. */
    box-shadow: 0 2px 8px rgba(222, 53, 128, 0.22);
}
/* Leading icons in primary buttons are slightly smaller and closer
   to the text than the default Bootstrap `mr-2` (0.5rem). vertical-
   align: middle centers small icons against text more reliably than
   baseline, which can float FA glyphs slightly high. The !important
   on margin-right is needed because `mr-2` is itself an !important
   utility class. */
.btn-primary > i.fas,
.btn-primary > i.far,
.btn-primary > i.fab {
    font-size: 0.88em;
    margin-right: 7px !important;
    vertical-align: middle;
    position: relative;
    top: -1px;
}
/* Shine sweep — matches WHMCS .vdc-order-btn: a translucent white gradient
   strip parked off the left edge that slides across on hover. */
.btn-primary::after {
    content: "";
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg,
                transparent 0%,
                rgba(255, 255, 255, 0.3) 50%,
                transparent 100%);
    transition: none;
    pointer-events: none;
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary:not(:disabled):not(.disabled):active {
    background: var(--cp-pink) !important;
    border-color: var(--cp-pink) !important;
    color: #ffffff !important;
    box-shadow: 0 5px 16px rgba(222, 53, 128, 0.28);
    transform: translateY(-1px);
}
.btn-primary:hover::after,
.btn-primary:focus::after {
    left: 100%;
    transition: left 0.5s ease;
}
.btn-secondary {
    background: #ffffff;
    color: var(--cp-text);
    border: 1px solid var(--cp-border-strong);
    font-family: var(--font-heading);
    font-weight: 500;
    padding: 11px 24px;
    border-radius: 6px;
    transition: box-shadow 0.2s ease, transform 0.15s ease,
                border-color 0.2s ease, color 0.2s ease;
}
.btn-secondary:hover,
.btn-secondary:focus {
    background: #ffffff;
    border-color: var(--cp-pink);
    color: var(--cp-pink);
    box-shadow: 0 8px 22px rgba(222, 53, 128, 0.18);
    transform: translateY(-1px);
}
.btn-ghost {
    background: transparent;
    color: #ffffff;
    border: 1px solid rgba(255, 255, 255, 0.45);
    font-family: var(--font-heading);
    font-weight: 500;
    padding: 11px 24px;
    border-radius: 6px;
    transition: box-shadow 0.2s ease, transform 0.15s ease,
                border-color 0.2s ease, color 0.2s ease;
}
.btn-ghost > i.fas,
.btn-ghost > i.far,
.btn-ghost > i.fab {
    font-size: 0.88em;
    margin-right: 7px !important;
    vertical-align: middle;
    position: relative;
    top: -1px;
}
.btn-ghost:hover, .btn-ghost:focus {
    border-color: #ffffff;
    color: #ffffff;
    transform: translateY(-1px);
}
.btn .fa-arrow-right,
.btn svg { margin-left: 8px; }

/* ==========================================================================
   8b. Hero intro overlay — full-screen takeover shown on first load.
   ---------------------------------------------------------------
   Layers:
     1. Fixed full-viewport white overlay sits on top of the page at
        z-index 9990, above header + everything else.
     2. Center headline "Infrastructure They Rely On" — narrative setup
        (third person: proof) that pairs with the orbiting client logos.
     3. N orbit arms, one per client logo in $CLIENT_LOGOS. Each uses
        the polar-coordinate trick `rotate(θ) translate(r) rotate(-θ)`
        so the arm ends up at position (r·cosθ, r·sinθ) with the logo
        upright. Each arm carries --i (0..N-1) and the parent orbit
        container carries --total (N). animation-delay is computed as
        calc(-42s * --i / --total), so adding or removing a logo
        redistributes spacing automatically — no CSS edit needed.
     4. Pulsing scroll indicator at the bottom-center hints at dismissal.
   On first scroll/wheel/touch/key the overlay gets .dismissed — opacity
   goes to 0, scale to 1.04, logos blur; 1.2s later the element is removed.
   Skipped entirely on viewports <900px and for prefers-reduced-motion (JS).
   ========================================================================== */
.hero-intro {
    position: fixed;
    inset: 0;
    z-index: 9990;
    background: #ffffff;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px;
    overflow: hidden;
    --orbit-radius: 360px;
    transition:
        opacity 700ms cubic-bezier(0.4, 0, 0.2, 1),
        transform 700ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hero-intro.dismissed {
    opacity: 0;
    transform: scale(1.04);
    pointer-events: none;
}
/* Fast exit used when the user skips the intro via scroll or the
   scroll button — shorter fade than .dismissed so the hero becomes
   visible as soon as possible. */
.hero-intro.skipping {
    opacity: 0;
    transform: scale(1.02);
    pointer-events: none;
    transition:
        opacity 250ms ease-out,
        transform 250ms ease-out;
}
.hero-intro.skipping .hero-intro__arm-inner {
    filter: blur(6px);
    transition: filter 250ms ease-out;
}
/* Centered crossfade stage — three absolutely-positioned items stacked
   on top of each other at the center. Each .hero-intro__stage-item
   starts at opacity 0; the JS sequencer adds/removes .is-visible to
   trigger the opacity transition (duration controlled here in CSS). */
.hero-intro__stage {
    position: relative;
    z-index: 2;
    width: min(900px, 86vw);
    height: clamp(180px, 24vh, 280px);
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}
.hero-intro__stage-item {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    opacity: 0;
    transition: opacity 250ms cubic-bezier(0.4, 0, 0.2, 1);
    text-align: center;
    max-width: 100%;
}
.hero-intro__stage-item.is-visible {
    opacity: 1;
}
.hero-intro__stage-phrase {
    font-family: var(--font-heading);
    font-size: clamp(2.5rem, 7vw, 5rem);
    font-weight: 700;
    line-height: 1.1;
    color: var(--cp-text);
    margin: 0;
    white-space: nowrap;
}
.hero-intro__emph {
    color: var(--cp-pink);
}
/* Tablet-landscape (901–1199): the default clamp(2.5rem, 7vw, 5rem)
   resolves to ~71px at iPad-landscape width, big enough that the
   headline spills out past the orbit radius and overlaps the logo
   arms. Cap at 3.75rem (60px) through this range; desktop (≥1200)
   falls back to the original 5rem max. */
@media (min-width: 901px) and (max-width: 1199px) {
    .hero-intro__stage-phrase {
        font-size: clamp(2.25rem, 6vw, 3.75rem);
    }
}
/* Suffix lives inside phrase2's emph span. It's in the DOM from the
   start so the parent container's layout is pre-reserved for "is the"
   — that way flipping opacity doesn't cause "is" to jump as the
   container re-centers. Fast 200ms fade keeps the "sounding out"
   effect snappy. */
.hero-intro__suffix {
    opacity: 0;
    transition: opacity 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hero-intro__suffix.is-visible {
    opacity: 1;
}
.hero-intro__orbit {
    position: absolute;
    inset: 0;
    pointer-events: none;
}
.hero-intro__arm {
    position: absolute;
    top: 50%;
    left: 50%;
    animation: hero-intro-orbit 42s linear infinite;
    animation-delay: calc(-42s * var(--i, 0) / var(--total, 15));
}
@keyframes hero-intro-orbit {
    from { transform: rotate(0deg)   translate(var(--orbit-radius)) rotate(0deg);    }
    to   { transform: rotate(360deg) translate(var(--orbit-radius)) rotate(-360deg); }
}
.hero-intro__arm-inner {
    transform: translate(-50%, -50%);
    transition: filter 0.9s ease-out;
}
.hero-intro.dismissed .hero-intro__arm-inner {
    filter: blur(10px);
}
.hero-intro__logo {
    height: 44px;
    width: auto;
    display: block;
    opacity: 0.88;
}
.hero-intro__scroll {
    position: absolute;
    bottom: 206px;
    left: 50%;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    border: 2px solid var(--cp-pink);
    background: rgba(255, 255, 255, 0.85);
    color: var(--cp-pink);
    font-size: 18px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    z-index: 3;
    animation: hero-intro-bounce 1.8s ease-in-out infinite;
    transition: background 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
}
.hero-intro__scroll:hover,
.hero-intro__scroll:focus {
    background: var(--cp-pink);
    color: #ffffff;
    box-shadow: 0 6px 18px rgba(222, 53, 128, 0.28);
    outline: none;
}
@keyframes hero-intro-bounce {
    0%, 100% { transform: translateX(-50%) translateY(0); }
    50%      { transform: translateX(-50%) translateY(10px); }
}
@media (max-width: 1200px) {
    .hero-intro { --orbit-radius: 300px; }
    .hero-intro__logo { height: 38px; }
}
@media (max-width: 900px) {
    /* Intro is removed entirely by site.js at this breakpoint. */
    .hero-intro { display: none; }
}
@media (prefers-reduced-motion: reduce) {
    .hero-intro { display: none; }
}

/* ==========================================================================
   9. Hero section
   ========================================================================== */
/* Hero reveal — when the hero intro overlay runs, site.js adds
   .is-pending-reveal to .hero before the first paint to hide the hero
   content (opacity 0, scaled down, nudged down) so the user never sees
   it flash. When the intro dismisses, .is-revealed is added, which
   fires a staggered keyframe animation (h1 → lead → CTAs) that grows
   the content from "depth" into its final position over 900ms each.
   animation-fill-mode: both keeps the content at the final state after
   the animation completes. Skipped automatically on mobile + reduced-
   motion via the JS branch that doesn't add .is-pending-reveal at all. */
.hero.is-pending-reveal h1,
.hero.is-pending-reveal .lead,
.hero.is-pending-reveal .cta-row {
    opacity: 0;
    transform: scale(0.88) translateY(24px);
}
.hero.is-revealed h1 {
    animation: hero-reveal 900ms cubic-bezier(0.22, 1, 0.36, 1) 0ms both;
}
.hero.is-revealed .lead {
    animation: hero-reveal 900ms cubic-bezier(0.22, 1, 0.36, 1) 180ms both;
}
.hero.is-revealed .cta-row {
    animation: hero-reveal 900ms cubic-bezier(0.22, 1, 0.36, 1) 360ms both;
}
@keyframes hero-reveal {
    from {
        opacity: 0;
        transform: scale(0.88) translateY(24px);
    }
    to {
        opacity: 1;
        transform: scale(1) translateY(0);
    }
}
/* Home-page hero. Underlying colors: a barely-tinted off-white base
   so the section separates from the pure-white content below it, plus
   a directional diagonal wash (pink top-left → slate bottom-right) to
   give the canvas brand-aligned movement. The motion/geometry on top
   of this canvas comes from `.hero__canvas` (particle network, wired
   up in site.js — see initHeroParticles) — the static wash is the
   quieter foundation the particles float over.
   `overflow: hidden` clips any particle that drifts past the section
   edge to the hero bounds. Padding tightened from 120/110 → 88/72. */
.hero {
    padding: 98px 0 82px;
    text-align: center;
    position: relative;
    overflow: hidden;
    background-color: #ffffff;
}
/* Viewport-filling hero on desktop. First paint lands the bottom of
   the hero at the browser fold, with a 600px floor so short monitors
   don't get a squished hero. Chrome deduction (154px) = 94px expanded
   sticky header + 60px sticky breadcrumb. Flex-column + justify-
   content:center vertically centers the text block when the hero is
   taller than the natural content height. */
@media (min-width: 769px) {
    .hero {
        display: flex;
        flex-direction: column;
        justify-content: center;
        min-height: max(600px, calc(100vh - 154px));
    }
}
/* Canvas sits behind the content: `inset: 0` fills the section,
   `pointer-events: none` lets clicks pass through to the CTAs. Mouse
   tracking uses the parent `.hero` element's mousemove instead of the
   canvas so pointer-events don't need to be re-enabled. */
.hero__canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    pointer-events: none;
}
/* Stack the content container above the canvas. */
.hero > .container {
    position: relative;
    z-index: 1;
}
.hero .eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 18px;
    background: rgba(222, 53, 128, 0.08);
    border: 1px solid rgba(222, 53, 128, 0.22);
    border-radius: 999px;
    font-size: 0.85rem;
    color: var(--cp-pink);
    font-weight: 600;
    margin-bottom: 26px;
    font-family: var(--font-heading);
}
.hero .eyebrow .dot {
    width: 8px;
    height: 8px;
    background: var(--cp-pink);
    border-radius: 50%;
    box-shadow: 0 0 0 4px rgba(222, 53, 128, 0.18);
}
.hero h1 { max-width: 920px; margin: 0 auto 24px; }
.hero h1 .highlight {
    background: var(--cp-gradient-default);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
}
.hero .lead {
    max-width: 680px;
    margin: 0 auto 44px;
    font-size: clamp(1.1rem, 1.5vw, 1.3rem);
    color: var(--cp-text-muted);
}
.hero .cta-row {
    display: flex;
    gap: 16px;
    justify-content: center;
    flex-wrap: wrap;
}
/* Capability trust line — single middot-separated row of noun phrases
   under the CTAs. Heading-font + uppercase + wide tracking pushes it
   into the "metadata / breadcrumb" visual register so it supports the
   hero without competing with the CTAs or the headline. */
.hero__capabilities {
    margin: 52px 0 0;
    font-family: var(--font-heading);
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--cp-text-muted);
    opacity: 0.78;
}
@media (max-width: 768px) {
    .hero { padding: 64px 0 48px; }
    .hero__capabilities { font-size: 0.72rem; margin-top: 40px; }
}

/* Each capability phrase keeps its own integrity — never breaks
   mid-phrase. Middle-dot separators are generated via ::before on
   items 2+ rather than being literal text in the HTML, so at narrow
   widths we can hide the separator that would sit in front of the
   third item when it wraps to its own line. */
.hero__capabilities-item {
    white-space: nowrap;
}
.hero__capabilities-item + .hero__capabilities-item::before {
    content: "·";
    margin: 0 0.5em;
    white-space: normal;
}
@media (max-width: 600px) {
    .hero__capabilities-item:nth-child(3) {
        display: block;
        text-align: center;
    }
    .hero__capabilities-item:nth-child(3)::before {
        content: "";
    }
}

/* Coming Soon placeholder — used on pages whose body isn't built yet.
   Fills most of the viewport between header and footer and vertically
   centers whatever lives inside. Headline is the gradient `.highlight`. */
.hero--coming-soon {
    min-height: calc(100vh - 340px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 60px 0;
    text-align: center;
}
.hero--coming-soon h1 {
    font-size: clamp(3rem, 7vw, 6rem);
    margin: 0;
}
@media (max-width: 768px) {
    .hero--coming-soon { min-height: 55vh; }
}

/* Error pages (/400, /403, /404, /500, /503) — reuses the home-page
   `.hero` styling, just scaled up and vertically centered so the error
   code reads like a landing-page headline rather than a server dump.
   Structure: <h1>{code}<br><span class="highlight">{title}</span></h1>
   — the `.highlight` gradient clip is inherited from `.hero h1 .highlight`. */
.hero--error {
    min-height: calc(100vh - 340px);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 60px 0;
}
.hero--error h1 {
    font-size: clamp(3.5rem, 9vw, 7rem);
    line-height: 1.05;
    margin: 0 auto 28px;
}
.hero--error h1 .highlight {
    /* Second line (the human-readable title) reads smaller than the
       numeric code above it — mirrors "Infrastructure / You Can Rely On"
       proportions where the gradient line anchors the meaning. */
    display: inline-block;
    font-size: 0.62em;
    line-height: 1.15;
    margin-top: 4px;
}
@media (max-width: 768px) {
    .hero--error { min-height: 55vh; }
}

/* ==========================================================================
   9b. Client logo band — marquee strip under the hero. Each logo is a
   pre-normalized 480x160 PNG with content scaled to fit 440x120
   centered, so a single CSS height value renders all of them uniformly.
   The row is duplicated in the markup (second copy aria-hidden) and
   translated -50% in a linear animation, producing a seamless loop
   without the list popping at the join. Track has a CSS mask that
   fades the left and right edges so logos appear to enter/exit smoothly
   instead of snapping at the viewport boundary. Pauses on hover.
   ========================================================================== */
.client-logos {
    padding: 22px 0 26px;
    background: #ffffff;
    border-top: 1px solid var(--cp-border);
    border-bottom: 1px solid var(--cp-border);
    overflow: hidden;
}
.client-logos__label {
    /* Flex row with fading decorative lines flanking the text on
       both sides via ::before/::after. The gradient-to-transparent
       endings keep them feeling soft rather than hard rules. */
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 18px;
    text-transform: uppercase;
    font-family: var(--font-heading);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.22em;
    color: var(--cp-text-muted);
    margin: 0 0 14px;
}
.client-logos__label::before,
.client-logos__label::after {
    content: '';
    display: block;
    width: 56px;
    height: 1px;
    background: linear-gradient(
        to right,
        transparent 0%,
        rgba(122, 139, 160, 0.5) 50%,
        transparent 100%
    );
}
.client-logos__track {
    overflow: hidden;
    /* Let vertical page-scroll gestures pass through the marquee
       while routing horizontal touches to our drag/flick handlers
       in site.js. Without this, touching the marquee would either
       (a) scroll the page horizontally if the browser's default
       kicks in, or (b) block vertical page scroll on narrow
       viewports where the marquee spans most of the visible area. */
    touch-action: pan-y;
    -webkit-mask-image: linear-gradient(
        to right,
        transparent 0,
        #000 96px,
        #000 calc(100% - 96px),
        transparent 100%
    );
            mask-image: linear-gradient(
        to right,
        transparent 0,
        #000 96px,
        #000 calc(100% - 96px),
        transparent 100%
    );
}
.client-logos__row {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    width: max-content;
    gap: 56px;
    /* CSS fallback animation — site.js disables this on init and drives
       transform manually so it can ramp direction on mouse hover. If JS
       fails or is disabled, the CSS animation keeps the marquee moving. */
    animation: client-logos-marquee 60s linear infinite;
    will-change: transform;
}
@keyframes client-logos-marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}
/* .client-logos__item is the <a> wrapper around each <img>. Static
   (no hover effects) — the marquee just scrolls. */
.client-logos__item {
    display: block;
    flex-shrink: 0;
    text-decoration: none;
}
.client-logos__item img {
    height: 56px;
    width: auto;
    display: block;
    pointer-events: none;
}
@media (max-width: 640px) {
    .client-logos { padding: 32px 0 26px; }
    .client-logos__row { gap: 36px; animation-duration: 45s; }
    .client-logos__item img { height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
    .client-logos__row { animation: none; }
    .client-logos__row > [aria-hidden="true"] { display: none; }
}

/* ==========================================================================
   10. Section headers
   ========================================================================== */
.section-header { text-align: center; max-width: 720px; margin: 0 auto 56px; }
.section-header .eyebrow {
    display: inline-block;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--cp-pink);
    font-weight: 700;
    margin-bottom: 14px;
    font-family: var(--font-heading);
}
.section-header p {
    color: var(--cp-text-muted);
    font-size: 1.1rem;
    margin-top: 16px;
}

/* ==========================================================================
   11. Services grid — LEGACY / SIMPLE VARIANT
   ----------------------------------------------------------------------------
   These are the flat white `.service-card` tiles that shipped on the MVP
   home page. The current home page uses `.cp-store-card` (section 11b
   below) to match the WHMCS store-browse layout. These rules are kept
   intentionally because the user may want to revive the simple look for
   a lighter secondary page or as an alternate home treatment. Named
   effectively as the "simple" variant — nothing currently references
   them, but they stay idle rather than being deleted.
   ========================================================================== */
.services { background: var(--cp-bg-alt); }
.service-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 24px;
}
.service-card {
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r);
    padding: 32px;
    box-shadow: var(--cp-shadow-card);
    transition: transform 0.25s ease, box-shadow 0.25s ease, border-color 0.25s ease;
    text-decoration: none;
    color: inherit;
    display: flex;
    flex-direction: column;
}
.service-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--cp-shadow-card-hover);
    border-color: rgba(222, 53, 128, 0.3);
    color: inherit;
    text-decoration: none;
}
.service-card__icon {
    width: 54px;
    height: 54px;
    border-radius: 14px;
    background: rgba(222, 53, 128, 0.08);
    color: var(--cp-pink);
    display: grid;
    place-items: center;
    margin-bottom: 22px;
    font-size: 22px;
}
.service-card h3 { margin-bottom: 10px; }
.service-card p { color: var(--cp-text-muted); font-size: 0.95rem; margin-bottom: 0; }
.service-card .arrow {
    margin-top: 22px;
    color: var(--cp-pink);
    font-weight: 600;
    font-size: 0.9rem;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: gap 0.2s ease;
    font-family: var(--font-heading);
}
.service-card:hover .arrow { gap: 10px; }

/* ==========================================================================
   11b. Store cards — cp-store-card / cp-store-browse
   ----------------------------------------------------------------------------
   Ported verbatim from cp-twenty-one/custom.css ~L2833-3122. These are
   the gradient product cards on the WHMCS store-browse page: gen3 (GPC)
   purple-navy, gen4 (MCC) navy-pink, veeam green, plus a default slate.
   Each card has a feature pill row at the top, a "CATEGORY" eyebrow, a
   product name, a white semi-transparent inner panel with description
   and "Pay As You Go / Dedicated Capacity" pill links, then a browse
   footer. Used on the home page and category pages.
   ========================================================================== */
.cp-store-browse {
    max-width: 900px;
    margin: 0 auto;
    padding: 20px 0;
}
.cp-store-browse__header {
    text-align: center;
    margin-bottom: 30px;
}
.cp-store-browse__header h1 {
    font-size: 28px;
    margin-bottom: 6px;
}
.cp-store-browse__header p {
    font-family: var(--font-heading);
    color: #888;
    font-size: 15px;
    margin: 0;
}
.cp-store-browse__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}
/* 2-up grids (MCC + GPC on home, etc.) tuck in from the container
   edges so the two cards don't sprawl across the full width. The
   --three variant for 3-up grids opts out of this max-width via the
   :not() selector — 3 cards across naturally need the full width. */
.cp-store-browse__grid:not(.cp-store-browse__grid--three) {
    max-width: 980px;
    margin-left: auto;
    margin-right: auto;
}
/* Center the last card when there's an odd number */
.cp-store-browse__grid > .cp-store-card:last-child:nth-child(odd) {
    grid-column: 1 / -1;
    max-width: calc(50% - 10px);
    justify-self: center;
}
@media (max-width: 767px) {
    .cp-store-browse__grid {
        grid-template-columns: 1fr;
    }
    .cp-store-browse__grid > .cp-store-card:last-child:nth-child(odd) {
        max-width: 100%;
    }
}

/* Card base */
.cp-store-card {
    display: flex;
    flex-direction: column;
    padding: 28px 28px 20px;
    border-radius: 12px;
    position: relative;
    overflow: hidden;
    text-decoration: none !important;
    color: inherit !important;
    transition: all 0.3s ease;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
    cursor: pointer;
}
/* Clean lift — tokens ported verbatim from WHMCS
   `/var/www/whmcs/html/templates/cp-twenty-one/css/custom.css`
   (.cp-store-card:hover on store-browse.php). A 2px upward nudge
   plus a neutral dark shadow reads as "the card lifted off the
   page" without the pink halo competing for attention.
   Gated behind `@media (hover: hover)` so the effect only fires on
   pointer-equipped devices (mouse, trackpad, stylus). Touch-only
   phones and tablets skip it — otherwise a tap would briefly trigger
   the lift before the navigation, which reads as a glitch.
   The second selector is required because the home-page cards carry
   `data-reveal` — the [data-reveal].is-revealed rule later in this
   file sets `transform: translateY(0)` at equal specificity, so
   without this bump the hover transform gets overridden by source
   order and the card doesn't actually lift. */
@media (hover: hover) {
    .cp-store-card:hover,
    .cp-store-card[data-reveal].is-revealed:hover {
        box-shadow: 0 6px 24px rgba(0, 0, 0, 0.15);
        transform: translateY(-2px);
    }
}
.cp-store-card::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    opacity: 0;
    transition: opacity 0.3s ease;
    z-index: 0;
}
.cp-store-card:hover::before {
    opacity: 1;
}
.cp-store-card > * {
    position: relative;
    z-index: 1;
}
.cp-store-card::after {
    content: '';
    position: absolute;
    border-radius: 50%;
    border: 2px solid rgba(255, 255, 255, 0.15);
    opacity: 0.18;
    pointer-events: none;
    z-index: 0;
    width: 120px;
    height: 120px;
    bottom: -30px;
    right: -10px;
}

/* Gradient variants */
.cp-store-card--gen3 {
    background: linear-gradient(135deg, #a0558a 0%, #5a7a9a 60%, #1d3a5b 100%);
}
.cp-store-card--gen3::before {
    background: linear-gradient(135deg, #b060a0 0%, #6a8cac 60%, #253f60 100%);
}
.cp-store-card--gen4 {
    background: linear-gradient(135deg, #1a3050 0%, #4d1230 45%, #de3580 100%);
}
.cp-store-card--gen4::before {
    background: linear-gradient(135deg, #2a4060 0%, #5d2240 45%, #ee4590 100%);
}
.cp-store-card--veeam {
    background: linear-gradient(135deg, #1b4332 0%, #2d6a4f 50%, #40916c 100%);
}
.cp-store-card--veeam::before {
    background: linear-gradient(135deg, #2b5342 0%, #3d7a5f 50%, #50a17c 100%);
}
.cp-store-card--veeam-teal {
    background: linear-gradient(135deg, #1b4343 0%, #2d6a6a 50%, #409191 100%);
}
.cp-store-card--veeam-teal::before {
    background: linear-gradient(135deg, #2b5353 0%, #3d7a7a 50%, #50a1a1 100%);
}
.cp-store-card--veeam-blue {
    background: linear-gradient(135deg, #1b3143 0%, #2d4e6a 50%, #406f91 100%);
}
.cp-store-card--veeam-blue::before {
    background: linear-gradient(135deg, #2b4153 0%, #3d5e7a 50%, #507fa1 100%);
}
.cp-store-card--default {
    background: linear-gradient(135deg, #2c3e50 0%, #4a6274 50%, #7a9dbe 100%);
}
.cp-store-card--default::before {
    background: linear-gradient(135deg, #3c4e60 0%, #5a7284 50%, #8aadce 100%);
}

/* Top row: icon + features */
.cp-store-card__toprow {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 16px;
}
.cp-store-card__icon {
    width: 48px;
    height: 48px;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    color: #fff;
    flex-shrink: 0;
    border: 2px solid rgba(255, 255, 255, 0.35);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}
.cp-store-card--gen3 .cp-store-card__icon { background: linear-gradient(135deg, #de3580, #bf6bb4); }
.cp-store-card--gen4 .cp-store-card__icon { background: linear-gradient(135deg, #bf6bb4, #8e44ad); }
.cp-store-card--veeam .cp-store-card__icon { background: linear-gradient(135deg, #28a745, #20c997); }
.cp-store-card--veeam-teal .cp-store-card__icon { background: linear-gradient(135deg, #20c997, #17a2b8); }
.cp-store-card--veeam-blue .cp-store-card__icon { background: linear-gradient(135deg, #17a2b8, #3b82f6); }
.cp-store-card--default .cp-store-card__icon { background: linear-gradient(135deg, #4a6274, #7a9dbe); }

/* Feature pills */
.cp-store-card__features {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.cp-store-card__feat {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.3px;
    text-transform: uppercase;
    padding: 3px 9px;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.15);
    color: rgba(255, 255, 255, 0.8);
    white-space: nowrap;
    line-height: 1.4;
}

/* Gen label / eyebrow */
.cp-store-card__gen {
    font-family: 'Share Tech', monospace;
    font-size: 11px;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    margin-bottom: 4px;
    color: rgba(255, 255, 255, 0.85);
}

/* Product name */
.cp-store-card__name {
    font-size: 18px;
    font-weight: 700;
    color: #fff;
    margin-bottom: 10px;
    font-family: var(--font-heading);
}

/* Inner content panel */
.cp-store-card__content {
    flex: 1;
    background: rgba(255, 255, 255, 0.20);
    border-radius: 10px;
    padding: 12px 14px;
}
.cp-store-card__desc {
    font-family: var(--font-heading);
    font-size: 13px;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.85);
    margin: 0 0 10px 0;
}
.cp-store-card__content .cp-store-card__desc:last-child {
    margin-bottom: 0;
}

/* Billing model pill links */
.cp-store-card__links {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
}
.cp-store-card__pill {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.3px;
    text-decoration: none !important;
    padding: 3px 9px;
    border-radius: 20px;
    border: 1px solid rgba(255, 255, 255, 0.3);
    background: #fff;
    color: #de3580;
    white-space: nowrap;
    transition: all 0.2s ease;
}
.cp-store-card__pill:hover {
    color: #fff !important;
    background: linear-gradient(135deg, #de3580, #bf6bb4);
    border-color: transparent;
    box-shadow: 0 2px 8px rgba(222, 53, 128, 0.3);
}
.cp-store-card__pill i {
    font-size: 10px;
    margin-left: 4px;
}
.cp-store-card__sep {
    color: #ccc;
    font-size: 12px;
}
@media (max-width: 991px) and (min-width: 768px) {
    .cp-store-card__pill { font-size: 10px; padding: 2px 7px; }
    .cp-store-card__pill i { font-size: 8px; margin-left: 3px; }
    .cp-store-card__sep { font-size: 10px; }
    .cp-store-card__name { font-size: 15px; }
    .cp-store-card--veeam .cp-store-card__name { font-size: 13px; }
    .cp-store-card--veeam .cp-store-card__pill { font-size: 9px; padding: 2px 6px; }
    .cp-store-card--veeam .cp-store-card__pill i { font-size: 7px; }
    .cp-store-card--veeam .cp-store-card__sep { font-size: 9px; }
}

/* Footer: starting-from pricing on the left, browse link on the right.
   Palette adapted for dark gradient cards — see WHMCS vdc.css for the
   source pattern (.vdc-card-footer / .vdc-footer-pricing). */
.cp-store-card__footer {
    margin-top: 14px;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}
.cp-store-card__pricing {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px;
}
.cp-store-card__pricing-label {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: rgba(255, 255, 255, 0.65);
    margin-right: 2px;
}
.cp-store-card__price {
    font-family: var(--font-heading);
    font-size: 1.6em;
    font-weight: 700;
    color: #fff;
    line-height: 1;
}
.cp-store-card__cycle {
    font-size: 12px;
    color: rgba(255, 255, 255, 0.7);
    margin-left: 1px;
}
.cp-store-card__browse {
    font-family: var(--font-heading);
    font-size: 13px;
    font-weight: 600;
    color: #fff;
    text-decoration: none !important;
    transition: color 0.2s ease;
}
.cp-store-card__browse i {
    margin-left: 4px;
    font-size: 11px;
    transition: transform 0.2s ease;
}
.cp-store-card:hover .cp-store-card__browse {
    color: #fff;
}
.cp-store-card:hover .cp-store-card__browse i {
    transform: translateX(3px);
}

/* Section wrapper the home page uses to hold grids of these cards */
.cp-store-section {
    padding: 72px 0;
}
.cp-store-section:nth-of-type(even) {
    background: var(--cp-bg-alt);
}
.cp-store-section__intro {
    text-align: center;
    max-width: 760px;
    margin: 0 auto 48px;
}
/* Short supporting line below the cards — centered, separated from the
   card row by a thin hairline divider. Normal weight + slate text reads
   as a quiet addendum without italic flourish. */
.cp-store-section__note {
    text-align: center;
    max-width: 660px;
    margin: 48px auto 0;
    padding-top: 26px;
    border-top: 1px solid var(--cp-border);
    font-size: 0.88rem;
    line-height: 1.6;
    color: var(--cp-text-muted);
}

/* Wing-shaped CTA cluster under the Enterprise Cloud cards on the
   home page: stock .btn-secondary on each side flanking a center
   "medallion" — pink-mauve-slate gradient outer ring around a
   deep navy core. The gradient ring carries the MCC→GPC color
   handshake; the dark core gives white text strong contrast and
   reads more "enterprise" / less "candy." At ≤767px the center
   moves to its own row on top with the two side buttons sharing
   a single row underneath. */
.platform-wings {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 28px;
    margin: 36px 0 0;
    flex-wrap: wrap;
}

.platform-wings__center {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 124px;
    height: 124px;
    border-radius: 50%;
    background: linear-gradient(135deg, #de3580 0%, #a0558a 50%, #5a7a9a 100%);
    color: #ffffff;
    text-decoration: none;
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.18);
    line-height: 1.15;
    text-align: center;
    flex-shrink: 0;
    position: relative;
    transition: transform .18s ease, box-shadow .18s ease;
    overflow: hidden;
}
/* Inner dark core sits inside the gradient ring. Pseudo-element so
   we keep a single <a> tag (semantics + click target intact). 5px
   inset on all sides leaves a 5px-wide gradient ring visible. */
.platform-wings__center::before {
    content: '';
    position: absolute;
    top: 5px; left: 5px; right: 5px; bottom: 5px;
    border-radius: 50%;
    background: #1a3050;
    z-index: 0;
}
.platform-wings__center:hover,
.platform-wings__center:focus-visible {
    transform: translateY(-2px);
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.24);
    color: #ffffff;
    text-decoration: none;
}

.platform-wings__compare-line {
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 0.95rem;
    letter-spacing: 0.02em;
    position: relative;
    z-index: 1;
}
.platform-wings__vs {
    font-weight: 400;
    font-style: italic;
    opacity: 0.92;
}
.platform-wings__sub {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    opacity: 0.92;
    position: relative;
    z-index: 1;
}
/* Spacing between the three stacked lines (Compare / MCC & GPC /
   Platforms). Gap on the flex parent applies uniformly above and
   below the middle line — no per-line margin tuning needed. */
.platform-wings__center { gap: 3px; }

@media (max-width: 767px) {
    /* Mobile layout: circle on the left, two stacked buttons on the
       right. Two-column grid where the circle spans both rows of the
       right column. Font inside circle drops one notch since the disc
       itself is smaller at this breakpoint. */
    .platform-wings {
        display: grid;
        grid-template-columns: auto 1fr;
        grid-template-rows: auto auto;
        column-gap: 16px;
        row-gap: 10px;
        margin-top: 32px;
        flex-wrap: initial;
        align-items: center;
        max-width: 380px;
        margin-left: auto;
        margin-right: auto;
    }
    .platform-wings__center {
        grid-column: 1;
        grid-row: 1 / 3;
        width: 104px;
        height: 104px;
    }
    .platform-wings__center .platform-wings__compare-line {
        font-size: 0.85rem;
    }
    .platform-wings__center .platform-wings__sub {
        font-size: 0.62rem;
        letter-spacing: 0.12em;
    }
    .platform-wings .btn-secondary {
        width: 100%;
        text-align: center;
    }
}
.cp-store-section__eyebrow {
    display: inline-block;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--cp-pink);
    font-weight: 700;
    margin-bottom: 14px;
    font-family: var(--font-heading);
}
.cp-store-section__intro h2 {
    margin-bottom: 16px;
}
.cp-store-section__intro p {
    color: var(--cp-text-muted);
    font-size: 1.05rem;
}

/* 3-up grid override for Data Protection section */
.cp-store-browse__grid--three {
    grid-template-columns: repeat(3, 1fr);
}
/* Cancel the 2-col "center last odd card" rule inherited from the base
   grid — for 3-across layouts the 3rd card should stay inline at
   column 3, not span full width centered. */
.cp-store-browse__grid--three > .cp-store-card:last-child:nth-child(odd) {
    grid-column: auto;
    max-width: none;
    justify-self: stretch;
}
/* Tablet (768–991px): 2 columns with the third card centered on its
   own row at half-width. Previously this breakpoint dropped straight
   from 3-up to 1-up, which made full-card widths absurdly wide on
   tablets (e.g. iPad portrait at ~768px). 2+1 keeps each card
   readable and mirrors the 2-up grid used elsewhere on the page. */
@media (max-width: 991px) {
    .cp-store-browse__grid--three {
        grid-template-columns: 1fr 1fr;
    }
    .cp-store-browse__grid--three > .cp-store-card:last-child:nth-child(odd) {
        grid-column: 1 / -1;
        max-width: calc(50% - 10px);
        justify-self: center;
    }
}
/* Phone (<= 767px): single column stack, cards fill the container. */
@media (max-width: 767px) {
    .cp-store-browse__grid--three {
        grid-template-columns: 1fr;
    }
    .cp-store-browse__grid--three > .cp-store-card,
    .cp-store-browse__grid--three > .cp-store-card:last-child:nth-child(odd) {
        grid-column: auto;
        max-width: 100%;
        justify-self: stretch;
    }
}
/* Wider container for the cards section so they breathe. Applies to
   both home-page .cp-store-section blocks and the .portfolio-backup
   block on /services-and-solutions, which reuses the same .cp-store-
   browse + .cp-store-card 3-up grid. */
.cp-store-section .cp-store-browse,
.portfolio-backup .cp-store-browse {
    max-width: 1080px;
}

/* ==========================================================================
   11c. Home page narrative sections
   Intro strip, section lead, why-us pillars, and the "Designed for
   Predictability" platform principle band. All quiet, understated,
   enterprise-tone layouts — no hero gradients, no decorative chrome.
   ========================================================================== */

/* Section lead — merged positioning block that sits directly under the
   hero. Full .platform-principle treatment: dark footer-tone background
   with the same radial-gradient overlay, eyebrow → headline → lead →
   body typographic rhythm, white text hierarchy. */
.section-lead {
    background: var(--cp-bg-footer);
    color: rgba(255, 255, 255, 0.88);
    padding: 96px 0 88px;
    text-align: center;
    position: relative;
    z-index: 1;
    overflow: hidden;
}
.section-lead::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse at 20% 40%, rgba(222, 53, 128, 0.08) 0%, transparent 55%),
        radial-gradient(ellipse at 80% 60%, rgba(122, 157, 190, 0.06) 0%, transparent 55%);
    pointer-events: none;
}
.section-lead > .container { position: relative; }
.section-lead__inner {
    max-width: 800px;
    margin: 0 auto;
}
.section-lead__eyebrow {
    display: inline-block;
    font-family: var(--font-heading);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--cp-pink-light);
    margin-bottom: 18px;
}
.section-lead h2 {
    margin-bottom: 24px;
    font-size: clamp(2rem, 3.5vw, 2.9rem);
    color: #ffffff;
}
.section-lead__lead {
    font-family: var(--font-heading);
    font-size: 1.3rem;
    font-weight: 600;
    color: #ffffff;
    line-height: 1.4;
    max-width: 680px;
    margin: 0 auto 22px;
}
.section-lead p:not(.section-lead__lead) {
    font-size: 1.05rem;
    line-height: 1.7;
    color: rgba(255, 255, 255, 0.78);
    max-width: 680px;
    margin: 0 auto;
}
/* Body text sits at 78% opacity, so plain bold barely registers. Lift
   <strong> emphasis to full white so the bolded phrases actually pop. */
.section-lead p strong {
    color: #ffffff;
    font-weight: 700;
}

/* Infrastructure jump-links under the section body — mirrors the
   hero's .cta-row layout so the Infrastructure trio of buttons
   (Platform Architecture, Our Network, Data Centers) reads with
   the same rhythm as the top-of-page hero CTAs. Scoped to
   .section-lead so it doesn't leak into other .cta-row uses. */
.section-lead .cta-row {
    display: flex;
    gap: 16px;
    justify-content: center;
    flex-wrap: wrap;
    margin-top: 32px;
}
/* Phone-portrait pyramid layout: Platform Architecture on its own
   row (full width), Our Network + Data Centers side-by-side on
   row 2. Without this, all three buttons stack as a vertical list
   which feels visually heavy on a small screen. */
@media (max-width: 480px) {
    .section-lead .cta-row {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 10px;
    }
    .section-lead .cta-row > a:nth-child(1) { grid-column: 1 / -1; }
}

/* Why Cloud Propeller — 6-pillar grid matching the WHMCS Quick Links
   tiles (see cp-twenty-one/css/custom.css .action-icon-btns): white card,
   4px brand gradient bar across the top via ::before, subtle lift on hover,
   pink border + pink shadow. Numbers replace the icon glyph.
   Locked to 3x2 at desktop, 2x3 at tablet, 1x6 on phones. */
.why-cp { background: var(--cp-bg-alt); }
.pillars-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
    max-width: 1240px;
    margin: 0 auto;
}
@media (max-width: 991px) {
    .pillars-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
    .pillars-grid { grid-template-columns: 1fr; }
}
.pillar {
    position: relative;
    background: #fff;
    border: 1px solid #e8e8e8;
    border-radius: 10px;
    padding: 30px 22px 24px;
    text-align: center;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
    transition: all 0.3s ease;
    overflow: hidden;
}
.pillar::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: var(--cp-gradient-default);
    border-radius: 10px 10px 0 0;
}
.pillar:hover {
    border-color: #de3580;
    box-shadow: 0 4px 20px rgba(222, 53, 128, 0.15);
    transform: translateY(-2px);
}
.pillar__number {
    font-family: var(--font-heading);
    font-size: 2.4rem;
    font-weight: 700;
    line-height: 1;
    color: #bf6bb4;
    margin: 6px 0 12px;
    transition: color 0.3s ease;
}
.pillar:hover .pillar__number {
    color: #de3580;
}
.pillar h3 {
    margin: 0 0 10px;
    font-size: 1.1rem;
    line-height: 1.3;
    color: #2c3e50;
}
.pillar p {
    color: var(--cp-text-muted);
    font-size: 0.92rem;
    line-height: 1.6;
    margin: 0;
}

/* Platform Principle — quiet full-width statement band */
.platform-principle {
    background: var(--cp-bg-footer);
    color: rgba(255, 255, 255, 0.88);
    padding: 100px 0;
    text-align: center;
    position: relative;
    z-index: 1;
    overflow: hidden;
}
.platform-principle::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse at 20% 40%, rgba(222, 53, 128, 0.08) 0%, transparent 55%),
        radial-gradient(ellipse at 80% 60%, rgba(122, 157, 190, 0.06) 0%, transparent 55%);
    pointer-events: none;
}
.platform-principle__inner {
    position: relative;
    max-width: 800px;
    margin: 0 auto;
}
.platform-principle__eyebrow {
    display: inline-block;
    font-family: var(--font-heading);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--cp-pink-light);
    margin-bottom: 18px;
}
.platform-principle h2 {
    color: #ffffff;
    margin-bottom: 24px;
    font-size: clamp(2rem, 3.5vw, 3rem);
}
.platform-principle__lead {
    font-family: var(--font-heading);
    font-size: 1.3rem;
    font-weight: 600;
    color: #ffffff;
    margin-bottom: 20px;
    line-height: 1.4;
}
/* Empty anchor element used to land deep-links at the top of a section
   without putting the id on the section itself (which only allows one
   id) and without putting it on a child mid-section element (which
   would scroll halfway down). Drop multiple .section-anchor spans —
   one per fragment — as siblings just before the section. zero height,
   aria-hidden, but the scroll-margin-top here lifts the scroll target
   so it lands below the sticky header (70px) + breadcrumb (~48px)
   chrome with a few px of breathing room. */
.section-anchor {
    display: block;
    height: 0;
    scroll-margin-top: 54px;
}
/* Per-anchor override: #hpe-alletra lands the HPE storage-vendor
   block on /platform-architecture, but the default 54px offset
   scrolled past the section's H2 and Ceph context. Bumping the
   offset lifts the landing position so the section header stays
   visible and the HPE block sits ~mid-viewport instead of at the
   top edge. */
#hpe-alletra { scroll-margin-top: 260px; }

/* Native #hash scroll into an .arch-section h2 — push the landing
   position up 200px so the section's eyebrow + meta block stay
   visible above the H2 when a cross-page link arrives at the section.
   Doesn't affect the TOC click handler (which scrolls to the eyebrow
   element directly via JS, bypassing scroll-margin-top entirely).
   First use: cross-page links from /platform-architecture →
   /network-architecture#low-latency-cut-through-eastwest-fabric and
   /network-architecture#designed-for-continuous-network-availability. */
.arch-section h2 {
    scroll-margin-top: 200px;
}

/* Anchors placed INSIDE a .consumption-model card (as a zero-height
   first child so the grid layout stays intact) need a different
   offset. With the 54px default the card lands too low — the section
   intro above still eats ~200px by the time scroll settles, and the
   card title tucks behind the sticky breadcrumb. Desktop carries
   more chrome (taller header) so it needs a slightly larger bump. */
.consumption-model > .section-anchor {
    scroll-margin-top: 180px;
}
@media (min-width: 1200px) {
    .consumption-model > .section-anchor {
        scroll-margin-top: 200px;
    }
}

/* Body paragraphs in .platform-principle. Excludes specialty paragraph
   variants that have their own dedicated styling:
     .platform-principle__lead         — larger lead statement
     .architecture-visual__caption     — photo metadata
     .single-pane-callout__lead        — pink-bordered callout heading
     .single-pane-callout__body        — pink-bordered callout body
   Adding new <p> variants in any platform-principle child means adding
   them to this :not() chain so this generic rule doesn't ambush their
   intended styling. The component-class styling itself stays authoritative
   for portability — drop the callout into a different section without
   a competing body rule and it renders right out of the box. */
.platform-principle p:not(.platform-principle__lead):not(.architecture-visual__caption):not(.single-pane-callout__lead):not(.single-pane-callout__body) {
    font-size: 1.05rem;
    line-height: 1.7;
    color: rgba(255, 255, 255, 0.78);
    max-width: 680px;
    margin: 0 auto;
}
/* Body sits at 78% white opacity, so plain bold barely registers
   against it. Lift <strong> to full white + heavy weight so emphasized
   spec terms (e.g. "DDR5 ECC", "400G networking") pop on dark bg.
   Mirrors the .section-lead p strong rule on the home page. */
.platform-principle p strong {
    color: #ffffff;
    font-weight: 700;
}

/* Split variant: text on the left, screenshot(s) on the right.
   Overrides the centered defaults set above by .platform-principle. */
.platform-principle--split { text-align: left; }
.platform-principle__split {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: 56px;
    align-items: center;
}
.platform-principle__text { max-width: 520px; }
.platform-principle--split .platform-principle__lead { margin: 0 0 20px; }
.platform-principle--split .platform-principle p:not(.platform-principle__lead),
.platform-principle--split p:not(.platform-principle__lead) {
    margin: 0;
    max-width: none;
}
.platform-principle__visual { position: relative; }
.platform-principle__cta { margin-top: 28px; }

/* Architecture visual — used on /mission-critical-compute (and any
   other product page that needs a single-image hero with a CTA below).
   Mirrors the home-page Management Experience pattern: the picture
   uses .portal-gallery__hero (subtle border, shadow, click-to-enlarge
   modal), but with no thumbnail rail (only one image). The CTA below
   is left-aligned with the picture frame. When the real diagram or
   photo lands, swap the .portal-gallery__placeholder block for an
   <img> — the rest of the structure (modal, CTA) stays. */
.architecture-visual {
    display: flex;
    flex-direction: column;
    gap: 14px;
}
/* Photo caption — sits directly under the picture frame, left-aligned to
   the image edge. Sized one step below body copy, normal weight, no
   chrome (no box, no border, no italics, no leading icon, no quote
   marks). Color sits softer than the section's body paragraphs (which
   are at 0.78 white) — the caption is photo metadata, not section copy.
   Width naturally matches the image because both fill the column.
   The optional .__caption-detail child sits on a new line, dimmer and
   smaller — same lead/detail relationship as the lightbox chrome. */
.architecture-visual__caption {
    margin: 0;
    font-size: 0.75rem;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.65);
    font-weight: 400;
}
.architecture-visual__caption-detail {
    display: block;
    margin-top: 3px;
    font-size: 0.92em;
    color: rgba(255, 255, 255, 0.45);
}

/* Placeholder for the hardware photo slot — used on /general-purpose-
   compute until a `gen3_back01.jpg` hardware shot lands. Fills the
   same visual mass as the real Lightbox3 image on MCC, so the section
   reads complete. Gradient is the gen3 palette (matches the hero).
   Swap it out: replace the `<div class="architecture-visual__placeholder">`
   with the `<a data-lightbox>` + `<img>` markup MCC uses once the
   photo exists. */
.architecture-visual__placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    aspect-ratio: 4 / 3;
    padding: 40px 32px;
    text-align: center;
    border-radius: 12px;
    background: linear-gradient(135deg, #a0558a 0%, #5a7a9a 60%, #1d3a5b 100%);
    color: rgba(255, 255, 255, 0.85);
    box-shadow: 0 10px 32px rgba(0, 0, 0, 0.15);
}
.architecture-visual__placeholder i {
    font-size: 2.6rem;
    opacity: 0.55;
}
.architecture-visual__placeholder-label {
    font-family: var(--font-heading);
    font-size: 1.05rem;
    font-weight: 600;
    color: #fff;
}
.architecture-visual__placeholder-meta {
    font-size: 0.7rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.65);
}

/* Reverse split modifier — visual on the LEFT, text on the RIGHT.
   Default .platform-principle__split is text-left/visual-right (5fr/6fr).
   --reverse swaps the column widths so the visual still gets the wider
   column when it sits on the left, keeping the focal point in the
   visually-heavier 6fr cell. Used on /mission-critical-compute for
   visual rhythm against the home page. */
.platform-principle__split--reverse {
    grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
}
.platform-principle__split--reverse .platform-principle__text {
    /* text now sits in the right column; nudge max-width so it fills
       its column rather than being capped at 520px (the default for
       the left-text variant). */
    max-width: 560px;
    margin-left: auto;
}

/* "Single pane of glass" callout — distinct from the regular body
   paragraph above it. Subtle pink left rule + brighter text color so
   it scans as its own benefit block rather than continuation copy.
   Modest top margin (24px instead of the default paragraph rhythm)
   keeps the column compact next to the right-side screenshots. */
.single-pane-callout {
    margin: 24px 0 0;
    padding: 6px 0 6px 18px;
    border-left: 3px solid var(--cp-pink);
}
.single-pane-callout__lead {
    font-family: var(--font-heading);
    font-size: 1.05rem;
    font-weight: 600;
    color: #ffffff;
    margin: 0 0 6px;
    letter-spacing: 0.01em;
    line-height: 1.4;
    /* Override the .platform-principle p:not(.platform-principle__lead)
       rule that sets max-width: 680px, margin auto. */
    max-width: none;
}
.single-pane-callout__body {
    color: rgba(255, 255, 255, 0.88);
    font-size: 0.98rem;
    line-height: 1.6;
    margin: 0;
    max-width: none;
}

@media (max-width: 900px) {
    .platform-principle__split {
        grid-template-columns: 1fr;
        gap: 36px;
    }
    .platform-principle__text { max-width: none; }
}

/* iPad-landscape range — wider visual sections need a small
   horizontal inset so they don't feel edge-to-edge inside the
   Bootstrap .container (which sits at 960px max at lg, leaving
   only ~32px viewport-edge gutter at 1024px). 28px each side
   matches the inset that the home page Management Experience
   has used since launch. Consolidated so every "wider section"
   pattern gets the same treatment:
     .platform-principle__split      — home page Management
                                        Experience + product-page
                                        Platform sections
     .arch-section--article          — /platform-architecture
        .arch-section__text             Hypervisor + Host Architecture,
                                        /about-us Our Story
     .portfolio-split__grid          — /services-and-solutions
                                        MCC + GPC tile blocks
   .arch-section--split keeps its existing 60px inset (its own
   2-col grid + diagram on the right is more crowded — 28px would
   make the visual column hug the floating TOC/scroll-to-top
   buttons on iPad landscape). */
@media (min-width: 901px) and (max-width: 1199px) {
    .platform-principle__split,
    .arch-section--article .arch-section__text,
    .portfolio-split__grid {
        padding: 0 28px;
    }
}

/* ==========================================================================
   Portal screenshots gallery — large hero + 3 thumbnails + lightbox modal.
   Lives inside .platform-principle--split's right column.
   The hero "feels real" via subtle white border + soft shadow rather
   than dashed-placeholder treatment. Thumbnails are understated by
   default and lift to active state with a thin pink ring.
   ========================================================================== */
.portal-gallery {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* Hero frame — looks like a real screenshot frame even when the
   content is a placeholder. Cursor is zoom-in to telegraph the
   click-to-enlarge interaction. */
.portal-gallery__hero {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 10;
    padding: 0;
    background: #0a1019;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 12px;
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.4);
    overflow: hidden;
    cursor: zoom-in;
    transition: box-shadow 0.25s ease, transform 0.2s ease;
}
.portal-gallery__hero:hover {
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
    transform: translateY(-2px);
}
.portal-gallery__hero:focus-visible {
    outline: 2px solid var(--cp-pink);
    outline-offset: 2px;
}

/* All 3 shots are rendered stacked inside the hero. Only the active
   one is visible; the others sit at opacity 0 with no pointer events.
   Crossfading via opacity keeps swap transitions smooth. */
.portal-gallery__shot {
    position: absolute;
    inset: 0;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease;
}
.portal-gallery__shot.is-active {
    opacity: 1;
    pointer-events: auto;
}
.portal-gallery__shot > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top center;
    display: block;
}

/* Zoom-in indicator — fades in on hero hover so users see the
   click-to-enlarge affordance without it being permanently in frame. */
.portal-gallery__zoom {
    position: absolute;
    bottom: 14px;
    right: 14px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.6);
    color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.85rem;
    opacity: 0;
    transition: opacity 0.2s ease;
}
.portal-gallery__hero:hover .portal-gallery__zoom { opacity: 1; }

/* Placeholder content inside a shot — soft duotone fill so the empty
   shot reads as "intentional design" rather than "TODO". */
.portal-gallery__placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background:
        radial-gradient(ellipse at 30% 25%, rgba(122, 157, 190, 0.10) 0%, transparent 60%),
        radial-gradient(ellipse at 70% 80%, rgba(222, 53, 128, 0.06) 0%, transparent 60%),
        #0a1019;
    text-align: center;
    padding: 16px;
}
.portal-gallery__placeholder-label {
    font-family: var(--font-heading);
    font-size: 0.95rem;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.82);
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.portal-gallery__placeholder-meta {
    font-size: 0.78rem;
    color: rgba(255, 255, 255, 0.45);
    max-width: 280px;
}

/* Thumbnail rail — three even-width thumbs, understated by default. */
.portal-gallery__rail {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
}
.portal-gallery__thumb {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 10;
    padding: 0;
    background: #0a1019;
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 8px;
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.2s ease, transform 0.15s ease,
                box-shadow 0.2s ease, opacity 0.2s ease;
    opacity: 0.6;
}
.portal-gallery__thumb:hover {
    opacity: 1;
    border-color: rgba(255, 255, 255, 0.18);
    transform: translateY(-1px);
}
.portal-gallery__thumb:focus-visible {
    outline: 2px solid var(--cp-pink);
    outline-offset: 2px;
}
.portal-gallery__thumb.is-active {
    opacity: 1;
    border-color: rgba(222, 53, 128, 0.55);
    box-shadow: 0 0 0 1px rgba(222, 53, 128, 0.28);
}
.portal-gallery__thumb > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top center;
    display: block;
}
.portal-gallery__placeholder--thumb {
    gap: 0;
    padding: 8px;
}
.portal-gallery__placeholder--thumb span {
    font-family: var(--font-heading);
    font-size: 0.7rem;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.65);
    letter-spacing: 0.05em;
    text-transform: uppercase;
    text-align: center;
    line-height: 1.2;
}

@media (max-width: 560px) {
    .portal-gallery__rail { gap: 8px; }
    .portal-gallery__placeholder-meta { display: none; }
}

/* ==========================================================================
   11d. Category page patterns
   Hero band (gradient matching the corresponding store-card variant),
   category intro, verbatim product blocks, and the cross-sell band at
   the bottom. Used on /mission-critical-compute, /general-purpose-compute,
   /veeam-backup and (eventually) any other category pages.
   ========================================================================== */

/* Category hero — gradient band, matches .cp-store-card--gen3/gen4/veeam */
.category-hero {
    padding: 96px 0 72px;
    /* Min-height so pages with fewer hero pills or shorter leads (e.g.
       /data-centers with 2 pills + 2-line lead) sit at the same visual
       height as pages with 4 pills + longer leads (/platform-
       architecture, /network-architecture). Centered flex keeps
       content vertically in the middle when there's extra space. */
    min-height: 460px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    color: #ffffff;
    text-align: center;
    position: relative;
    overflow: hidden;
}
.category-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(ellipse at bottom, rgba(255, 255, 255, 0.1), transparent 70%);
    pointer-events: none;
}
.category-hero > .container { position: relative; z-index: 1; }
.category-hero--gen4 {
    background: linear-gradient(135deg, #1a3050 0%, #4d1230 45%, #de3580 100%);
}
.category-hero--gen3 {
    background: linear-gradient(135deg, #a0558a 0%, #5a7a9a 60%, #1d3a5b 100%);
}
.category-hero--veeam {
    background: linear-gradient(135deg, #1b4332 0%, #2d6a4f 50%, #40916c 100%);
}
.category-hero--default {
    background: linear-gradient(135deg, #2c3e50 0%, #4a6274 50%, #7a9dbe 100%);
}
/* Photo-backed hero. The page sets `--hero-bg-image: url(...)` inline
   on the section. The translucent slate gradient lives on the section
   itself; the photo + filter live on a ::before so we can wash it out
   without touching the H1/lead text. */
/* Photo-backed hero — same technique as .category-hero--dc:
   the section is a solid navy base, and the photo lives in a
   ::before with `mix-blend-mode: screen` + a radial mask that
   confines it to a mid-radius RING (transparent at the center
   where text sits AND at the corners). Result: text always
   reads against solid navy; photo is atmospheric texture only. */
.category-hero--photo-bg {
    background: linear-gradient(135deg, #1a1c1f 0%, #2a2d31 50%, #3a3e44 100%);
    isolation: isolate;
}
.category-hero--photo-bg::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    background-image: var(--hero-bg-image);
    background-size: cover;
    background-position: center;
    filter: contrast(1.1) brightness(0.65);
    mix-blend-mode: screen;
    opacity: 0.2;
    -webkit-mask-image: radial-gradient(ellipse 80% 75% at 50% 50%,
                            transparent 0%,
                            #000 50%,
                            #000 75%,
                            transparent 100%);
            mask-image: radial-gradient(ellipse 80% 75% at 50% 50%,
                            transparent 0%,
                            #000 50%,
                            #000 75%,
                            transparent 100%);
    pointer-events: none;
}
/* Top-fade darkening behind the title; preserves the base
   .category-hero::after bottom vignette as a second background
   layer so we don't lose that. */
.category-hero--photo-bg::after {
    background:
        linear-gradient(to bottom,
            rgba(10, 22, 36, 0.5) 0%,
            rgba(10, 22, 36, 0.2) 35%,
            transparent 60%),
        radial-gradient(ellipse at bottom,
            rgba(255, 255, 255, 0.1), transparent 70%);
}
/* Pills on --photo-bg get a quieter outline-style treatment
   (matching --dc) instead of the default fill. */
.category-hero--photo-bg .category-hero__features .cp-store-card__feat {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.16);
    color: rgba(255, 255, 255, 0.8);
}

/* Platform Architecture hero — blueprint-on-steel treatment.
   Stacks layers in a single `background` property (rendered back-to-
   front, first declaration on top):
     1. Center spotlight: soft blue radial behind the title to lift
        the h1 off the grid.
     2. Horizontal + vertical 60px blueprint grid at ~2.2% white —
        just visible enough to read as architectural drafting paper,
        never distracting.
     3. Deep steel gradient base.
   Pure CSS gradients, no images. Moved here from the Data Centers
   hero (which now uses its own dot-matrix variant below). */
.category-hero--arch {
    background:
        radial-gradient(ellipse 70% 55% at 50% 45%,
            rgba(100, 160, 220, 0.22), transparent 65%),
        repeating-linear-gradient(0deg,
            transparent 0, transparent 59px,
            rgba(255, 255, 255, 0.022) 59px,
            rgba(255, 255, 255, 0.022) 60px),
        repeating-linear-gradient(90deg,
            transparent 0, transparent 59px,
            rgba(255, 255, 255, 0.022) 59px,
            rgba(255, 255, 255, 0.022) 60px),
        linear-gradient(135deg, #0f2033 0%, #1a3050 55%, #23415f 100%);
}

/* Data Centers hero — dot-matrix-on-navy treatment.
   Distinct visual language from platform-architecture: where that
   page evokes drafting/blueprints (linework), this page evokes the
   physical facility (data-hall floor tiles, fiber node arrays,
   server grid points). Layers back-to-front:
     1. Pink brand glow from top-center — claims the page as
        "our infrastructure" with brand warmth, not just neutral
        slate. Eases into transparent by mid-height.
     2. Cool blue wash rising from the bottom — gives depth without
        fighting the pink glow above.
     3. White dot grid at 40px pitch (~5% white) — evokes the dotted
        grid of a data-hall floor plan or a server-rack LED array.
        Pure CSS via radial-gradient + background-size, no images.
     4. Deeper navy base — slightly darker than the arch hero so
        the two pages feel like siblings, not twins. */
.category-hero--dc {
    background-image:
        /* Faint cool slate glow, top-center — replaced the earlier
           pink brand glow which was reading as synthetic against a
           facility photo. Neutral/cool tone keeps the hero feeling
           infrastructural. */
        radial-gradient(ellipse 55% 45% at 50% 38%,
            rgba(140, 175, 215, 0.08), transparent 65%),
        /* Blue cool wash from bottom */
        radial-gradient(ellipse 95% 55% at 50% 108%,
            rgba(100, 160, 220, 0.08), transparent 70%),
        /* Rack-row linework — dialed back now that the photo is
           doing the structural heavy lifting. */
        repeating-linear-gradient(0deg,
            transparent 0, transparent 29px,
            rgba(255, 255, 255, 0.018) 29px,
            rgba(255, 255, 255, 0.018) 30px),
        /* Vertical bay lines at 25/50/75 — also lighter */
        linear-gradient(90deg,
            transparent 0, transparent calc(25% - 0.5px),
            rgba(255, 255, 255, 0.025) calc(25% - 0.5px),
            rgba(255, 255, 255, 0.025) calc(25% + 0.5px),
            transparent calc(25% + 0.5px),
            transparent calc(50% - 0.5px),
            rgba(255, 255, 255, 0.025) calc(50% - 0.5px),
            rgba(255, 255, 255, 0.025) calc(50% + 0.5px),
            transparent calc(50% + 0.5px),
            transparent calc(75% - 0.5px),
            rgba(255, 255, 255, 0.025) calc(75% - 0.5px),
            rgba(255, 255, 255, 0.025) calc(75% + 0.5px),
            transparent calc(75% + 0.5px)),
        /* Dot grid at 40px — barely there */
        radial-gradient(circle,
            rgba(255, 255, 255, 0.035) 1px, transparent 1.6px),
        /* Navy gradient base */
        linear-gradient(135deg, #0a1624 0%, #13253b 50%, #1a3048 100%);
    background-size: auto, auto, auto, auto, 40px 40px, auto;
    background-position: center, center, 0 0, 0 0, 0 0, center;
    background-repeat: no-repeat, no-repeat, repeat, no-repeat, repeat, no-repeat;
}

/* Facility photo underlay — a real data center image processed to
   grayscale + placed behind the hero content with screen blend-mode
   and low opacity so it reads as a ghostly architectural presence
   rather than a full-bleed photo. Mask is a double-fade "ring":
   transparent at the center (content zone) AND fading to transparent
   at the corners so the image never hits the hero edges — it only
   shows in a mid-radius band. Combined with lowered opacity and
   further-dimmed brightness, the image now reads as quiet atmosphere
   rather than a photograph sitting behind the text. */
.category-hero--dc::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: url("/assets/img/data-centers/hero-facility.jpg");
    background-size: cover;
    background-position: center center;
    background-repeat: no-repeat;
    /* Softer contrast — previous 1.4 was showing too much rooftop
       detail competing with the title; 1.15 preserves the building
       silhouette without emphasizing texture. */
    filter: contrast(1.15) brightness(0.6);
    mix-blend-mode: screen;
    opacity: 0.16;
    -webkit-mask-image: radial-gradient(ellipse 78% 72% at 50% 50%,
                            transparent 0%,
                            #000 48%,
                            #000 72%,
                            transparent 100%);
    mask-image: radial-gradient(ellipse 78% 72% at 50% 50%,
                    transparent 0%,
                    #000 48%,
                    #000 72%,
                    transparent 100%);
    pointer-events: none;
    z-index: 0;
}

/* Top-third darkening overlay on the --dc hero. The base
   .category-hero::after is a bottom-vignette; for --dc we extend
   it with a top-fade that deepens the navy behind the title. Sits
   between ::before (image) and content (z-index 1), so it darkens
   the image without affecting text legibility. Bottom vignette
   preserved. */
.category-hero--dc::after {
    background:
        linear-gradient(to bottom,
            rgba(10, 22, 36, 0.5) 0%,
            rgba(10, 22, 36, 0.2) 35%,
            transparent 60%),
        radial-gradient(ellipse at bottom,
            rgba(255, 255, 255, 0.1), transparent 70%);
}

/* Mobile — pull the image's focus slightly higher so the building
   mass stays centered when the narrow aspect crops the image
   vertically. 40% y-anchor favors the top half where the building
   silhouette sits. */
@media (max-width: 767px) {
    .category-hero--dc::before {
        background-position: center 40%;
    }
}

/* Hero pills on --dc specifically — refined, less button-like.
   Lower-opacity background, thin outline, slightly dimmer text so
   the pills read as quiet facility tags instead of active buttons. */
.category-hero--dc .category-hero__features .cp-store-card__feat {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.16);
    color: rgba(255, 255, 255, 0.8);
}

/* Network Architecture hero — distinct from the sister infra pages:
     /data-centers          → .category-hero--dc      (photo underlay + dots)
     /platform-architecture → .category-hero--arch    (blueprint grid)
     /network-architecture  → THIS                    (diagonal hatching +
                                                        cool teal base)
   Diagonal hatching reads as "layered/stacked/moving" rather than
   the architectural blueprint language already on Platform Arch.
   Base slightly teal-shifted so the palette feels distinct even
   at a quick side-by-side. */
.category-hero--network {
    background-image:
        /* Soft cool-blue center glow */
        radial-gradient(ellipse 55% 45% at 50% 40%,
            rgba(130, 180, 225, 0.10), transparent 65%),
        /* Diagonal hatching — very subtle, ~2% white at 50px pitch */
        repeating-linear-gradient(45deg,
            transparent 0, transparent 49px,
            rgba(255, 255, 255, 0.02) 49px,
            rgba(255, 255, 255, 0.02) 50px),
        /* Slate-teal base — distinct hue from DC's pure navy and
           PA's steel-blue (both of those lean darker blue; this
           leans a touch green). */
        linear-gradient(135deg, #0e2530 0%, #153b48 50%, #1c4858 100%);
}

/* ==========================================================================
   /network-architecture — topology diagram wrapper + callout band
   --------------------------------------------------------------------------
   The bulk of .arch-section styling (theme, split layout, typography,
   visual stack, photo card, spec grid) lives in the consolidated
   component block further down (search "unified section component for
   /network-architecture"). This block only keeps the isolated pieces:
   the inline-SVG wrapper sizing and the inter-section callout band.
   ========================================================================== */

/* Diagram wrapper — holds inline SVG. No own chrome; the SVG carries
   its own borders/colors via its style block. max-width keeps the
   diagram a sensible size on wide viewports; width 100% on narrow. */
.arch-diagram {
    width: 100%;
    max-width: 520px;
    margin: 0 auto;
}
.arch-diagram svg {
    display: block;
    width: 100%;
    height: auto;
}

/* Callout band between Section 01 and Section 02 — slim inset note
   clarifying the client-routing/security model (VyOS/Palo Alto).
   Light background, pink left-rule for emphasis, constrained
   max-width so it doesn't compete with the flanking sections. */
.arch-callout {
    background: var(--cp-bg-alt);
    padding: 36px 0;
}
.arch-callout__inner {
    max-width: 820px;
    margin: 0 auto;
    padding: 20px 28px;
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-left: 3px solid var(--cp-pink);
    border-radius: var(--cp-r-sm);
    box-shadow: 0 2px 12px rgba(26, 34, 51, 0.04);
}
.arch-callout__eyebrow {
    display: inline-block;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--cp-pink);
    margin-bottom: 8px;
}
.arch-callout__inner p {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.65;
    color: var(--cp-text);
}
.arch-callout__inner p strong {
    color: var(--cp-text-heading);
    font-weight: 600;
}

/* Inline variant — when .arch-callout lives INSIDE a section (vs. as
   a standalone band). Drops the outer bg/padding so it reads as a
   closing note of the parent section, not a separate band. The inner
   card keeps its pink-rule treatment but sits naturally under the
   spec-card grid above. */
.arch-callout--inline {
    background: transparent;
    padding: 0;
    margin-top: 36px;
}
/* Inline callouts are footnote-scale — dial the body text down from
   the default 0.95rem so they read as supporting notes, not primary
   copy. Line-height tightens a touch to match. */
.arch-callout--inline .arch-callout__inner p {
    font-size: 0.82rem;
    line-height: 1.55;
}

/* Breadcrumb: middle sentinel (no url, not the last crumb) — render as
   a neutral section label, NOT pink-active. Fixes the bug where pages
   with 3-deep breadcrumbs had two `aria-current="page"` items and two
   pink crumbs (e.g. /data-centers's "Infrastructure" + "Data Centers"
   were both active). Only the last crumb keeps .active styling. */
.master-breadcrumb .breadcrumb-item--sentinel {
    color: rgba(255, 255, 255, 0.65);
}
.category-hero__eyebrow {
    display: inline-block;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.85rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.8);
    margin-bottom: 14px;
}
.category-hero h1 {
    color: #ffffff;
    margin: 0 0 18px;
    /* Reduced from 2.4..3.75rem so the prefixed abbreviation
       ("MCC // Mission Critical Compute" / "GPC // General Purpose
       Compute") fits on a single line at common viewport widths
       without awkward wraps. */
    font-size: clamp(2rem, 4.3vw, 3.3rem);
    line-height: 1.12;
}
.category-hero__lead {
    font-size: 1.2rem;
    color: rgba(255, 255, 255, 0.88);
    max-width: 720px;
    margin: 0 auto 28px;
    line-height: 1.55;
}
.category-hero__features {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
    max-width: 720px;
    margin: 0 auto;
}
.category-hero__features .cp-store-card__feat {
    font-size: 11px;
    padding: 4px 10px;
}

/* Category intro — my-authored 150-ish-word lead-in */
.category-intro {
    /* Balanced vertical padding — was 80/40 which read as the first
       section under the hero being "double on top, half on bottom".
       Even 60/60 keeps roughly the same total vertical footprint
       (120px) while visually centering the intro prose between
       hero and the first numbered content section. */
    padding: 60px 0;
}
.category-intro__inner {
    max-width: 780px;
    margin: 0 auto;
    text-align: center;
}
.category-intro h2 {
    font-size: clamp(1.75rem, 3vw, 2.4rem);
    margin-bottom: 22px;
}
/* Sub-title between h2 and the body paragraph — single-line punchy
   one-liner that anchors the page's voice (e.g. "purpose-built
   enterprise cloud that favors predictability over scale" on
   /platform-architecture). Heading font, slightly larger than body,
   tightened margin so it reads as a continuation of the h2 rather
   than a fresh paragraph. */
.category-intro__subtitle {
    font-family: var(--font-heading);
    font-size: 1.2rem;
    font-weight: 600;
    line-height: 1.5;
    color: var(--cp-text-heading);
    max-width: 680px;
    margin: -6px auto 28px;
}
.category-intro p {
    font-size: 1.05rem;
    line-height: 1.7;
    color: var(--cp-text-muted);
    margin-bottom: 16px;
}
.category-intro p:last-child { margin-bottom: 0; }

/* Product block — verbatim description card */
.product-block {
    padding: 56px 0;
}
.product-block:nth-of-type(even) { background: var(--cp-bg-alt); }
.product-block__card {
    max-width: 920px;
    margin: 0 auto;
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r);
    box-shadow: var(--cp-shadow-card);
    overflow: hidden;
}
.product-block__header {
    padding: 36px 40px 28px;
    border-bottom: 1px solid var(--cp-border);
}
.product-block__meta {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
}
.product-block__num {
    font-family: var(--font-heading);
    font-size: 0.8rem;
    font-weight: 800;
    letter-spacing: 0.12em;
    color: var(--cp-pink);
    padding: 4px 10px;
    border: 1px solid rgba(222, 53, 128, 0.3);
    border-radius: 4px;
    background: rgba(222, 53, 128, 0.06);
}
.product-block__label {
    font-family: var(--font-heading);
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    color: var(--cp-text-muted);
    text-transform: uppercase;
}
.product-block__name {
    margin: 0 0 10px;
    font-size: clamp(1.6rem, 2.8vw, 2rem);
    line-height: 1.25;
}
.product-block__tagline {
    color: var(--cp-text-muted);
    font-size: 1.05rem;
    margin: 0 0 18px;
    font-style: italic;
}
.product-block__features {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.product-block__features .cp-store-card__feat {
    background: rgba(26, 34, 51, 0.06);
    color: var(--cp-text);
    border: 1px solid rgba(26, 34, 51, 0.08);
    font-size: 10px;
    padding: 3px 9px;
}
.product-block__body {
    padding: 32px 40px;
    font-family: var(--font-body);
    line-height: 1.72;
    color: var(--cp-text);
}
.product-block__body > p {
    margin: 0 0 16px;
    font-size: 1rem;
}
.product-block__body > p:last-of-type { margin-bottom: 0; }
.product-block__body strong { color: var(--cp-text-heading); font-weight: 600; }
.product-block__group {
    margin-top: 28px;
    padding-top: 20px;
    border-top: 1px solid var(--cp-border);
}
.product-block__group h5 {
    font-family: var(--font-heading);
    font-size: 0.8rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--cp-pink);
    margin: 0 0 12px;
    font-weight: 700;
}
.product-block__group ul {
    margin: 0;
    padding-left: 20px;
}
.product-block__group ul li {
    margin-bottom: 6px;
    font-size: 0.95rem;
    color: var(--cp-text);
}
.product-block__footer {
    padding: 24px 40px 32px;
    border-top: 1px solid var(--cp-border);
    background: var(--cp-bg-alt);
    display: flex;
    align-items: center;
    gap: 20px;
    flex-wrap: wrap;
}
.product-block__footer .btn-primary { padding: 12px 22px; font-size: 0.95rem; }
.product-block__link {
    color: var(--cp-pink);
    font-weight: 600;
    font-size: 0.9rem;
    font-family: var(--font-heading);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: gap 0.15s ease;
}
.product-block__link:hover { gap: 10px; color: var(--cp-pink-dark); }
@media (max-width: 640px) {
    .product-block__header { padding: 28px 22px 20px; }
    .product-block__body { padding: 22px 22px; }
    .product-block__footer { padding: 20px 22px 26px; }
}

/* Cross-sell — the note-like link at the bottom */
.cross-sell {
    padding: 48px 0 64px;
    background: var(--cp-bg-alt);
}
.cross-sell__inner {
    max-width: 780px;
    margin: 0 auto;
    padding: 22px 28px;
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-left: 4px solid var(--cp-pink);
    border-radius: var(--cp-r-sm);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
}
.cross-sell__inner p {
    margin: 0;
    font-size: 1rem;
    color: var(--cp-text);
    line-height: 1.6;
}
.cross-sell__inner i {
    color: var(--cp-pink);
    margin-right: 8px;
}
.cross-sell__inner a { text-decoration: none; }
.cross-sell__inner a:hover { text-decoration: underline; }

/* About-page / narrative section — used for /about-us and /data-centers */
.about-section {
    padding: 80px 0;
}
.about-section--alt { background: var(--cp-bg-alt); }
.about-section__inner {
    max-width: 780px;
    margin: 0 auto;
}
.about-section__meta {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
}
.about-section__num {
    font-family: var(--font-heading);
    font-size: 0.85rem;
    font-weight: 800;
    letter-spacing: 0.1em;
    color: var(--cp-pink);
    padding: 4px 10px;
    border: 1px solid rgba(222, 53, 128, 0.3);
    border-radius: 4px;
    background: rgba(222, 53, 128, 0.06);
}
.about-section__label {
    font-family: var(--font-heading);
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    color: var(--cp-pink);
    text-transform: uppercase;
}
.about-section h2 {
    font-size: clamp(1.65rem, 2.8vw, 2.2rem);
    margin-bottom: 20px;
    line-height: 1.3;
}
.about-section p {
    font-size: 1.05rem;
    line-height: 1.7;
    color: var(--cp-text);
    margin-bottom: 16px;
}
.about-section p:last-child { margin-bottom: 0; }

/* Data center card grid */
.dc-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
    gap: 24px;
    margin-top: 32px;
}
.dc-card {
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r);
    padding: 32px 28px;
    box-shadow: var(--cp-shadow-card);
}
.dc-card__label {
    font-family: var(--font-heading);
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--cp-pink);
    margin-bottom: 10px;
}
.dc-card h3 {
    margin: 0 0 8px;
    font-size: 1.35rem;
}
.dc-card__tagline {
    color: var(--cp-text-muted);
    font-size: 0.95rem;
    margin-bottom: 18px;
}
.dc-card__address {
    font-size: 0.88rem;
    color: var(--cp-text-muted);
    margin-bottom: 18px;
    padding: 12px 14px;
    background: var(--cp-bg-alt);
    border-radius: 8px;
    font-family: var(--font-heading);
}
.dc-card ul {
    margin: 0;
    padding-left: 20px;
}
.dc-card ul li {
    margin-bottom: 6px;
    font-size: 0.92rem;
    color: var(--cp-text);
}
/* Single-column variant — when a section profiles ONE facility (instead
   of comparing two side-by-side), the dc-card spans the available width
   with a comfortable max so the address + descriptive paragraphs read
   well on wide displays. */
.dc-grid--single {
    grid-template-columns: 1fr;
    max-width: 920px;
    margin-left: auto;
    margin-right: auto;
}

/* Per-facility specs grid — 3-col on desktop, 2-col on tablet, 1-col on
   phone. Each card holds a category heading + bullet list (Power,
   Network, Cooling, Security, etc). Companion to .dc-card which holds
   the address + descriptive prose for the same facility. */
.dc-specs-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
    margin-top: 36px;
}
.dc-specs-grid--two { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 900px) {
    .dc-specs-grid,
    .dc-specs-grid--two { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
    .dc-specs-grid,
    .dc-specs-grid--two { grid-template-columns: 1fr; }
}
.dc-specs-card {
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r-sm);
    padding: 22px 22px 18px;
}
.dc-specs-card h4 {
    font-family: var(--font-heading);
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--cp-text);
    margin: 0 0 12px;
    display: flex;
    align-items: center;
    gap: 10px;
}
.dc-specs-card h4 i {
    color: var(--cp-pink);
    font-size: 0.88rem;
    width: 18px;
    text-align: center;
}
.dc-specs-card ul {
    margin: 0;
    padding-left: 18px;
}
.dc-specs-card ul li {
    margin-bottom: 5px;
    font-size: 0.88rem;
    line-height: 1.55;
    color: var(--cp-text-muted);
}
.dc-specs-card ul li:last-child { margin-bottom: 0; }
.dc-specs-card ul li strong { color: var(--cp-text); font-weight: 600; }

.dc-capabilities {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 20px;
    margin-top: 40px;
}
.dc-capability {
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r-sm);
    padding: 20px 22px;
    text-align: center;
}
.dc-capability i {
    font-size: 26px;
    color: var(--cp-pink);
    margin-bottom: 10px;
}
.dc-capability h4 {
    font-size: 0.95rem;
    margin: 0 0 6px;
}
.dc-capability p {
    font-size: 0.85rem;
    color: var(--cp-text-muted);
    margin: 0;
    line-height: 1.5;
}

/* ==========================================================================
   12. Stats strip
   ========================================================================== */
/* Dark footer-tone treatment matching .section-lead / .platform-principle.
   Lives between Data Protection cards and the Why Us pillars — visually
   anchors the page with a dark band of proof metrics before the
   credibility pillars land on the light background below. */
.stats {
    padding: 32px 0;
    background: var(--cp-bg-footer);
    color: rgba(255, 255, 255, 0.88);
    position: relative;
    z-index: 1;
    overflow: hidden;
}
.stats::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse at 20% 40%, rgba(222, 53, 128, 0.08) 0%, transparent 55%),
        radial-gradient(ellipse at 80% 60%, rgba(122, 157, 190, 0.06) 0%, transparent 55%);
    pointer-events: none;
}
.stats > .container { position: relative; }
.stats-grid {
    /* Flexbox instead of grid so incomplete rows (when wrap happens at
       narrower viewports) center their remaining items — a 3-column
       auto-fit grid would leave a pair of items left-aligned in columns
       1 and 2 with column 3 empty; flex-wrap + justify-content: center
       centers the orphan pair instead. Effect:
         desktop (≥ ~992px):  5 stats in one row
         tablet  (~600–991):  3 + 2 rows, the "2.3 PB" + "2016" pair
                              centered on row 2
         phone   (< ~600):    2 + 2 + 1 rows, the lone "2016" centered
                              on row 3
       All three cases visually flow because the grid centers itself
       instead of pinning items to column grid-lines. */
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 24px;
    text-align: center;
    max-width: 980px;
    margin: 0 auto;
}
.stats-grid .stat {
    flex: 0 1 170px;
    min-width: 150px;
}
/* Same gradient as --cp-gradient-default but with the 0% stop lifted from
   #1a3050 (dark navy) to a medium wine/raspberry so the top-left of each
   digit stays visible against --cp-bg-footer #0f1826. All other stops are
   unchanged from the default. Scoped to .stats only. */
.stat__value {
    font-family: var(--font-heading);
    font-size: clamp(1.9rem, 2.8vw, 2.4rem);
    font-weight: 700;
    background: linear-gradient(135deg,
                #a63562 0%,
                #de3580 38%,
                #bf6bb4 58%,
                #7a9dbe 78%,
                #2d4a6b 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
    display: inline-block;
    margin-bottom: 4px;
    line-height: 1.1;
}
.stat__label {
    color: rgba(255, 255, 255, 0.72);
    font-size: 0.82rem;
    font-weight: 500;
    letter-spacing: 0.01em;
}
/* Footnote asterisk — sits inline next to the label text (or in front of
   the footnote paragraph below the grid), in brand pink to mark the
   reference. Inherits font-size from its parent so the in-label mark
   sits flush with the label and the in-paragraph mark sits flush with
   the paragraph copy. */
.stat__footnote-mark,
.stats__footnote-mark {
    color: var(--cp-pink);
    font-weight: 600;
}
/* Footnote line under the stats grid — small text, dimmer than labels,
   max-width keeps the line readable as a single block. */
.stats__footnote {
    text-align: center;
    margin: 24px auto 0;
    max-width: 720px;
    font-size: 0.78rem;
    line-height: 1.55;
    color: rgba(255, 255, 255, 0.7);
}
.stats__footnote .stats__footnote-mark { margin-right: 4px; }

/* ==========================================================================
   13. Testimonials
   ========================================================================== */
.testimonials { background: var(--cp-bg-alt); }
.testimonial-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 24px;
}
.testimonial-card {
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r);
    padding: 36px 32px 32px;
    position: relative;
    box-shadow: var(--cp-shadow-card);
    overflow: hidden;
}
.testimonial-card::after {
    content: "";
    position: absolute;
    top: -40px;
    right: -40px;
    width: 140px;
    height: 140px;
    background: radial-gradient(circle, rgba(222, 53, 128, 0.08) 0%, transparent 70%);
    border-radius: 50%;
    pointer-events: none;
}
.testimonial-card__quote {
    font-family: var(--font-heading);
    font-size: 3.5rem;
    line-height: 0.8;
    color: var(--cp-pink);
    opacity: 0.22;
    margin-bottom: 8px;
}
.testimonial-card__body {
    font-style: italic;
    color: var(--cp-text);
    margin-bottom: 24px;
    position: relative;
}
.testimonial-card__author {
    display: flex;
    align-items: center;
    gap: 14px;
}
.testimonial-card__avatar {
    width: 46px;
    height: 46px;
    border-radius: 50%;
    background: var(--cp-gradient-default);
    color: #ffffff;
    display: grid;
    place-items: center;
    font-family: var(--font-heading);
    font-weight: 700;
    flex-shrink: 0;
}
.testimonial-card__name { font-weight: 600; font-size: 0.95rem; color: var(--cp-text-heading); }
.testimonial-card__role { font-size: 0.8rem; color: var(--cp-text-muted); }

/* ==========================================================================
   14. Final CTA
   ========================================================================== */
.final-cta { padding: 120px 0; }
.final-cta--alt-bg { background: var(--cp-bg-alt); }
.final-cta .cta-wrap {
    max-width: 760px;
    margin: 0 auto;
    padding: 72px 48px;
    background: var(--cp-gradient-default);
    border-radius: var(--cp-r-lg);
    color: #ffffff;
    text-align: center;
    box-shadow: 0 24px 64px rgba(26, 34, 51, 0.2);
}
.final-cta h2 { color: #ffffff; margin-bottom: 18px; }
.final-cta p {
    color: rgba(255, 255, 255, 0.88);
    margin-bottom: 36px;
    font-size: 1.1rem;
}
.final-cta .cta-row {
    display: flex;
    gap: 14px;
    justify-content: center;
    flex-wrap: wrap;
}
/* Secondary row of ghost buttons, stacked below the primary CTA */
.final-cta .cta-row + .cta-row-secondary {
    margin-top: 16px;
}
/* Quieter follow-up line under the CTA card — sits on the page bg
   (not the gradient card), so we explicitly override the inherited
   .final-cta p white color and use slate text. The Calendly link
   itself uses brand pink, so the eye still has somewhere to land. */
.final-cta .final-cta__followup {
    text-align: center;
    margin: 28px auto 0;
    font-size: 0.92rem;
    color: var(--cp-text-muted);
}
.final-cta .final-cta__followup a {
    color: var(--cp-pink);
    font-weight: 600;
    text-decoration: none;
    border-bottom: 1px solid rgba(222, 53, 128, 0.35);
    transition: border-color 0.2s ease, color 0.2s ease;
}
.final-cta .final-cta__followup a:hover,
.final-cta .final-cta__followup a:focus {
    color: var(--cp-pink-dark);
    border-bottom-color: var(--cp-pink);
}
.final-cta .btn-primary {
    background: #ffffff !important;
    color: var(--cp-pink) !important;
    border-color: #ffffff !important;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.24);
}
/* The final-CTA variant flips to white-on-pink-panel, so the global white
   shine sweep would be invisible. Override ::after with a pink gradient
   that reads correctly against the white button. */
.final-cta .btn-primary::after {
    background: linear-gradient(90deg,
                transparent 0%,
                rgba(222, 53, 128, 0.28) 50%,
                transparent 100%);
}
.final-cta .btn-primary:hover,
.final-cta .btn-primary:focus {
    background: #ffffff !important;
    color: var(--cp-pink-dark) !important;
    border-color: #ffffff !important;
    transform: translateY(-2px);
}
@media (max-width: 640px) {
    .final-cta { padding: 80px 0; }
    .final-cta .cta-wrap { padding: 56px 28px; }
}

/* ==========================================================================
   15. Footer — cp-footer, lifted from cp-twenty-one/custom.css ~L2419-2650.
   Shimmer SVG logo + two contact groups + Company/Services/Resources
   columns, dark background with a huge faint cloud watermark, pink border
   under column headers, green "Systems Status" terminal-pill in the
   bottom-right. FA6 Free replaces FA6 Pro for the cloud glyph.
   ========================================================================== */
footer.cp-footer {
    background: #1e2a38 !important;
    color: #ccc;
    padding: 50px 0 0 !important;
    margin-top: 0;
    position: relative;
    overflow: hidden;
    font-family: var(--font-heading);
    box-shadow: inset 0 12px 24px -6px rgba(0, 0, 0, 0.45);
}
/* Huge cloud watermark — bottom-left, only the top peeks up */
footer.cp-footer::before {
    content: "\f0c2"; /* fa-cloud */
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    position: absolute;
    font-size: 600px;
    color: rgba(255, 255, 255, 0.022);
    bottom: -320px;
    left: -80px;
    pointer-events: none;
    z-index: 0;
}
footer.cp-footer > .container {
    position: relative;
    z-index: 1;
}
.cp-footer-inner {
    display: flex;
    gap: 40px;
    align-items: flex-start;
}
.cp-footer-brand {
    flex: 0 0 auto;
}
.cp-footer-logo {
    /* Explicit width + aspect-ratio gives the <object> a real box
       to render into. The embedded SVG only declares a viewBox (no
       width/height), so without a concrete width the object would
       compute to 0px and fall back to its text content ("Cloud
       Propeller"). Aspect ratio matches the SVG's viewBox
       (350.88 / 145.81 ≈ 2.406). */
    display: block;
    width: 200px;
    max-width: 100%;
    aspect-ratio: 350.88 / 145.81;
    margin-bottom: 20px;
    background: transparent !important;
}
/* Contact info — two groups side by side on desktop */
.cp-footer-contact {
    margin-top: 18px;
    display: flex;
    gap: 32px;
}
.cp-footer-contact-group {
    display: flex;
    flex-direction: column;
    gap: 7px;
}
.cp-footer-contact-label {
    color: #8899aa;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    font-family: 'Share Tech', 'Exo 2', sans-serif;
    margin-bottom: 2px;
}
.cp-footer-contact-item {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
}
.cp-footer-contact-item i {
    color: #667788;
    font-size: 13px;
    width: 14px;
    text-align: center;
    flex-shrink: 0;
}
.cp-footer-contact-item a {
    color: #8899aa;
    text-decoration: none;
    transition: color 0.2s ease;
}
.cp-footer-contact-item a:hover {
    color: #de3580;
}
.cp-footer-links {
    flex: 1;
    display: flex;
    gap: 40px;
    justify-content: flex-end;
}
.cp-footer-col {
    flex: 1 1 0;
    min-width: 0;
    text-align: right;
}
.cp-footer-col h5 {
    color: #fff;
    font-size: 14px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    margin: 0 0 16px 0;
    padding-bottom: 8px;
    border-bottom: 2px solid #de3580;
    font-family: 'Share Tech', 'Exo 2', sans-serif;
}
.cp-footer-col ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.cp-footer-col ul li {
    margin-bottom: 8px;
}
.cp-footer-col ul li a {
    color: #8899aa;
    font-size: 15px;
    text-decoration: none;
    transition: color 0.2s ease;
    letter-spacing: 0.3px;
}
.cp-footer-col ul li a:hover {
    color: #fff;
}
.cp-footer-separator {
    color: #8899aa;
}
/* Bottom bar — split: copyright left, status right */
.cp-footer-bottom {
    margin-top: 16px;
    padding: 12px 0;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.cp-footer-bottom p {
    margin: 0;
    color: #556677;
    font-size: 15px;
    letter-spacing: 0.5px;
    font-family: 'Share Tech', 'Exo 2', sans-serif;
}
/* Systems Status link — green terminal-style pill */
.cp-status-link {
    color: #4caf50 !important;
    font-family: 'Share Tech Mono', 'Courier New', monospace;
    font-size: 14px !important;
    letter-spacing: 0.5px;
    text-decoration: none;
    padding: 6px 14px;
    border: 1px solid rgba(76, 175, 80, 0.3);
    border-radius: 6px;
    background: rgba(76, 175, 80, 0.06);
    transition: all 0.25s ease;
}
.cp-status-link:hover {
    color: #69f0ae !important;
    text-shadow: 0 0 8px rgba(76, 175, 80, 0.4);
    text-decoration: none;
    border-color: rgba(76, 175, 80, 0.5);
    background: rgba(76, 175, 80, 0.1);
    box-shadow: 0 0 12px rgba(76, 175, 80, 0.15);
}
.cp-status-dot {
    font-size: 8px;
    color: #4caf50;
    vertical-align: middle;
    margin-right: 2px;
    animation: cp-pulse-dot 2s ease-in-out infinite;
}
@keyframes cp-pulse-dot {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.4; }
}

/* Footer columns — prevent Services text wrap at narrower desktop */
@media only screen and (max-width: 1020px) {
    .cp-footer-col {
        min-width: auto;
    }
    .cp-footer-col ul li a {
        white-space: nowrap;
    }
}
/* Footer responsive — stack brand above links at tablet widths */
@media only screen and (max-width: 990px) {
    .cp-footer-inner {
        flex-direction: column;
        align-items: center;
        text-align: center;
    }
    .cp-footer-brand {
        flex: none;
    }
    .cp-footer-contact {
        gap: 24px;
    }
    .cp-footer-links {
        flex-wrap: wrap;
        gap: 24px;
        justify-content: space-evenly;
        width: 100%;
    }
    .cp-footer-col {
        text-align: center;
    }
    .cp-footer-bottom {
        flex-direction: column;
        gap: 12px;
        text-align: center;
    }
}
/* Footer — decorative background scales down on small screens */
@media only screen and (max-width: 767px) {
    footer.cp-footer::before {
        font-size: 360px;
        bottom: -200px;
        left: -60px;
    }
}
/* Footer — iPhone-portrait tuning. At ≤480px the 3-col link row
   was too cramped (links wrapping to 2 lines at ~109px col width)
   and the contact groups were fighting for horizontal space.
   Shrink fonts ~20% so links fit one-per-line in narrow columns,
   stack the contact groups vertically for breathing room, and
   widen the between-sections gap so the whole footer reads with
   more air — the "padded more" feel without bloating padding
   values themselves. */
@media only screen and (max-width: 480px) {
    footer.cp-footer {
        padding: 40px 0 0 !important;
    }
    .cp-footer-inner {
        gap: 32px;
    }
    /* Keep Contact + Support groups side-by-side (matching WHMCS
       at iPhone portrait). Just trim the gap so they fit in the
       narrow viewport without cramping. */
    .cp-footer-contact {
        gap: 18px;
    }
    .cp-footer-contact-label {
        font-size: 10px;
    }
    .cp-footer-contact-item {
        font-size: 12px;
    }
    .cp-footer-links {
        gap: 22px;
    }
    .cp-footer-col h5 {
        font-size: 12px;
        letter-spacing: 1px;
        margin-bottom: 10px;
        padding-bottom: 6px;
    }
    .cp-footer-col ul li {
        margin-bottom: 6px;
    }
    .cp-footer-col ul li a {
        font-size: 12px;
    }
    .cp-footer-bottom {
        margin-top: 24px;
        padding: 14px 0;
        font-size: 11px;
    }
    .cp-footer-bottom p {
        font-size: 11px;
    }
}

/* ==========================================================================
   /cloud-manager page — capability grid + walkthrough tile gallery
   --------------------------------------------------------------------------
   Capability grid: 5 features in a 3x2-with-one-gap layout. Each card
   has a pink gradient icon chip, h3, and body. Mirrors the .pillar
   pattern but without the numbered eyebrow — these are functional
   capabilities, not a ranked list of brand differentiators.

   Walkthrough tiles: 3-col grid (3+3 on desktop) of click-to-enlarge
   screenshot tiles. Reuses the .portal-gallery__placeholder + modal
   styling from the homepage gallery, but every tile is its own
   independent modal trigger (no hero/thumb swap pattern).
   ========================================================================== */

.cloud-manager-capabilities {
    background: var(--cp-bg-alt);
}
.capability-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
    max-width: 1240px;
    margin: 0 auto;
}
@media (max-width: 900px) {
    .capability-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
    .capability-grid { grid-template-columns: 1fr; }
}
.capability-card {
    position: relative;
    background: #ffffff;
    border: 1px solid #e8e8e8;
    border-radius: 14px;
    padding: 32px 28px;
    transition: border-color 0.2s ease, box-shadow 0.2s ease,
                transform 0.2s ease;
}
.capability-card::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: var(--cp-gradient-default);
    border-radius: 14px 14px 0 0;
}
.capability-card:hover {
    border-color: rgba(222, 53, 128, 0.4);
    box-shadow: 0 14px 32px rgba(222, 53, 128, 0.12);
    transform: translateY(-2px);
}
.capability-card__icon {
    width: 48px;
    height: 48px;
    border-radius: 10px;
    background: linear-gradient(135deg, var(--cp-pink), var(--cp-pink-dark, #b32867));
    color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.15rem;
    margin-bottom: 18px;
    box-shadow: 0 6px 16px rgba(222, 53, 128, 0.22);
}
.capability-card h3 {
    font-family: var(--font-heading);
    font-size: 1.15rem;
    font-weight: 700;
    color: #2c3e50;
    line-height: 1.3;
    margin-bottom: 12px;
}
.capability-card p {
    color: var(--cp-text-muted);
    font-size: 0.95rem;
    line-height: 1.65;
    margin: 0;
}
.capability-card p strong {
    color: var(--cp-text);
    font-weight: 600;
}

/* Walkthrough tile grid — 3 cols at desktop, 2 at tablet, 1 at phone. */
.cloud-manager-walkthrough { background: #ffffff; }
.walkthrough-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 20px;
    max-width: 1180px;
    margin: 0 auto;
}
@media (max-width: 900px) {
    .walkthrough-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
    .walkthrough-grid { grid-template-columns: 1fr; }
}
.walkthrough-tile {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 10;
    padding: 0;
    background: #0a1019;
    border: 1px solid rgba(15, 24, 38, 0.12);
    border-radius: 10px;
    overflow: hidden;
    cursor: zoom-in;
    transition: box-shadow 0.25s ease, transform 0.2s ease,
                border-color 0.2s ease;
}
.walkthrough-tile:hover {
    box-shadow: 0 14px 36px rgba(0, 0, 0, 0.18);
    transform: translateY(-2px);
    border-color: rgba(222, 53, 128, 0.4);
}
.walkthrough-tile:focus-visible {
    outline: 2px solid var(--cp-pink);
    outline-offset: 2px;
}
.walkthrough-tile > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top center;
    display: block;
}
.walkthrough-tile .portal-gallery__zoom { opacity: 0; }
.walkthrough-tile:hover .portal-gallery__zoom { opacity: 1; }

/* ==========================================================================
   Category-page consumption-model + platform-details + page-cta sections
   --------------------------------------------------------------------------
   Used on /mission-critical-compute (and eventually /general-purpose-compute).
   The page consolidates two "products" (Pay As You Go and Dedicated Capacity)
   that share the same underlying platform — the layout is:
     1. .consumption-models    — the differentiated billing/allocation models
     2. .platform-details      — the shared technical foundation (specs grid)
     3. .page-cta              — final action band with both order CTAs
   Both consumption-model cards get equal visual weight; the difference is
   communicated through copy + a left-edge accent stripe (pink for PAYG,
   slate for Dedicated) so neither feels like the "default" choice.
   ========================================================================== */

/* --- Consumption models grid ----------------------------------------- */
.consumption-models {
    padding: 80px 0;
    background: var(--cp-bg-alt);
}
.consumption-models__intro {
    max-width: 760px;
    margin: 0 auto 48px;
    text-align: center;
}
.consumption-models__intro .eyebrow {
    display: inline-block;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--cp-pink);
    margin-bottom: 14px;
}
.consumption-models__intro h2 {
    margin-bottom: 18px;
    font-size: clamp(1.7rem, 2.6vw, 2.2rem);
}
.consumption-models__intro p {
    color: var(--cp-text-muted);
    font-size: 1.05rem;
    line-height: 1.7;
    margin: 0;
}
.consumption-models__grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 28px;
    max-width: 1140px;
    margin: 0 auto;
}
@media (max-width: 800px) {
    .consumption-models__grid { grid-template-columns: 1fr; }
}

/* Three-card triad variant: Cloud Connect + Backup & Replication in
   the first row, Microsoft 365 centered alone in the second row at
   any width >800px. Used on /veeam-backup where the portfolio has 3
   products vs MCC/GPC's 2 consumption models. Inherits the 2-column
   grid at >800px and the 1-column stack at <=800px from the base. */
.consumption-models__grid--triad > :nth-child(3) {
    grid-column: 1 / -1;
    justify-self: center;
    width: 100%;
    max-width: calc((100% - 28px) / 2);
}
@media (max-width: 800px) {
    .consumption-models__grid--triad > :nth-child(3) {
        max-width: none;
    }
}

/* Consumption model card — pillar-style with a left accent stripe to
   differentiate the two without changing typographic hierarchy. */
.consumption-model {
    position: relative;
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: 14px;
    padding: 36px 32px 32px;
    box-shadow: var(--cp-shadow-card);
    transition: border-color 0.2s ease, box-shadow 0.2s ease,
                transform 0.2s ease;
    display: flex;
    flex-direction: column;
    /* overflow: hidden lets the pseudo-element accent stripe inherit
       the card's rounded corners — without it, the 4px stripe sits as
       a square rectangle that pokes outside the 14px-radius curve at
       the top-left and bottom-left. box-shadow is drawn outside the
       border-box so the hover shadow is unaffected by this clip. */
    overflow: hidden;
}
/* Resting accent stripe — slate, identical on both cards so neither
   reads as the "default" choice. Pink on hover (see ::after below). */
.consumption-model::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 4px;
    height: 100%;
    background: linear-gradient(180deg, #4a6274, #2c3e50);
}
/* Hover-state stripe — pink, layered on top of ::before. CSS can't
   smoothly transition between two gradients via `background`, so we
   fade a second pseudo-element in/out for a clean crossfade. */
.consumption-model::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 4px;
    height: 100%;
    background: linear-gradient(180deg, var(--cp-pink), #b32867);
    opacity: 0;
    transition: opacity 0.25s ease;
}
/* Hover state for the PAYG / Dedicated cards — pink accent stripe
   crossfade, pink-tinted border, soft pink-tinted shadow, 2px lift.
   Gated behind `@media (hover: hover)` so touch devices don't briefly
   trigger the lift + stripe flash on tap before navigating. */
@media (hover: hover) {
    .consumption-model:hover::after { opacity: 1; }
    .consumption-model:hover {
        border-color: rgba(222, 53, 128, 0.4);
        /* Neutral dark shadow, matching .cp-store-card:hover on the
           home page. Pink tint stays on the border + the ::after
           accent stripe; the glow/shadow is intentionally neutral so
           both surfaces (home-page tiles, MCC/GPC consumption-model
           tiles) read with the same "lifted off the page" weight. */
        box-shadow: 0 6px 24px rgba(0, 0, 0, 0.15);
        transform: translateY(-2px);
    }
}
/* Tiny eyebrow above the card heading (`Elastic` / `Reserved`) — small,
   uppercased, brand pink. Source text stays Title Case per the heading
   convention; CSS does the uppercasing for presentational consistency. */
.consumption-model__label {
    display: inline-block;
    font-family: var(--font-heading);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--cp-pink);
    margin-bottom: 6px;
}
.consumption-model__name {
    font-family: var(--font-heading);
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--cp-text);
    margin: 0 0 12px;
    line-height: 1.25;
}
.consumption-model__tagline {
    color: var(--cp-text-muted);
    font-size: 1rem;
    line-height: 1.6;
    margin: 0 0 22px;
}
.consumption-model__bullets {
    margin: 0 0 28px;
    padding-left: 18px;
    flex: 1;
}
.consumption-model__bullets li {
    color: var(--cp-text);
    font-size: 0.95rem;
    line-height: 1.65;
    margin-bottom: 8px;
}
.consumption-model__bullets li:last-child { margin-bottom: 0; }
.consumption-model__bullets li strong {
    color: var(--cp-text);
    font-weight: 600;
}
/* Starting price strip — sits between bullets and CTA so the buyer
   sees price right before the action. Visually echoes the cp-store-card
   pricing pattern (label + value + cycle, baseline-aligned) but no
   border separator since the bullets above already establish a section
   change visually. */
.consumption-model__price {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-bottom: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--cp-border);
}
.consumption-model__price-label {
    font-family: var(--font-heading);
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--cp-text-muted);
}
.consumption-model__price-value {
    font-family: var(--font-heading);
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--cp-pink);
}
.consumption-model__price-cycle {
    font-size: 0.92rem;
    color: var(--cp-text-muted);
}
/* Microcopy under the price row (sibling of `__price`, not child)
   explaining what the starting figure actually buys — base
   connectivity, IP subnet, etc. Reads as a footnote, not as a peer. */
.consumption-model__price-note {
    margin: -10px 0 18px;          /* pull up close under price, breathe below */
    font-size: 0.72rem;
    line-height: 1.4;
    color: var(--cp-text-muted);
}
.consumption-model__cta { margin-top: auto; }
.consumption-model__cta .btn { display: inline-flex; align-items: center; }

/* --- Shared platform details ----------------------------------------- */
.platform-details { padding: 80px 0; background: #ffffff; }
/* Architecture quick-links row above the Platform Details spec grid
   on /mission-critical-compute and /general-purpose-compute. Two
   .btn-secondary buttons centered, with a comfortable gap. Stacks
   to a single column at narrow widths. Bottom margin spaces the
   row from the grid below it. */
.platform-details__cta {
    display: flex;
    justify-content: center;
    gap: 14px;
    margin: 0 0 40px;
    flex-wrap: wrap;
}
@media (max-width: 575px) {
    .platform-details__cta { flex-direction: column; align-items: center; }
    .platform-details__cta .btn-secondary { width: 100%; max-width: 280px; text-align: center; }
}
.platform-details__intro {
    max-width: 760px;
    margin: 0 auto 48px;
    text-align: center;
}
.platform-details__intro .eyebrow {
    display: inline-block;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--cp-pink);
    margin-bottom: 14px;
}
.platform-details__intro h2 {
    margin-bottom: 18px;
    font-size: clamp(1.7rem, 2.6vw, 2.2rem);
}
.platform-details__intro p {
    color: var(--cp-text-muted);
    font-size: 1.05rem;
    line-height: 1.7;
    margin: 0;
}
.platform-details__grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 24px;
    max-width: 1140px;
    margin: 0 auto;
}
/* When the grid has an odd card count (e.g. 3 cards in a 2-col grid),
   center the orphan last card on its own row at half-width — instead
   of leaving it stretched to full container width or floating to one
   side. Half-width = (100% - 24px gap) / 2 = calc(50% - 12px). Mobile
   below resets this since the grid stacks to 1-up. */
/* Scoped with :not(--three) so this rule fires only on the default
   2-col variant. The --three variant has its own breakpoint logic
   (3-col at desktop, 2-col at tablet, 1-col at mobile) and is
   handled by .platform-details__grid--three rules instead — without
   the :not() guard, this orphan-center rule would fire on 3-col
   .platform-details__grid--three layouts too, producing a
   half-width centered "card 3" that breaks the 3-up row above it. */
.platform-details__grid:not(.platform-details__grid--three) > :last-child:nth-child(odd) {
    grid-column: 1 / -1;
    max-width: calc(50% - 12px);
    justify-self: center;
}
/* On the --three variant at tablet (when the grid drops from 3-up to
   2-up), apply the same orphan-center treatment so the 3rd card
   doesn't sprawl across both columns. */
@media (max-width: 991px) {
    .platform-details__grid--three > :last-child:nth-child(odd) {
        grid-column: 1 / -1;
        max-width: calc(50% - 12px);
        justify-self: center;
    }
}
@media (max-width: 767px) {
    .platform-details__grid { grid-template-columns: 1fr; }
    /* Specificity must match the desktop orphan rule above (which
       uses :not(--three) for scoping). Without the same :not(),
       this reset has lower specificity and the orphan card stays
       capped at calc(50% - 12px) on mobile. */
    .platform-details__grid:not(.platform-details__grid--three) > :last-child:nth-child(odd),
    .platform-details__grid--three > :last-child:nth-child(odd) {
        grid-column: auto;
        max-width: 100%;
        justify-self: stretch;
    }
}

/* Spec card — same family as .dc-specs-card on /data-centers but
   slightly more substantial padding since this is the flagship product
   page and the cards carry technical credibility. */
/* =============================================================
   Platform spec cards — three interchangeable styles.
     --v1  flat: white card, 1px border, icon+title, bullets below
           (original 2026-04-14 look; lightest visual weight)
     --v2  product-card: CP gradient header with numbered badge,
           body with bullets below (mirrors WHMCS `.vdc-product-card`)
     --v3  feature-tile: uppercase h5 + purple underline, pink FA6
           check-circle bullets (mirrors `.vdc-description-short > div`
           from WHMCS product listings — the inner feature tiles)
   Apply by adding the modifier class to any card markup that follows
   the variant's expected shape. Full rundown + each variant's expected
   HTML skeleton: claude/design-guidelines.md § "Platform Spec Cards".
   ============================================================= */

/* Shared base — position:relative so the US-flag ::before can anchor
   to the card on any variant. */
.platform-spec-card { position: relative; }

/* ---------- V1: flat ---------- */
.platform-spec-card--v1 {
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: 12px;
    padding: 28px 28px 24px;
    transition: border-color 0.2s ease, box-shadow 0.2s ease,
                transform 0.2s ease;
}
.platform-spec-card--v1:hover {
    border-color: rgba(222, 53, 128, 0.32);
    box-shadow: 0 10px 26px rgba(26, 34, 51, 0.08);
    transform: translateY(-1px);
}
.platform-spec-card--v1 h4 {
    font-family: var(--font-heading);
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--cp-text);
    margin: 0 0 16px;
    display: flex;
    align-items: center;
    gap: 12px;
}
.platform-spec-card--v1 h4 i {
    color: var(--cp-pink);
    font-size: 1rem;
    width: 22px;
    text-align: center;
}
.platform-spec-card--v1 ul {
    margin: 0;
    padding-left: 20px;
}
.platform-spec-card--v1 ul li {
    margin-bottom: 6px;
    font-size: 0.92rem;
    line-height: 1.6;
    color: var(--cp-text-muted);
}
.platform-spec-card--v1 ul li:last-child { margin-bottom: 0; }
.platform-spec-card--v1 ul li strong { color: var(--cp-text); font-weight: 600; }

/* ---------- V2: gradient header + numbered badge ---------- */
.platform-spec-card--v2 {
    background: #ffffff;
    border: none;
    border-radius: 8px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
    overflow: hidden;
    transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.platform-spec-card--v2:hover {
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
    transform: translateY(-2px);
}
.platform-spec-card--v2 .platform-spec-card__header {
    background: var(--cp-gradient-default);
    color: #fff;
    padding: 16px 20px;
    display: flex;
    align-items: center;
    gap: 10px;
    position: relative;
}
.platform-spec-card--v2 .platform-spec-card__num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.92);
    border: 1.5px solid rgba(255, 255, 255, 0.6);
    font-family: var(--font-heading);
    font-size: 11px;
    font-weight: 700;
    color: var(--cp-text-heading);
    flex-shrink: 0;
    line-height: 1;
}
.platform-spec-card--v2 .platform-spec-card__header h4 {
    font-family: var(--font-heading);
    font-size: 1.05rem;
    font-weight: 600;
    color: #fff;
    margin: 0;
    flex: 1;
    line-height: 1.25;
}
.platform-spec-card--v2 .platform-spec-card__icon {
    color: rgba(255, 255, 255, 0.85);
    font-size: 1.05rem;
    flex-shrink: 0;
    transition: opacity 1000ms ease;
}
.platform-spec-card--v2 .platform-spec-card__body {
    padding: 22px 22px 20px;
}
.platform-spec-card--v2 .platform-spec-card__body ul {
    margin: 0;
    padding-left: 20px;
}
.platform-spec-card--v2 .platform-spec-card__body ul li {
    margin-bottom: 6px;
    font-size: 0.92rem;
    line-height: 1.6;
    color: var(--cp-text-muted);
}
.platform-spec-card--v2 .platform-spec-card__body ul li:last-child { margin-bottom: 0; }
.platform-spec-card--v2 .platform-spec-card__body ul li strong { color: var(--cp-text); font-weight: 600; }

/* ---------- V3: "Best suited for" feature tile ---------- */
/* Tokens ported verbatim from vdc.css `.vdc-description-short > div`
   on the WHMCS orderform. The h5's 2px purple bottom-border and
   FA6-check-circle bullets are the signature visual. */
.platform-spec-card--v3 {
    background: #ffffff;
    border: 1px solid #e8e8e8;
    border-radius: 6px;
    padding: 14px 16px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
    transition: transform 0.25s ease, box-shadow 0.25s ease,
                border-color 0.25s ease;
    font-family: var(--font-heading);
    line-height: 1.15;
}
.platform-spec-card--v3:hover {
    transform: translateY(-3px);
    box-shadow: 0 8px 24px rgba(222, 53, 128, 0.12),
                0 4px 12px rgba(0, 0, 0, 0.06);
    border-color: rgba(222, 53, 128, 0.3);
}
.platform-spec-card--v3 h5 {
    font-family: var(--font-heading);
    font-size: 13px;
    font-weight: 700;
    color: #000;
    padding: 0 0 5px 0;
    margin: 0 0 10px 0;
    border-bottom: 2px solid #bf6bb4;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}
.platform-spec-card--v3 ul {
    list-style: none;
    padding: 0;
    margin: 0;
}
.platform-spec-card--v3 ul li {
    padding: 2px 0 2px 22px;
    position: relative;
    font-size: 14px;
    line-height: 1.55;
    color: var(--cp-text);
}
.platform-spec-card--v3 ul li::before {
    content: "\f058";                 /* fa-circle-check (solid) */
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    font-size: 12px;
    color: var(--cp-pink);
    position: absolute;
    left: 0;
    top: 6px;
}
.platform-spec-card--v3 ul li strong { color: var(--cp-text-heading); font-weight: 600; }

/* ---------- US-flag accent (Support & SLA card, all variants) ----------
   The card already has position:relative via the shared base rule.
   V1 / V3: flag fades into the top-right corner.
   V2: flag cross-fades with the headset icon inside the gradient header. */

.platform-spec-card--v1.platform-spec-card--us::before,
.platform-spec-card--v3.platform-spec-card--us::before {
    content: "";
    position: absolute;
    top: 16px;
    right: 16px;
    width: 48px;
    height: 25px;                    /* ~1.9:1, matches US flag 7410×3900 */
    background-image: url('/assets/img/flags/us.svg');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    border-radius: 2px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
    opacity: 0;
    transition: opacity 1000ms ease;
    pointer-events: none;
}
.platform-spec-card--v1.platform-spec-card--us:hover::before,
.platform-spec-card--v3.platform-spec-card--us:hover::before {
    opacity: 1;
}

.platform-spec-card--v2.platform-spec-card--us .platform-spec-card__header::after {
    content: "";
    position: absolute;
    top: 50%;
    right: 20px;
    transform: translateY(-50%);
    width: 44px;
    height: 23px;
    background-image: url('/assets/img/flags/us.svg');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    border-radius: 2px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
    opacity: 0;
    transition: opacity 1000ms ease;
    pointer-events: none;
}
.platform-spec-card--v2.platform-spec-card--us:hover .platform-spec-card__header::after {
    opacity: 1;
}
.platform-spec-card--v2.platform-spec-card--us:hover .platform-spec-card__icon {
    opacity: 0;
}

/* "Best Suited For" callout — a horizontal strip below the specs grid,
   prescriptive use cases separated by middots. Quieter than a card,
   wider than a bullet list. */
/* Inline `.cross-sell__inner` context overrides when embedded inside
   `.platform-details` (replaces the old "Best Suited For" strip that
   used to sit here). The card's own max-width + centering come from
   `.cross-sell__inner`; we just need breathing room above and a size
   drop so the note reads smaller than the spec-card bullets (0.92rem),
   since it's a footnote/suggestion rather than a sibling content block.
   On GPC and Veeam, `.cross-sell__inner` keeps its full-size 1rem text
   because there it lives inside a full-width `<section class="cross-
   sell">` band where it's the only content. */
.platform-details .cross-sell__inner {
    margin-top: 36px;
}
.platform-details .cross-sell__inner p {
    font-size: 0.88rem;
    line-height: 1.55;
}

/* --- Page CTA band --------------------------------------------------- */
/* Page-CTA band sits on `--cp-bg-alt` so it matches the Consumption
   Models section above and breaks up the run of white between
   Platform Details (white) → Page CTA (alt) → footer. The pink
   gradient inside `.page-cta__inner` still pops — arguably more —
   against the light grey bg than it did against pure white. */
/* Final CTA band — white bg so it doesn't collide with preceding
   gray sections (e.g. /network-architecture's `.arch-section--panel`
   hardware spotlights, which now sit directly before the CTA on
   some pages). The `.page-cta__inner` card carries its own gradient
   + shadow, so it pops on either a white or grey surface. */
.page-cta { padding: 72px 0; background: #ffffff; }
/* Section bg variant — gray instead of white. Used on pages where the
   section above the CTA is also white, so a color shift is needed for
   the closing band to read as a separate beat. The inner gradient
   panel is unchanged; only the section's outer bg flips. */
.page-cta--alt-bg { background: var(--cp-bg-alt); }
.page-cta__inner {
    max-width: 760px;
    margin: 0 auto;
    text-align: center;
    padding: 56px 48px;
    background: var(--cp-gradient-default);
    color: #ffffff;
    border-radius: var(--cp-r-lg);
    box-shadow: 0 24px 64px rgba(26, 34, 51, 0.2);
}
.page-cta__inner h2 { color: #ffffff; margin-bottom: 12px; }
/* :not(.page-cta__followup) so the followup paragraph isn't picked
   up here — it has its own .page-cta__followup rule with top margin
   and zero bottom. Without :not(), the (0,1,1) specificity of this
   selector outweighs .page-cta__followup's (0,1,0) and the followup
   silently inherits this 28px bottom margin → 28px chin below the
   followup before the panel's own 56px padding-bottom. */
.page-cta__inner > p:not(.page-cta__followup) {
    color: rgba(255, 255, 255, 0.88);
    font-size: 1.05rem;
    margin-bottom: 28px;
}
.page-cta__row {
    display: flex;
    gap: 14px;
    justify-content: center;
    flex-wrap: wrap;
    /* No bottom margin — the gap to the followup paragraph below is
       now owned by the followup's margin-top instead of the row's
       margin-bottom. Either is mathematically equivalent, but
       semantically the row is a self-contained "buttons" unit that
       ends at its own bottom; the followup adds its own top breathing
       room. Keeps the panel's bottom-padding distance from the last
       element symmetrical with the top, no chin. */
    margin-bottom: 0;
}
/* Inverted button styling on the gradient panel — same pattern as
   .final-cta .btn-primary on the home page final CTA. */
.page-cta .btn-primary {
    background: #ffffff !important;
    color: var(--cp-pink) !important;
    border-color: #ffffff !important;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.24);
}
.page-cta .btn-primary:hover,
.page-cta .btn-primary:focus {
    background: #ffffff !important;
    color: var(--cp-pink-dark) !important;
    border-color: #ffffff !important;
    transform: translateY(-2px);
}
.page-cta__followup {
    /* Top breathing room from the row above; zero bottom so the
       panel's padding-bottom is the only gap to the panel border. */
    margin: 20px 0 0;
    font-size: 0.92rem;
    color: rgba(255, 255, 255, 0.78);
}
.page-cta__followup a {
    color: #ffffff;
    font-weight: 600;
    text-decoration: none;
    border-bottom: 1px solid rgba(255, 255, 255, 0.4);
    transition: border-color 0.2s ease;
}

.page-cta__followup a:hover { border-bottom-color: #ffffff; }

/* ==========================================================================
   Scroll-triggered reveal animations.
   --------------------------------------------------------------------------
   Single attribute system: any [data-reveal] element starts hidden +
   slightly translated, transitions to visible state when an
   IntersectionObserver in site.js adds .is-revealed.
   The motion vocabulary is intentionally narrow:
     - opacity 0 -> 1
     - translateY 24px -> 0 (cards) or 16px -> 0 (subtle, e.g. final CTA)
     - duration 600ms
     - easing cubic-bezier(0.22, 1, 0.36, 1) — a smooth decelerate
       that feels deliberate, not bouncy
   No rotate, no scale, no overshoot. Card stagger comes from
   transition-delay applied to nth-child selectors below.
   prefers-reduced-motion: site.js skips the observer and immediately
   marks every element revealed — and for safety we also drop the
   transform delta here so reduced-motion clients see no motion.
   ========================================================================== */
[data-reveal] {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity 600ms cubic-bezier(0.22, 1, 0.36, 1),
                transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
    will-change: opacity, transform;
}
[data-reveal].is-revealed {
    opacity: 1;
    transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
    [data-reveal] {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
}

/* Smaller travel for subtle reveals — final CTA card. */
.cta-wrap[data-reveal] { transform: translateY(16px); }
.cta-wrap[data-reveal].is-revealed { transform: translateY(0); }

/* Stagger for the home product cards (MCC/GPC and the 3 Veeam cards
   share .cp-store-browse__grid). The IntersectionObserver triggers
   each card on its own intersection; for cards in the same row this
   happens at almost the same scroll position, so the transition-delay
   creates the visual staircase within the row. 100ms gap is enterprise-
   neutral — readable, not playful. */
.cp-store-browse__grid > [data-reveal]:nth-child(1).is-revealed { transition-delay: 0ms; }
.cp-store-browse__grid > [data-reveal]:nth-child(2).is-revealed { transition-delay: 100ms; }
.cp-store-browse__grid > [data-reveal]:nth-child(3).is-revealed { transition-delay: 200ms; }

/* Pillars grid — 3-col desktop, so cards 1-3 form row 1 and 4-6 form
   row 2. The nth-child(3n+1/2/3) pattern resets the within-row stagger
   for each row, so each row reveals as a group. 80ms intra-row gap is
   tighter than product cards because there are more pillars and we
   don't want the second row to feel laggy. */
.pillars-grid > [data-reveal]:nth-child(3n+1).is-revealed { transition-delay: 0ms; }
.pillars-grid > [data-reveal]:nth-child(3n+2).is-revealed { transition-delay: 80ms; }
.pillars-grid > [data-reveal]:nth-child(3n+3).is-revealed { transition-delay: 160ms; }

/* Cloud Manager split — text on the left reveals first, screenshot on
   the right follows after a small lead/follow gap so the section feels
   like a story unfolding (intro -> proof) rather than two unrelated
   pieces popping in together. */
.platform-principle__split > [data-reveal]:nth-child(2).is-revealed {
    transition-delay: 140ms;
}

/* ==========================================================================
   Lightbox3 (Lokesh Dhakar) — vendor lib loaded from
   assets/vendor/lightbox3/. Defaults are good; only minor add-ons here.
   Use `<a href="full.jpg" data-lightbox="..." data-title="...">
   <img src="thumb.jpg"></a>` to make any image click-to-enlarge.
   data-title accepts HTML (Lightbox3 sets caption via innerHTML), so
   `<br><span class="lb-subtitle">...</span>` gives a two-line caption
   with a dimmer technical-detail line below the headline.
   ========================================================================== */
.lightbox3-caption .lb-subtitle {
    display: block;
    margin-top: 3px;
    font-size: 0.85em;
    font-weight: 400;
    opacity: 0.7;
    letter-spacing: 0.01em;
}

/* Scroll-to-top floating button. Fixed bottom-right, circular, pink
   CP brand color. Hidden until user scrolls past ~400px (JS toggles
   .is-visible). Smooth-scrolls back to top on click. Sized for
   48px min-touch-target on iOS. z-index below modals/header (1030)
   but above page content. */
/* Floating button stack — fixed container that holds both the TOC
   toggle and the scroll-top button as flex siblings. Positioning
   lives here (right edge + bottom offset), per-breakpoint; the
   buttons inside are static flex items and inherit the alignment.
   This eliminates the "both buttons should be aligned but ended up
   in different spots" drift that happened when each had its own
   position rules across different breakpoints. */
.cp-floating-stack {
    position: fixed;
    right: 24px;
    bottom: 84px;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
}
/* Tablet portrait — raise the stack into the right-hand thumb-
   reach zone for iPad-like devices held in portrait. */
@media (min-width: 601px) and (max-width: 1199px) and (orientation: portrait) {
    .cp-floating-stack {
        bottom: 33vh;
    }
}
/* Phones (any orientation) + tablet landscape — shorter height
   pushes thumb reach higher up the screen; right-edge tighter. */
@media (max-width: 600px),
       (min-width: 601px) and (max-width: 1199px) and (orientation: landscape) {
    .cp-floating-stack {
        bottom: 40vh;
        right: 16px;
    }
}

.cp-scroll-top {
    /* Position inherited from .cp-floating-stack (flex child) —
       no `position: fixed` here. Size 42×42 matches the TOC
       toggle above it. Opacity-based hide so the button keeps its
       slot in the stack even while inert (no layout jump when it
       appears on scroll). */
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: var(--cp-pink);
    color: #fff;
    border: 0;
    cursor: pointer;
    opacity: 0;
    visibility: hidden;
    transform: translateY(10px);
    transition: opacity 0.28s ease,
                visibility 0.28s ease,
                transform 0.28s cubic-bezier(0.4, 0, 0.2, 1),
                background 0.2s ease,
                box-shadow 0.2s ease;
    box-shadow: 0 4px 14px rgba(222, 53, 128, 0.35);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 15px;
    line-height: 1;
    padding: 0;
    flex: 0 0 auto;
}
.cp-scroll-top.is-visible {
    opacity: 0.8;
    visibility: visible;
    transform: translateY(0);
}
.cp-scroll-top:hover,
.cp-scroll-top:focus {
    opacity: 1;
    background: var(--cp-pink-dark);
    color: #fff;
    box-shadow: 0 6px 20px rgba(222, 53, 128, 0.45);
    outline: none;
}
.cp-scroll-top:focus-visible {
    outline: 3px solid rgba(222, 53, 128, 0.5);
    outline-offset: 2px;
}
.cp-scroll-top:active {
    transform: translateY(0) scale(0.95);
}
/* Per-breakpoint thumb-reach positioning (tablet portrait 33vh,
   phone + tablet landscape 40vh) now lives on .cp-floating-stack
   above — the whole stack moves together so TOC and scroll-top
   stay aligned. */

/* ==========================================================================
   /data-centers — redesigned facility pages (2026-04-18)
   --------------------------------------------------------------------------
   Each facility ("mini-page") is an `.about-section` with a wider inner
   container (`.dc-section-inner`, 1120px) than the default 780px reading
   column. The inner lays out:
     1. `.about-section__meta`  — number + label (global)
     2. `.dc-partner`           — logo badge + wordmark + location line
     3. h2 + `.dc-lead`         — section headline and lead paragraph
     4. `.dc-facility-grid`     — 2-col: map+address on left, photo on right
     5. `.dc-prose`             — narrow-column descriptive paragraphs
     6. `.platform-details__grid` (+ `.dc-feature-grid`) — spec cards

   New components introduced:
     .dc-page-section         scope hook; tiers vertical rhythm per facility
     .dc-section-inner        wider reading column inside `.about-section`
     .dc-partner              logo badge + facility wordmark row
     .dc-partner__badge       white-framed card around the partner logo
     .dc-facility-grid        2-col split (map column + photo/logo column)
     .dc-map-frame            rounded, shadowed iframe container
     .dc-address-card         pink-bar accent card under the map
     .dc-photo-frame          rounded image frame with hover zoom icon
     .dc-photo-frame--logo    logo fallback when no exterior photo exists
     .dc-prose                narrow prose column under the split grid
     .dc-feature-grid         margin-top wrapper for the spec-card grid
     .platform-details__grid--three  3-col variant of the shared grid
     .dc-divider              `.platform-principle` override — tighter pad
     .dc-colo-grid            2-col: prose + highlights card grid
     .dc-colo-highlights/__highlight     quick-hit colocation value tiles

   All rules are scoped with `.dc-*` classes so they don't bleed into
   other pages that use `.about-section` / `.platform-spec-card` etc.
   ========================================================================== */

/* Wider reading column for the DC sections — the default 780px inside
   `.about-section__inner` is too narrow for a 2-col split with a map.
   We opt out of `.about-section__inner` entirely on these sections and
   use `.dc-section-inner` instead. */
.dc-section-inner {
    /* Width is governed by the parent .container (Bootstrap 1140px max
       at >=1200px viewport), matching the gold-standard width treatment
       used by /index.php's Management Experience section. Previously
       this rule capped at 1120px which pinched content 10px each side
       narrower than the container — visible drift on a wide laptop. */
    margin: 0 auto;
}

/* Vertical rhythm inside a facility block. The default `.about-section`
   gives us `padding: 80px 0`. We keep that for the meta + heading stack,
   and use margin helpers on the inner blocks to space them. */
.dc-page-section .about-section__meta {
    margin-bottom: 14px;
}
/* DC sections drop the numeric badge (01/02/03) and promote the label
   itself to a pink pill — same visual recipe as the old .about-section__
   num (pink border + bg tint + rounded). Keeps the site's pill language
   consistent with the hero's .cp-store-card__feat pills above, but
   doesn't disturb /about-us or any other page that still wants plain
   uppercase-muted labels. Scoped by .dc-page-section parent only. */
.dc-page-section .about-section__label {
    display: inline-block;
    padding: 4px 10px;
    border: 1px solid rgba(222, 53, 128, 0.3);
    border-radius: 4px;
    background: rgba(222, 53, 128, 0.06);
    color: var(--cp-pink);
    font-weight: 700;
    letter-spacing: 0.08em;
}

/* DC badge pinned to the right of the .dc-partner row — sits in
   line with the logo + name + location header block. margin-left:
   auto pushes it to the far right of the existing flex layout on
   .dc-partner without needing extra containers. Kept matched in
   size/style across both facilities via .about-section__label
   (the existing pink pill rule). On narrow viewports .dc-partner
   wraps and the badge drops below. */
.dc-partner__badge-label {
    flex: 0 0 auto;
    margin-left: auto;
    align-self: center;
    white-space: nowrap;
}
@media (max-width: 640px) {
    .dc-partner {
        flex-wrap: wrap;
    }
    .dc-partner__badge-label {
        margin-left: 0;
        order: 3;
        width: 100%;
    }
}
.dc-page-section h2 {
    margin-bottom: 18px;
    font-size: clamp(1.75rem, 3vw, 2.4rem);
    line-height: 1.22;
}

/* Lead paragraph — one step larger than body, sets the intro tone
   below the h2 and above the split grid. */
.dc-lead {
    font-family: var(--font-heading);
    font-size: clamp(1.05rem, 1.5vw, 1.2rem);
    font-weight: 600;
    color: var(--cp-text-heading);
    line-height: 1.5;
    margin: 0 0 36px;
    max-width: 820px;
}

/* ---- Partner identity row (logo badge + eyebrow wordmark) ---- */
.dc-partner {
    display: flex;
    align-items: center;
    gap: 18px;
    /* Tightened: header stack reads as one composed block (eyebrow pill
       + partner row + h2 + lead). Was separated by a border-bottom +
       22px padding, which visually cut the section header in two. The
       panel wrapper below takes over as the containing boundary. */
    margin: 4px 0 18px;
}
.dc-partner__badge {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 84px;
    height: 84px;
    padding: 10px 12px;
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r-sm);
    box-shadow: 0 2px 10px rgba(26, 34, 51, 0.06);
    overflow: hidden;
}
.dc-partner__badge--wide {
    width: 132px;
    padding: 16px;
}
.dc-partner__logo {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    display: block;
    object-fit: contain;
}
.dc-partner__meta {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}
.dc-partner__eyebrow {
    font-family: var(--font-heading);
    font-size: clamp(0.95rem, 1.4vw, 1.15rem);
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--cp-text-heading);
    line-height: 1.15;
}
.dc-partner__location {
    font-size: 0.92rem;
    color: var(--cp-text-muted);
    display: inline-flex;
    align-items: center;
    gap: 8px;
    line-height: 1.3;
}
.dc-partner__location i {
    color: var(--cp-pink);
    font-size: 0.88rem;
}
@media (max-width: 560px) {
    .dc-partner { gap: 14px; }
    .dc-partner__badge { width: 64px; height: 64px; padding: 6px 8px; }
    .dc-partner__badge--wide { width: 96px; padding: 10px; }
}

/* ---- Split grid: map + address on left, photo on right ---- */
.dc-facility-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 32px;
    align-items: stretch;
    margin-bottom: 44px;
}
.dc-facility-grid__map,
.dc-facility-grid__photo {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* Unified map module — map iframe + integrated address footer in one
   visual container. The module carries the border/radius/shadow so the
   inner pieces don't each render as separate cards ("card inside card"
   was the feedback). Matches `.dc-photo-frame`'s framing so both sides
   of the facility-grid row read as the same visual system. */
.dc-map-module {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 320px;
    border-radius: 12px;
    overflow: hidden;
    border: 1px solid var(--cp-border);
    box-shadow: 0 14px 38px rgba(26, 34, 51, 0.14);
    background: #ffffff;
}

/* Map pane — inner iframe container. Positioned absolute inside
   .dc-map-module__map-link so it fills the anchor's height exactly
   (rather than collapsing to its own min-height when the row is
   stretched taller than 240px by the photo module on the other
   side). The anchor carries the flex/min-height; the frame just
   carpets it. */
.dc-map-frame {
    position: absolute;
    inset: 0;
    overflow: hidden;
    background: #e8edf2;
}
.dc-map-frame iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
    /* pointer-events: none lets the wrapping .dc-map-module__map-link
       anchor catch clicks anywhere on the map area — so clicking the
       pindrop (or anywhere else on the map) opens the full location
       in Google Maps in a new tab, rather than triggering the
       iframe's own "View larger map" tooltip. Map becomes a "picture
       that opens Google Maps" instead of a draggable embed, which is
       the right tradeoff for a marketing page. */
    pointer-events: none;
}

/* Address card — when standalone (future reuse), keeps its own pink-
   left-accent card styling. When INSIDE .dc-map-module, the scoped
   override below reshapes it into an integrated footer. */
.dc-address-card {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    margin-top: 14px;
    padding: 14px 18px;
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-left: 3px solid var(--cp-pink);
    border-radius: var(--cp-r-sm);
    box-shadow: 0 2px 8px rgba(26, 34, 51, 0.04);
}
.dc-map-module .dc-address-card {
    /* Integrated-footer variant: no own radius/shadow, no pink-left
       accent (the module owns the framing), subtle tinted surface to
       distinguish it from the map above. Top border is the only
       internal divider. Flex row so the address info + directions
       button split the footer horizontally. min-height matches the
       photo-module's footer so both bottoms read as the same bar. */
    flex: 0 0 auto;
    display: flex;
    align-items: stretch;
    gap: 0;
    margin-top: 0;
    padding: 0;
    min-height: 86px;
    background: rgba(26, 34, 51, 0.025);
    border: 0;
    border-top: 1px solid var(--cp-border);
    border-radius: 0;
    box-shadow: none;
}

/* Address info (left side of footer) — plain text block (not
   clickable). 2 lines (address on line 1, hours on line 2) matching
   the photo footer's title + subtitle rhythm. Content vertically
   centered in the 86px bar via flex-column + justify-center so it
   lines up with the photo-footer info layout. Only the Directions
   button on the right is interactive — clicking elsewhere on the
   footer bar does nothing, per user feedback. */
.dc-address-card__info {
    display: flex;
    flex-direction: column;
    justify-content: center;
    flex: 1 1 auto;
    min-width: 0;
    padding: 14px 20px;
    color: inherit;
}

/* Directions button — solid pink CTA, the primary action in the
   map-module footer. Leading turn-right icon + "Directions" label.
   Fixed 120px width (shared with .dc-photo-footer__action) so both
   module footers present identical button widths regardless of
   label length. Content centered inside the fixed box. */
.dc-address-card__directions {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex: 0 0 auto;
    width: 120px;
    padding: 0;
    background: var(--cp-pink);
    color: #ffffff;
    font-family: var(--font-heading);
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-decoration: none;
    border-left: 1px solid var(--cp-border);
    transition: background-color 0.15s ease;
}
.dc-address-card__directions i.fa-diamond-turn-right {
    font-size: 0.82rem;
    transition: transform 0.2s ease;
}
.dc-address-card__directions:hover,
.dc-address-card__directions:focus-visible {
    background: var(--cp-pink-dark);
    color: #ffffff;
    text-decoration: none;
}
.dc-address-card__directions:hover i.fa-diamond-turn-right,
.dc-address-card__directions:focus-visible i.fa-diamond-turn-right {
    transform: translateX(2px);
}

/* Map anchor — wraps the iframe in a clickable link that opens the
   location in Google Maps. Fills the flex space above the address
   footer. Cursor pointer signals "this is clickable" since the
   iframe inside has pointer-events: none. */
.dc-map-module__map-link {
    display: block;
    position: relative;
    flex: 1 1 auto;
    min-height: 240px;
    cursor: pointer;
    text-decoration: none;
    color: inherit;
}

/* Stack the directions button below the info block on narrow
   viewports — side-by-side becomes cramped under ~480px wide. */
@media (max-width: 480px) {
    .dc-map-module .dc-address-card {
        flex-direction: column;
    }
    .dc-address-card__directions {
        justify-content: center;
        padding: 12px 20px;
        border-left: 0;
        border-top: 1px solid var(--cp-border);
    }
}

/* Map tag chip — small top-left label that claims the map as an
   intentional asset, not a placeholder. Pink-tinted pill with icon
   and short text. Pointer-events none so it passes clicks through
   to the underlying map-link anchor. */
.dc-map-frame__tag {
    position: absolute;
    top: 14px;
    left: 14px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 11px;
    background: rgba(255, 255, 255, 0.96);
    color: var(--cp-text-heading);
    font-family: var(--font-heading);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    border: 1px solid var(--cp-border);
    border-radius: 999px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
    pointer-events: none;
    z-index: 2;
}
.dc-map-frame__tag i {
    color: var(--cp-pink);
    font-size: 0.7rem;
}

/* Partner role tags — small row of pills below the partner logo +
   wordmark row on facilities that have a specific role (DR target,
   off-site backup, etc.). Makes the "this facility is for X"
   visually explicit without needing a second headline. */
.dc-partner__tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
}
.dc-partner__tag {
    display: inline-block;
    padding: 3px 10px;
    background: rgba(26, 34, 51, 0.05);
    color: var(--cp-text-muted);
    font-family: var(--font-heading);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    border: 1px solid var(--cp-border);
    border-radius: 4px;
}
.dc-partner__tag--role {
    background: rgba(222, 53, 128, 0.06);
    color: var(--cp-pink);
    border-color: rgba(222, 53, 128, 0.25);
}

/* Compliance & certifications card — 7th card in the Cologix grid,
   stylized as a full-width "capstone" so the 3-col grid doesn't
   leave it orphaned on its own row. Inside, the bullet list flows
   in a multi-column layout so the wider card reads as a neat
   summary block rather than a lonely single-column list. Icon +
   header styling inherits from the shared .platform-spec-card--v1
   base. */
.platform-spec-card--compliance {
    grid-column: 1 / -1;
}
.platform-spec-card--compliance ul {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 6px 32px;
    padding-left: 0;
    list-style: none;
}
.platform-spec-card--compliance ul li {
    position: relative;
    padding-left: 20px;
    margin-bottom: 0;
}
.platform-spec-card--compliance ul li::before {
    content: "\f058"; /* fa-check-circle */
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    position: absolute;
    left: 0;
    top: 0.1em;
    color: var(--cp-pink);
    font-size: 0.88rem;
}
@media (max-width: 991px) {
    .platform-spec-card--compliance ul {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}
@media (max-width: 560px) {
    .platform-spec-card--compliance ul {
        grid-template-columns: 1fr;
    }
}

/* Scope footnote inside the compliance card — sits under the bullets
   as small muted italic fine-print, keeping the caveat physically
   tied to the claim it qualifies. Top border is a thin tint that
   separates it from the cert list without making it feel like a
   separate component. */
.platform-spec-card--compliance .platform-spec-card__footnote {
    margin: 18px 0 0;
    padding-top: 14px;
    border-top: 1px solid var(--cp-border);
    font-size: 0.78rem;
    line-height: 1.55;
    color: var(--cp-text-muted);
    font-style: italic;
}

/* Cloud Propeller compliance-support note — pink-tinted surfaced
   callout positioning CP's own regulatory support posture (HIPAA /
   PCI DSS / CJIS / Ohio LEADS) separately from the facility claims.
   Soft pink surface signals "this is ours" while the disclaimer
   above signals "that was the facility's". Together they make the
   two scopes visually distinct. */
.dc-compliance-note {
    max-width: 900px;
    margin: 16px auto 0;
    padding: 20px 26px;
    background: rgba(222, 53, 128, 0.04);
    border: 1px solid rgba(222, 53, 128, 0.18);
    border-radius: var(--cp-r-sm);
    color: var(--cp-text);
}
/* Font-size + line-height declared directly on the <p> selector
   because `.about-section p { font-size: 1.05rem; line-height: 1.7 }`
   (line ~3075) has equal specificity (0,1,1) to `.dc-compliance-note
   p`, so putting font-size on the parent div would be overridden by
   that rule on the <p>. Targeting the <p> directly wins on source-
   order tie-break and forces the fine-print scale we want. */
.dc-compliance-note p {
    margin: 0 0 12px;
    font-size: 0.9rem;
    line-height: 1.6;
}
.dc-compliance-note p:last-child {
    margin-bottom: 0;
}
.dc-compliance-note strong {
    color: var(--cp-text-heading);
}
@media (max-width: 560px) {
    .dc-compliance-note {
        padding: 18px 20px;
    }
}

/* Colocation 2-col service layout — left surfaced "Deployment Fit"
   card, right compact highlights grid. Distinct from DC1/DC2 which
   are facility profiles stacked text-then-grid; colocation is a
   service layer inside the primary facility so it reads as a
   polished service card + supporting proof chips. */
.dc-page-section--colo .dc-colo-layout {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    gap: 32px;
    align-items: start;
    margin-top: 16px;
}
@media (max-width: 991px) {
    .dc-page-section--colo .dc-colo-layout {
        grid-template-columns: 1fr;
    }
}

/* Deployment Fit card — brighter white, soft elevation. Pink
   accent is now a short corner tab (via ::before) instead of a
   full-width top border, which reads as "premium content panel"
   rather than "alert box." Length tuned to match the eyebrow
   width-ish. */
.dc-colo-card {
    position: relative;
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r);
    padding: 32px 36px 28px;
    box-shadow: 0 4px 20px rgba(26, 34, 51, 0.04);
}
.dc-colo-card::before {
    content: "";
    position: absolute;
    top: -1px; /* overlap the 1px top border so the tab reads solid */
    left: 36px; /* aligns with content left-edge (matches padding) */
    width: 44px;
    height: 2px;
    background: var(--cp-pink);
    border-radius: 0 0 2px 2px;
}
.dc-colo-card__eyebrow {
    display: inline-block;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.74rem;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--cp-pink);
    margin-bottom: 16px;
}

/* Mini-facts row — three at-a-glance qualifiers. Typography-led
   now rather than pill/button: no tinted container, just a thin
   bottom border separating the row from the prose. Smaller, muted
   text; pink icon anchors each fact. */
.dc-colo-card__facts {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 28px;
    margin: 0 0 22px;
    padding: 0 0 16px;
    border-bottom: 1px solid var(--cp-border);
}
.dc-colo-card__fact {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-family: var(--font-heading);
    font-size: 0.78rem;
    font-weight: 500;
    letter-spacing: 0.03em;
    color: var(--cp-text-muted);
    white-space: nowrap;
}
.dc-colo-card__fact i {
    color: var(--cp-pink);
    font-size: 0.78rem;
}

/* Content chunks — paragraph groupings with a thin dashed rule
   between them. No visible subheads (keeps it clean), but the
   physical separation signals "new aspect" to the reader. */
.dc-colo-card__chunk + .dc-colo-card__chunk {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px dashed var(--cp-border);
}
.dc-colo-card__chunk p {
    margin: 0;
    font-size: 0.98rem;
    line-height: 1.7;
    color: var(--cp-text);
}
.dc-colo-card__chunk strong {
    color: var(--cp-text-heading);
    font-weight: 600;
}

/* Card footer — thin top divider + the CTA button. Makes the card
   feel "finished" with a proper bottom-anchor instead of a paragraph
   just trailing off into the button. */
.dc-colo-card__footer {
    margin-top: 22px;
    padding-top: 20px;
    border-top: 1px solid var(--cp-border);
}
.dc-colo-card__footer .btn i {
    margin-left: 8px;
    transition: transform 0.2s ease;
}
.dc-colo-card__footer .btn:hover i {
    transform: translateX(3px);
}

@media (max-width: 767px) {
    .dc-colo-card {
        padding: 24px 22px 22px;
    }
    .dc-colo-card__facts {
        padding: 12px 14px;
        gap: 6px 14px;
    }
    .dc-colo-card__fact {
        font-size: 0.82rem;
    }
}
/* Title + meta — match the photo-footer __title/__subtitle exactly
   so both module footers speak the same typographic rhythm. Two
   lines (address + hours). The old .dc-address-card__line and
   __hours / __body / __icon classes are retained below for any
   other page that might still use the standalone-card variant. */
.dc-address-card__title {
    font-family: var(--font-heading);
    font-size: 0.98rem;
    font-weight: 600;
    color: var(--cp-text-heading);
    line-height: 1.3;
}
.dc-address-card__meta {
    margin-top: 3px;
    font-size: 0.82rem;
    color: var(--cp-text-muted);
    letter-spacing: 0.02em;
}

/* Legacy — retained for any non-module standalone usage. */
.dc-address-card__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex: 0 0 34px;
    border-radius: 50%;
    background: rgba(222, 53, 128, 0.08);
    color: var(--cp-pink);
    font-size: 0.95rem;
}
.dc-address-card__body { min-width: 0; }
.dc-address-card__line {
    font-family: var(--font-heading);
    font-size: 0.98rem;
    color: var(--cp-text-heading);
    line-height: 1.4;
}
.dc-address-card__hours {
    margin-top: 4px;
    font-size: 0.85rem;
    color: var(--cp-text-muted);
    letter-spacing: 0.02em;
}

/* Photo module — the right-column sibling of .dc-map-module.
   Matches the map module's outer frame treatment (same radius,
   border, shadow, background) so the two sides of the facility row
   read as a matched pair. Photo on top + integrated footer strip
   below, mirroring map + address-card. */
.dc-photo-module {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 320px;
    border-radius: 12px;
    overflow: hidden;
    border: 1px solid var(--cp-border);
    box-shadow: 0 14px 38px rgba(26, 34, 51, 0.14);
    background: #ffffff;
}

/* Photo frame — now just the image pane inside .dc-photo-module.
   Frame chrome moved to the module above; this is flush on top. */
.dc-photo-frame {
    position: relative;
    display: block;
    width: 100%;
    flex: 1 1 auto;
    min-height: 240px;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    background: var(--cp-bg-alt);
    cursor: zoom-in;
}
.dc-photo-frame > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.45s ease;
}
.dc-photo-frame:hover > img { transform: scale(1.02); }
.dc-photo-frame__zoom {
    position: absolute;
    top: 14px;
    right: 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(15, 24, 38, 0.7);
    backdrop-filter: blur(4px);
    color: #ffffff;
    font-size: 0.9rem;
    opacity: 0;
    transform: translateY(-4px);
    transition: opacity 0.2s ease, transform 0.2s ease;
    pointer-events: none;
}
.dc-photo-frame:hover .dc-photo-frame__zoom,
.dc-photo-frame:focus-visible .dc-photo-frame__zoom {
    opacity: 1;
    transform: translateY(0);
}
/* Photo footer — sibling of the address card on the map side.
   Matches its layout AND its exact vertical metric (min-height 86px,
   tinted bg, top border divider) so both bottoms are the same bar.
   Houses facility title + subtitle on the left and an external link
   action on the right. */
.dc-photo-module .dc-photo-footer {
    display: flex;
    align-items: stretch;
    flex: 0 0 auto;
    padding: 0;
    min-height: 86px;
    background: rgba(26, 34, 51, 0.025);
    border-top: 1px solid var(--cp-border);
}
.dc-photo-footer__info {
    display: flex;
    flex-direction: column;
    justify-content: center;
    flex: 1 1 auto;
    min-width: 0;
    padding: 14px 20px;
}
.dc-photo-footer__title {
    font-family: var(--font-heading);
    font-size: 0.98rem;
    font-weight: 600;
    color: var(--cp-text-heading);
    line-height: 1.3;
}
.dc-photo-footer__subtitle {
    margin-top: 3px;
    font-size: 0.82rem;
    color: var(--cp-text-muted);
    letter-spacing: 0.02em;
}

/* Photo footer action (right side) — solid blue CTA linking to the
   partner's own page. Same 120px fixed width as the pink Directions
   button on the map side, so the two footer rows mirror each other
   exactly — distinct colors for distinct actions (pink = our
   navigation action; blue = partner external link). Blue was picked
   from the slate-gradient family so it lives in the same visual
   neighborhood as the rest of the site without competing with the
   pink brand. */
.dc-photo-footer__action {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex: 0 0 auto;
    width: 120px;
    padding: 0;
    background: #336699;
    color: #ffffff;
    font-family: var(--font-heading);
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-decoration: none;
    border-left: 1px solid var(--cp-border);
    transition: background-color 0.15s ease;
}
.dc-photo-footer__action i.fa-arrow-up-right-from-square {
    font-size: 0.62rem;
    opacity: 0.85;
}
.dc-photo-footer__action:hover,
.dc-photo-footer__action:focus-visible {
    background: #29527a;
    color: #ffffff;
    text-decoration: none;
}

/* Photo hover lift — now on the module (not the frame) since the
   module carries the shadow. Only fires when the module actually
   contains a real photo (i.e. a .dc-photo-frame that is NOT the
   .--logo variant). On the WOW side where the module holds only a
   static logo, hovering shouldn't suggest interactivity. */
.dc-photo-module:has(.dc-photo-frame:not(.dc-photo-frame--logo)):hover {
    box-shadow: 0 20px 48px rgba(26, 34, 51, 0.2);
}

/* Logo variant — used on the WOW! section where no exterior photo
   exists on the legacy source. Plain white background (no gradient)
   so the logo reads as a clean brand mark on a neutral surface
   rather than a stylized placeholder. The logo's own drop-shadow
   (on .dc-photo-frame__logo-img) gives it enough lift against the
   white plane without needing decorative bg treatment. */
.dc-photo-frame--logo {
    cursor: default;
    background: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 36px;
}
/* No :hover rule — the logo frame should be visually static. The
   older rule here painted a box-shadow on hover (a leftover from
   when the frame carried its own chrome) which read as an
   unwelcome lift on a non-interactive element. */
.dc-photo-frame__logo-inner {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    max-width: 80%;
}
.dc-photo-frame__logo-img {
    display: block;
    max-width: 100%;
    max-height: 160px;
    width: auto;
    height: auto;
}
.dc-photo-frame__logo-tag {
    font-family: var(--font-heading);
    font-size: 0.82rem;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--cp-text-muted);
}

/* Stack split grid on ≤991px — map above the photo on tablet/phone. */
@media (max-width: 991px) {
    .dc-facility-grid {
        grid-template-columns: 1fr;
        gap: 24px;
    }
    .dc-photo-frame {
        aspect-ratio: 16 / 10;
        min-height: 260px;
    }
}
@media (max-width: 560px) {
    .dc-map-frame { min-height: 260px; }
    .dc-photo-frame { min-height: 220px; }
}

/* Facility narrative — base prose styling. Width-constrained for
   comfortable line measure. When sitting standalone on the page it
   carries no surface; when inside .dc-facility-module it becomes an
   integrated continuation (see override below). */
.dc-prose {
    max-width: 820px;
    margin: 0 0 48px;
}
.dc-prose p {
    font-size: 1.02rem;
    line-height: 1.7;
    color: var(--cp-text);
    margin-bottom: 14px;
}
.dc-prose p:last-child { margin-bottom: 0; }

/* =============================================================
   .dc-facility-module — unified surfaced case study panel.
   Holds the facility header stack + media row + narrative prose
   as ONE continuous composition. The shared surface makes the
   reader perceive a single case study instead of three stacked
   blocks. Feature cards live outside this wrapper as separate
   "supporting details". Scoped to the data-centers page via
   .dc-page-section so no other page inherits it accidentally.
   ============================================================= */
.dc-page-section .dc-facility-module {
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r);
    box-shadow: 0 8px 34px rgba(26, 34, 51, 0.07);
    padding: 44px 48px 40px;
    margin-bottom: 56px;
}

/* Header stack inside the module — tight vertical rhythm so
   eyebrow pill + partner row + h2 + lead read as one composed
   intro. Small margin-bottom hands off cleanly to the media row. */
.dc-page-section .dc-facility-module__header {
    margin-bottom: 28px;
}

/* Media row inside the module — tuck closer to the prose below.
   Was 44px bottom margin; inside the module it becomes 24px so the
   prose reads as a continuation, not as a separate third block. */
.dc-page-section .dc-facility-module .dc-facility-grid {
    margin-bottom: 24px;
}

/* Prose inside the module — strip the standalone card treatment.
   No border, no shadow, no own background, no pink-left bar (the
   module's surface already provides the dimensional frame). Spans
   the module's full width so it aligns with the media row above.
   The subtle top divider is the only internal boundary — a thin
   tint that signals "new section" within the module without
   reasserting a card feel. */
.dc-page-section .dc-facility-module .dc-prose {
    max-width: none;
    margin: 0;
    padding: 20px 0 0;
    background: transparent;
    border: 0;
    border-top: 1px solid var(--cp-border);
    border-radius: 0;
    box-shadow: none;
}

/* Responsive: tighter padding on the module at mobile so it doesn't
   dominate the viewport. Radius drops slightly so the card feels
   appropriately sized for the smaller surface. */
@media (max-width: 767px) {
    .dc-page-section .dc-facility-module {
        padding: 28px 22px 28px;
        margin-bottom: 40px;
        border-radius: var(--cp-r-sm);
    }
    .dc-page-section .dc-facility-module__header {
        margin-bottom: 22px;
    }
    .dc-page-section .dc-facility-module .dc-facility-grid {
        margin-bottom: 22px;
    }
    .dc-page-section .dc-facility-module .dc-prose {
        padding-top: 22px;
    }
}
.dc-prose strong {
    color: var(--cp-text-heading);
    font-weight: 600;
}

/* ---- Feature grid ---- */
.dc-feature-grid {
    margin-top: 12px;
    max-width: none;
}
/* Three-column variant of `.platform-details__grid` (was 2-col by default).
   The six Cologix feature cards read as a proper 3x2 grid on desktop,
   collapse to 2-col on tablet, then 1-col at ≤767px — matching the
   base .platform-details__grid breakpoint so WOW and Cologly stack
   at the same viewport width. Before, the single-col breakpoint was
   560, which left 561-767 showing a cramped 2-col on phones while
   WOW had already gone single-col. */
.platform-details__grid--three {
    grid-template-columns: repeat(3, 1fr);
    max-width: none;
}
@media (max-width: 991px) {
    .platform-details__grid--three { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 767px) {
    .platform-details__grid--three { grid-template-columns: 1fr; }
}

/* ---- Editorial divider band (single dark stripe on the page) ---- */
.dc-divider { padding: 80px 0; }
.dc-divider .platform-principle__inner { max-width: 820px; }
.dc-divider h2 { font-size: clamp(1.8rem, 3vw, 2.6rem); }

/* ---- Colocation section ---- */
/* Was 2-col grid (text | highlights aside). Now follows the same
   text-on-top + grid-below rhythm as Cologix/WOW feature grids —
   text block surfaced (see .dc-page-section--colo .dc-colo-text
   further up in the file) then highlights as a naked 3-col grid
   sitting directly on the section bg. */
.dc-colo-text p {
    font-size: 1.05rem;
    line-height: 1.75;
    color: var(--cp-text);
    margin-bottom: 16px;
}
.dc-colo-text p:last-child { margin-bottom: 0; }
.dc-colo-text strong { color: var(--cp-text-heading); font-weight: 600; }
.dc-colo-text__cta {
    margin-top: 28px;
}
.dc-colo-text__cta .btn i { margin-left: 10px; transition: transform 0.2s ease; }
.dc-colo-text__cta .btn:hover i { transform: translateX(3px); }

/* Compact highlights grid — right column of the colocation layout.
   2-col at desktop (fits 6 cards in 3 rows alongside the
   Deployment Fit card). Tighter padding + smaller icon so the grid
   reads as "supporting proof chips" not full feature cards. */
.dc-colo-highlights {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
}
.dc-colo-highlight {
    display: flex;
    flex-direction: column;
    padding: 16px 14px;
    min-height: 140px;
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r-sm);
    transition: border-color 0.2s ease, transform 0.2s ease,
                box-shadow 0.2s ease;
}
.dc-colo-highlight:hover {
    border-color: rgba(222, 53, 128, 0.25);
    transform: translateY(-2px);
    box-shadow: 0 6px 18px rgba(26, 34, 51, 0.06);
}
.dc-colo-highlight__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    margin-bottom: 8px;
    border-radius: 8px;
    background: rgba(222, 53, 128, 0.1);
    color: var(--cp-pink);
    font-size: 0.88rem;
}
.dc-colo-highlight__label {
    font-family: var(--font-heading);
    font-size: 0.88rem;
    font-weight: 700;
    color: var(--cp-text-heading);
    margin-bottom: 4px;
    line-height: 1.25;
}
.dc-colo-highlight__body {
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--cp-text-muted);
}
/* Full-width layout stacks on ≤991px — the 2-col tight grid then
   expands to 3-col for balance, then drops to 1-col on phones. */
@media (max-width: 991px) {
    .dc-colo-highlights {
        grid-template-columns: repeat(3, 1fr);
        margin-top: 8px;
    }
}
@media (max-width: 640px) {
    .dc-colo-highlights { grid-template-columns: 1fr; }
}

/* ==========================================================================
   =========== platform-architecture page ===========
   --------------------------------------------------------------------------
   Styles specific to /platform-architecture. Builds on the existing
   .about-section, .platform-details, .platform-spec-card, .section-lead,
   and .page-cta primitives — layering a subsection-eyebrow + lead-paragraph
   pattern on top (.arch-section*) and a full bespoke comparison table
   (.hw-compare) that is the hero element of the page.
   ========================================================================== */

/* ==========================================================================
   .arch-section — unified section component for /network-architecture
   --------------------------------------------------------------------------
   Both Section 01 (Layer 3 Core) and Section 02 (Switching Fabric) share
   ONE base component — `.arch-section` — and differ only by theme
   modifier: `--edge` (dark footer-tone) vs `--tor` (light). Previously
   each section sat on a different base (`.platform-principle` vs
   `.about-section`), which forced us to fight inherited body-copy rules
   with !important and compound-class specificity hacks. Owning our own
   base removes that class of bug entirely.

   Structure:
     section.arch-section.arch-section--split.arch-section--(edge|tor)
       .container
         .arch-section__split
           .arch-section__text
             .arch-section__meta  (__num + __label)
             .arch-section__eyebrow
             h2
             .arch-section__lead
             p, p, p...
           .arch-section__visual
             .arch-visual-stack
               .arch-diagram           (inline SVG)
               figure.arch-photo-card  (optional real-hardware photo)
         .arch-spec-grid  (shared spec-card grid, 48px gap from split)
   ========================================================================== */

.arch-section {
    padding: 96px 0;
    position: relative;
    overflow: hidden;
    z-index: 1;
}

/* ---------- Theme: dark (--edge) ---------- */
/* Bottom padding tightened to 48px (vs. the 96px base) so the peer
   marquee — which lives as the last element in this section — sits
   close to the bottom edge of the dark surface instead of floating
   in a large void below it. Top padding keeps the default. */
.arch-section--edge {
    background: var(--cp-bg-footer);
    color: rgba(255, 255, 255, 0.88);
    padding-bottom: 48px;
}
.arch-section--edge::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse at 20% 40%, rgba(222, 53, 128, 0.08) 0%, transparent 55%),
        radial-gradient(ellipse at 80% 60%, rgba(122, 157, 190, 0.06) 0%, transparent 55%);
    pointer-events: none;
    z-index: -1;
}
.arch-section--edge h2 { color: #ffffff; }
.arch-section--edge .arch-section__eyebrow,
.arch-section--edge .arch-section__label { color: var(--cp-pink-light); }
.arch-section--edge .arch-section__lead { color: #ffffff; }
/* Body p excludes the lead so the lead's pure white wins over the
   body's 78% — without :not(), the body-p rule (specificity 0,2,1)
   outweighs the lead rule (0,2,0) and the lead would render as the
   gray body color even with its dedicated color rule above. */
.arch-section--edge .arch-section__text p:not(.arch-section__lead) { color: rgba(255, 255, 255, 0.78); }
.arch-section--edge .arch-section__text p strong { color: #ffffff; font-weight: 700; }

/* ---------- Theme: light (--tor) ---------- */
/* Inherits site bg (white); only text colors shift. */
.arch-section--tor { color: var(--cp-text); }
.arch-section--tor h2 { color: var(--cp-text-heading); }
.arch-section--tor .arch-section__eyebrow { color: var(--cp-pink); }
.arch-section--tor .arch-section__lead { color: var(--cp-text-heading); }
.arch-section--tor .arch-section__text p { color: var(--cp-text); }
.arch-section--tor .arch-section__text p strong { color: var(--cp-text-heading); font-weight: 700; }

/* ---------- Theme: panel (--panel) ---------- */
/* Light-gray editorial breakout band — used for hardware spotlights
   between narrative dark/light sections. The dark section holds
   architecture (topology, uplinks, routing/security); this --panel
   band holds physical hardware proof, letting those two content
   types live in visually distinct zones. Same split-layout recipe
   as the narrative variants but on --cp-bg-alt instead of the dark
   footer tone. Generous vertical padding (96px) so it reads as
   intentional editorial space, not a thin spacer. */
.arch-section--panel {
    background: var(--cp-bg-alt);
    color: var(--cp-text);
    padding: 96px 0;
}
/* Zero the split's bottom margin — .arch-section--panel has no
   spec-grid beneath to absorb the default 48px. Compound-class
   specificity (0,3,0) so we win regardless of source order vs.
   the base `.arch-section--split .arch-section__split` rule. */
.arch-section--panel.arch-section--split .arch-section__split { margin-bottom: 0; }
.arch-section--panel h2 { color: var(--cp-text-heading); }
.arch-section--panel .arch-section__eyebrow { color: var(--cp-pink); }
.arch-section--panel .arch-section__lead { color: var(--cp-text-heading); }
.arch-section--panel .arch-section__text p { color: var(--cp-text); }
.arch-section--panel .arch-section__text p strong { color: var(--cp-text-heading); font-weight: 700; }
/* Architecture-visual caption is hardcoded to white-on-dark upstream
   (.architecture-visual__caption at ~L2464 — tuned for MCC's dark
   .platform-principle). Re-theme it inside our gray panel so it
   reads against the light surface. */
.arch-section--panel .architecture-visual__caption { color: var(--cp-text-muted); }
.arch-section--panel .architecture-visual__caption-detail { color: rgba(26, 34, 51, 0.5); }

/* ---------- Shared subcomponents ---------- */
.arch-section__meta {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
}
.arch-section__num {
    font-family: var(--font-heading);
    font-size: 0.85rem;
    font-weight: 800;
    letter-spacing: 0.1em;
    color: var(--cp-pink);
    padding: 4px 10px;
    border: 1px solid rgba(222, 53, 128, 0.3);
    border-radius: 4px;
}
.arch-section__label {
    font-family: var(--font-heading);
    font-size: 0.85rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    color: var(--cp-pink);
    text-transform: uppercase;
}
.arch-section__eyebrow {
    display: inline-block;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--cp-pink);
    margin: 4px 0 14px;
}
.arch-section__lead {
    font-family: var(--font-heading);
    /* 1.3rem matches /index.php's .platform-principle__lead so the
       lead callout reads with the same prominence on both pages. */
    font-size: 1.3rem;
    font-weight: 600;
    line-height: 1.4;
    margin: 0 0 1.15rem;
}

/* Body-copy rhythm — explicit p + p spacing so the text column reads
   as discrete paragraphs, not one merged block. No !important needed
   here since .arch-section owns these selectors outright (no upstream
   .platform-principle collapse rule to fight). */
.arch-section__text { min-width: 0; }
/* :not(.arch-section__lead) so the lead's 1.3rem / 1.4 line-height
   from .arch-section__lead wins over this body-p rule. Without it,
   the body rule's specificity (0,1,1) outweighs the lead's (0,1,0)
   and the lead renders at body size. */
.arch-section__text p:not(.arch-section__lead) {
    font-size: 1.05rem;
    line-height: 1.7;
    margin: 0;
}
.arch-section__text p:not(.arch-section__lead) + p:not(.arch-section__lead) { margin-top: 1.05rem; }
/* When the lead sits BETWEEN body paragraphs (used as a mid-section
   pull-quote rather than the section's opening sentence — e.g.
   /platform-architecture Section 01's "Proxmox VE emerged as the
   clear winner..." callout), give it breathing room above so it
   visually separates from the prose that comes before. Match the
   lead's own bottom margin (1.15rem) so the callout sits in
   symmetric whitespace — uneven top/bottom reads as misaligned.
   Adjacent-sibling combinator scopes the rule to "lead follows a
   p" cases only — when the lead is the first body element
   (preceded by h2, eyebrow, or .arch-section__meta), no top
   margin is added. */
.arch-section__text p + .arch-section__lead { margin-top: 1.15rem; }

/* Links inside arch-section paragraphs: <strong> inside an <a> must
   inherit the link color, not get re-coloured by the theme rules
   (`.arch-section--edge/tor/panel .arch-section__text p strong`)
   which sit at (0,3,1) and would otherwise make the link read as
   plain body text. Explicit (0,3,2) selectors beat those. Same fix
   applied to the spec-card list so linked card items stay visible. */
.arch-section--edge .arch-section__text p a strong,
.arch-section--tor .arch-section__text p a strong,
.arch-section--panel .arch-section__text p a strong,
.platform-spec-card--v1 ul li a strong { color: inherit; }

/* Non-split intro wrapper — for .arch-section variants that don't
   need a text/visual split (e.g. /network-architecture Section 02
   which reads as centered prose + cards + inset, no diagram). Matches
   the .category-intro rhythm so cross-page layouts feel consistent.
   The meta row (01/02/...) gets centered too via justify-content. */
.arch-section__intro {
    max-width: 780px;
    margin: 0 auto 48px;
    text-align: center;
}
.arch-section__intro .arch-section__meta { justify-content: center; }
.arch-section__intro .arch-section__eyebrow { margin: 4px auto 14px; }
.arch-section__intro p + p { margin-top: 1.05rem; }

/* Magazine-article variant of .arch-section — single-column body
   with a floated diagram (treated like a magazine photo). Title +
   meta + h2 sit full-width across the top; the diagram floats right
   immediately after the h2; body paragraphs wrap around it. Once the
   prose passes the diagram's bottom edge, the remaining text flows
   full-width across the column. Used on /platform-architecture's
   Section 01 (Hypervisor) where the prose is 5+ paragraphs and the
   prior --split layout left too much vertical dead space next to
   the diagram. */
.arch-section--article .arch-section__text {
    /* Match .arch-section--split .arch-section__split's behavior
       exactly: fill the parent .container's content area with no
       width constraint and no auto-margins. We override the global
       `.arch-section__text { max-width: 470px }` rule (defined for
       split layouts at >=992px in line 6825) by explicitly setting
       max-width: none here. width: 100% + margin: 0 + max-width:
       none is the same shape as a CSS-Grid container with no inner
       cap — which is what /network-architecture's arch-section__split
       resolves to. Both wrappers now produce identical viewport-edge
       gutters at every breakpoint. */
    width: 100%;
    max-width: none;
    margin: 0;
    min-width: 0;
}
.arch-section--article .arch-section__text::after {
    content: "";
    display: block;
    clear: both;
}
/* Diagram carousel — used to slide between platform variants of a
   diagram (e.g. /platform-architecture's MCC Gen 4 vs GPC Gen 3 host
   layouts). Two-or-more slides + dot navigation below. JS in site.js
   handles dot-click → slide-swap. CSS handles the show/hide. */
.diagram-carousel { position: relative; width: 100%; }
.diagram-carousel__slides { position: relative; }
.diagram-carousel__slide { display: none; }
.diagram-carousel__slide.is-active {
    display: block;
    animation: dc-fadeIn 0.22s ease;
}
@keyframes dc-fadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}
/* Tab-style nav for the diagram carousel — two-or-more text+outline
   buttons under the diagram that toggle between slides. Active tab
   shows CP pink text + pink outline (matches the hover state of
   ghost buttons elsewhere). Inactive tabs are muted gray and adopt
   the pink treatment on hover. Replaces the older dots + pill
   caption pattern (cleaner: the button label IS the caption). */
.diagram-carousel__tabs {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-top: 18px;
    flex-wrap: wrap;
}
.diagram-carousel__tab {
    background: transparent;
    color: var(--cp-text-muted);
    border: 1px solid rgba(26, 34, 51, 0.22);
    font-family: var(--font-heading);
    font-size: 0.82rem;
    font-weight: 600;
    padding: 7px 16px;
    border-radius: 6px;
    cursor: pointer;
    transition: color 0.18s, border-color 0.18s;
    line-height: 1.2;
}
.diagram-carousel__tab:hover,
.diagram-carousel__tab.is-active {
    color: var(--cp-pink);
    border-color: var(--cp-pink);
}
.diagram-carousel__tab:focus-visible {
    outline: 2px solid var(--cp-pink);
    outline-offset: 3px;
}
/* Dark-theme variant — when the carousel sits inside an --edge
   section, the gray border is too dark to see on dark navy bg. */
.arch-section--edge .diagram-carousel__tab {
    color: rgba(255, 255, 255, 0.65);
    border-color: rgba(255, 255, 255, 0.28);
}
.arch-section--edge .diagram-carousel__tab:hover,
.arch-section--edge .diagram-carousel__tab.is-active {
    color: var(--cp-pink-light);
    border-color: var(--cp-pink-light);
}
/* Float-right modifier — same pattern as .arch-diagram--float-right
   but applied at the whole-carousel level so dots + caption float
   together as one unit. Used in --article-layout sections where the
   carousel sits as a magazine "photo" on the right. */
.diagram-carousel--float-right {
    float: right;
    width: 48%;
    max-width: 520px;
    /* Top margin pushes the carousel down to align with the start of
       the H2 — same alignment as Section 01's .arch-diagram--float-right.
       Reset to 0 in the stacked layout below. */
    margin: 96px 0 24px 32px;
}

/* Float-right modifier for .arch-diagram. max-width 520px matches
   the base .arch-diagram cap so the diagram can render at its full
   native size when room allows; width 48% means on a 1100px article
   column the diagram lands at ~520px (its cap) and wrap-around prose
   has ~550px beside it. */
.arch-diagram--float-right {
    float: right;
    width: 48%;
    max-width: 520px;
    /* Top margin pushes the diagram down to align with the start of
       the title text (page H2), not the very top of the section
       container. The magazine effect we want is for the diagram and
       the H2 to begin at the same horizontal line. Reset in stacked
       layout below. */
    margin: 96px 0 24px 32px;
}

/* Stacked-mode rules — 992 → 991 breakpoint matches the site's
   "narrow desktop / tablet landscape" boundary. Below 992 we stop
   the float, drop the magazine padding-top, and reorder the article
   so the diagram appears in a logical place per section.
     Section 01 (.arch-diagram--float-right): pinned right after the
       meta line ("01 / Hypervisor Foundation") so the Cloud Propeller
       Stack reads as a quick visual anchor before the long article.
     Section 02 (.diagram-carousel--float-right): after the lead/
       subtitle, since the host architecture story benefits from the
       intro framing before the diagram makes sense.
   Flex ordering:
     1 = meta, 2 = arch-diagram (sec 01), 3 = eyebrow, 4 = h2,
     5 = lead, 6 = carousel (sec 02), 7 = body paragraphs. */
@media (max-width: 991px) {
    .arch-section--article .arch-section__text {
        display: flex;
        flex-direction: column;
    }
    .arch-section--article .arch-section__text > .arch-section__meta             { order: 1; }
    .arch-section--article .arch-section__text > .arch-diagram--float-right      { order: 2; }
    .arch-section--article .arch-section__text > .arch-section__eyebrow          { order: 3; }
    .arch-section--article .arch-section__text > h2                              { order: 4; }
    .arch-section--article .arch-section__text > .arch-section__lead             { order: 5; }
    .arch-section--article .arch-section__text > .diagram-carousel--float-right  { order: 6; }
    .arch-section--article .arch-section__text > p:not(.arch-section__lead)      { order: 7; }

    /* Section 01 (Hypervisor Foundation) override — instead of the
       diagram appearing right after the meta line on mobile, slot it
       AFTER the third body <p> ("Proxmox VE emerged as the clear
       winner..."). The reading order then flows: meta → eyebrow →
       h2 → lead → P2 ("In mid-2024...") → P3 ("Proxmox VE
       emerged...") → DIAGRAM → P4 → P5. Mirrors the same "diagram
       after the framing paragraphs" treatment we use on
       /network-architecture's Architecture Overview.
       Body paragraphs split into two buckets via :nth-of-type:
         - p:nth-of-type(1)         is the .arch-section__lead (order 5)
         - p:nth-of-type(2 and 3)   = the framing paragraphs before the diagram (order 6-7)
         - .arch-diagram--float-right                                   (order 8)
         - p:nth-of-type(n+4)       = follow-up paragraphs after diagram (order 9). */
    .arch-section--article.arch-section--edge .arch-section__text > .arch-diagram--float-right { order: 8; }
    /* Mobile reading order on Section 01 (Hypervisor Foundation):
       eyebrow → h2 → p1 (merged intro: "For Cloud first nine years...
       mid-2024... twelve-month evaluation") → p2 LEAD CALLOUT
       ("Proxmox VE emerged as the clear winner...") → DIAGRAM → p3
       ("Cloud Propeller has always prioritized...") → p4
       ("per-socket licensing") → p5 ("cost benefit").
       p1 gets order 5 explicitly so it renders BEFORE the lead p2
       (which inherits order 5 from the generic .arch-section__lead
       rule and tiebreaks behind p1 by DOM order); diagram at 8
       slots between the lead callout and p3; p3-p5 push past via
       order 9. */
    .arch-section--article.arch-section--edge .arch-section__text > p:nth-of-type(1)            { order: 5; }
    .arch-section--article.arch-section--edge .arch-section__text > p:nth-of-type(n+3)          { order: 9; }

    .arch-diagram--float-right,
    .diagram-carousel--float-right {
        float: none;
        width: 100%;
        max-width: 520px;
        /* Bottom margin trimmed so the visual gap below the diagram
           matches the gap above. The next paragraph already brings
           ~17px from the .arch-section__text `p + p` rule (DOM-based,
           still fires when the diagram is reordered between paragraphs
           via flex order), so 8px on the diagram + 17px from the p
           = ~25px below, matching ~24px above. Was 32px which doubled
           the bottom gap. */
        margin: 24px auto 8px;
        align-self: center;
    }
}

/* Per-diagram desktop top-padding tweaks for /platform-architecture.
   The Cloud Propeller Stack and the MCC/GPC host-connectivity carousel
   each need a touch more breathing room above their SVG content so
   the diagrams' first elements line up nicely beside the prose H2.
   Mobile (<992px) inherits the stacked-mode reset above and keeps the
   diagrams flush with their wrapper's top, so these rules are
   intentionally desktop-only. */
@media (min-width: 992px) {
    /* Cloud Propeller Stack diagram (Section 01 — Hypervisor
       Foundation). Pushes the SVG content down 60px inside its
       float-right wrapper. */
    .arch-diagram--dark {
        padding-top: 60px;
    }
    /* MCC + GPC host connectivity carousel slides (Section 02 —
       Host Architecture). 10px nudge applied to BOTH slides so
       switching between them stays visually stable. */
    .diagram-carousel .arch-diagram--light {
        padding-top: 10px;
    }
}

/* Wider editorial "note" callout — sits BELOW an .arch-section__split
   (or after the split's prose) when there's a narrative aside that
   shouldn't be a card. Lives at 920px max-width (wider than the
   780px body or 860px inset card) so it visually breaks the split's
   text-column rhythm and reads as a distinct addendum.
   Theme-aware. On --edge sections (e.g. /platform-architecture's
   Section 01 Hypervisor), the left accent shifts to Proxmox-orange
   so the note ties to the orange Proxmox VE 9 box in the diagram. */
.arch-section__note {
    max-width: 920px;
    margin: 56px auto 40px;
    padding: 22px 28px 22px 32px;
    border-left: 3px solid var(--cp-pink);
}
.arch-section__note-label {
    display: block;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.82rem;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    margin: 0 0 12px;
    color: var(--cp-pink);
}
.arch-section__note p {
    font-size: 1.05rem;
    line-height: 1.7;
    margin: 0;
}
.arch-section__note p + p { margin-top: 1.05rem; }
/* Theme-aware text colors */
.arch-section--edge .arch-section__note p { color: rgba(255, 255, 255, 0.82); }
.arch-section--edge .arch-section__note p strong { color: #ffffff; font-weight: 700; }
.arch-section--tor .arch-section__note p { color: var(--cp-text); }
.arch-section--tor .arch-section__note p strong { color: var(--cp-text-heading); font-weight: 700; }
.arch-section--panel .arch-section__note p { color: var(--cp-text); }
.arch-section--panel .arch-section__note p strong { color: var(--cp-text-heading); font-weight: 700; }
/* Links inside note paragraphs: <strong> nested in <a> must keep
   the link color, mirroring the same rule for .arch-section__text. */
.arch-section--edge .arch-section__note p a strong,
.arch-section--tor .arch-section__note p a strong,
.arch-section--panel .arch-section__note p a strong { color: inherit; }

/* Body-prose wrapper for non-split arch-sections that need narrative
   paragraphs BETWEEN the intro and the cards/inset (e.g.
   /platform-architecture's Storage section and 50% Manifesto).
   Centered horizontally to match the 780px reading column, but text
   left-aligned so multi-line body copy doesn't read as ragged poetry.
   margin-bottom feeds default spacing to whatever follows (inset card,
   spec grid). */
.arch-section__body {
    max-width: 780px;
    margin: 0 auto 40px;
    text-align: left;
}
.arch-section__body p {
    font-size: 1.05rem;
    line-height: 1.7;
    margin: 0;
}
.arch-section__body p + p { margin-top: 1.05rem; }
/* Theme-aware body color: --edge inherits the dark-section text rule
   from .arch-section--edge .arch-section__text p; --tor and --panel
   inherit their own. Mirror those one-liner overrides here so body
   copy in the new wrapper picks up the right palette. */
.arch-section--edge .arch-section__body p { color: rgba(255, 255, 255, 0.78); }
.arch-section--edge .arch-section__body p strong { color: #ffffff; font-weight: 700; }
.arch-section--tor .arch-section__body p { color: var(--cp-text); }
.arch-section--tor .arch-section__body p strong { color: var(--cp-text-heading); font-weight: 700; }
.arch-section--panel .arch-section__body p { color: var(--cp-text); }
.arch-section--panel .arch-section__body p strong { color: var(--cp-text-heading); font-weight: 700; }
/* Links inside body paragraphs: <strong> nested in <a> must keep the
   link color, mirroring the same rule for .arch-section__text. */
.arch-section--edge .arch-section__body p a strong,
.arch-section--tor .arch-section__body p a strong,
.arch-section--panel .arch-section__body p a strong { color: inherit; }

/* Intro-section CTA row (Network Architecture / Data Centers buttons
   directly under the lead paragraph on /platform-architecture). The
   .category-intro__inner is text-align: center, but the .cta-row needs
   explicit flex centering + gap because .btn elements are display:
   inline-block by default and only the centering happens via inline-
   block alignment. Mirrors the .section-lead .cta-row recipe so the
   visual rhythm is consistent across the site's "intro band + jump
   buttons" pattern. */
.category-intro .cta-row {
    display: flex;
    gap: 16px;
    justify-content: center;
    flex-wrap: wrap;
    margin-top: 24px;
}
/* .btn-ghost is hard-coded white text + white-on-translucent border
   for use on dark hero/section backgrounds. On .category-intro's
   white surface that reads as invisible text on an invisible border.
   Re-color the variant in this context to dark text + dark-translucent
   border, with pink hover. Scoped narrowly so the dark-section usage
   elsewhere (hero, .arch-section--edge, manifesto) is unaffected. */
.category-intro .btn-ghost {
    color: var(--cp-text-heading);
    border-color: rgba(26, 34, 51, 0.32);
}
.category-intro .btn-ghost:hover,
.category-intro .btn-ghost:focus {
    color: var(--cp-pink);
    border-color: var(--cp-pink);
}

/* Split layout (shared by both themes). Default columns tuned for the
   diagram+photo-stack visual column — narrower text, wider visual.
   margin-bottom: 48px feeds the default gap to whatever sits under
   the split (cards grid, inset, inline callout). Zeroed via the
   :last-child rule below when the split IS the last element in its
   container — the section's own padding-bottom handles that case. */
.arch-section--split .arch-section__split {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: 48px;
    align-items: center;
    margin-bottom: 48px;
}
.arch-section--split .arch-section__split:last-child { margin-bottom: 0; }
.arch-section__visual {
    min-width: 0;
    position: relative;
}
@media (min-width: 992px) {
    .arch-section--split .arch-section__split {
        grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.25fr);
        gap: 64px;
    }
    .arch-section__text { max-width: 470px; }
    /* When a split section has an .arch-section__aside slot (e.g.
       Architecture Overview's upstream-carriers strip), use named
       grid areas so the aside sits in the LEFT column below the
       text, while the visual spans BOTH rows on the right.
       On mobile (single col), DOM order takes care of itself:
       text → visual → aside, putting the diagram between the
       paragraphs above and the carrier strip below. */
    .arch-section--split .arch-section__split:has(.arch-section__aside) {
        grid-template-areas:
            "text   visual"
            "aside  visual";
        align-items: start;
        /* Zero row-gap so the aside sits right under the text — its
           own .upstream-strip { margin-top: 28px } handles the
           breathing room. The default 64px gap was applying as BOTH
           column-gap and row-gap, putting 64+28=92px between P2 and
           the carrier strip on desktop. Column-gap stays 64px for
           text↔visual separation. */
        column-gap: 64px;
        row-gap: 0;
    }
    .arch-section--split .arch-section__split:has(.arch-section__aside) > .arch-section__text   { grid-area: text; }
    .arch-section--split .arch-section__split:has(.arch-section__aside) > .arch-section__visual { grid-area: visual; align-self: start; padding-top: 100px; }
    /* Same offset for the Rack-Level Switching Fabric diagram in
       the Arista — Top of Rack section: top-align + 90px padding
       so the diagram sits beside the h2 title, not floating
       centered relative to the full text column.
       :has(.arch-diagram) targets the SVG-diagram split sections
       only — leaves the .arch-section--panel hardware-photo splits
       (Layer 3 Core Hardware, Layer 2 Fabric) center-aligned as
       before. */
    .arch-section--split:not(:has(.arch-section__aside)) > .container > .arch-section__split > .arch-section__visual:has(.arch-diagram) {
        align-self: start;
        padding-top: 100px;
    }
    /* Top-align the WHOLE row when the visual is offset 100px down
       (Rack-Level Switching Fabric in --tor section). Without this,
       the parent grid's default `align-items: center` centers the
       text in a row whose height has been stretched by the visual
       + 100px padding — so the eyebrow appears ~100px lower than
       the section's top padding intends. align-items: start pins
       the text to the row top; the visual still has its own
       padding-top: 100px to drop it to title level. */
    .arch-section--split:not(:has(.arch-section__aside)) > .container > .arch-section__split:has(.arch-section__visual .arch-diagram) {
        align-items: start;
    }
    /* Bump the SVG diagrams in .arch-section--split sections by 20%
       on desktop wide mode. Base .arch-diagram caps at 520px; 1.2x
       = 624px. Scoped via :has(.arch-diagram) so it only fires on
       the SVG-diagram split sections (Architecture Overview +
       Arista Top of Rack). The visual column on a 1140px container
       is ~640px wide, so 624px fills it nicely. */
    .arch-section--split .arch-section__visual:has(.arch-diagram) .arch-diagram {
        max-width: 624px;
    }
    .arch-section--split .arch-section__split:has(.arch-section__aside) > .arch-section__aside  { grid-area: aside; }
}
@media (max-width: 991px) {
    .arch-section--split .arch-section__split {
        grid-template-columns: 1fr;
        gap: 32px;
    }
    .arch-section__text { max-width: none; }
}

/* DRY inset for split layouts at narrow-desktop / tablet viewports.
   --------------------------------------------------------------------
   The --article modifier has natural side margin from its
   `max-width: 1100px` text constraint. The --split modifier (2-col
   grid) fills the container edge-to-edge with no equivalent
   constraint, so at iPad-landscape / narrow-desktop widths the 2-col
   content can crowd the floating TOC + scroll-to-top buttons on the
   right. 60px horizontal inset at 768px–1199px solves that.
   Excluded from <=767px (phone portrait/landscape): the grid has
   already collapsed to single-column there, the floating buttons
   are repositioned, and 60px each side would steal half the screen.
   Mobile uses Bootstrap's `.container` gutter (~15px each side) —
   matches what `.about-section` does (e.g. "Why We Run Proxmox VE"
   on /platform-architecture).
   Used by /network-architecture: Architecture Overview, Layer 3
   Core, Arista Top-of-Rack, Layer 2 Fabric. */
@media (min-width: 768px) and (max-width: 1199px) {
    .arch-section--split .arch-section__split {
        padding-left: 60px;
        padding-right: 60px;
    }
}

/* ==========================================================================
   Upstream Carriers & Peering strip (.upstream-strip)
   --------------------------------------------------------------------------
   Proof-point strip for /network-architecture Section 01. Lives inside
   the left text column (.arch-section__text) so it reads as supporting
   the architecture copy, not competing with the topology diagram on
   the right. Two sub-groups — Upstream Carriers (4 transit providers)
   and Peering (Ohio IX) — surfaced as small pills with brand wordmarks.

   Logos are normalised to pure white via `filter: brightness(0)
   invert(1)` so the section reads as cohesive regardless of the
   original brand colours. Opacity dialed to 0.82 so the pills feel
   restrained — supporting the dark --edge theme, not fighting it.
   ========================================================================== */
.upstream-strip {
    margin: 28px 0 0;
}
.upstream-strip__label {
    display: block;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.45);
    margin: 0 0 14px;
}
.upstream-strip__group + .upstream-strip__group { margin-top: 18px; }
.upstream-strip__group-label {
    display: block;
    font-family: var(--font-heading);
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.5);
    margin: 0 0 8px;
}
.upstream-strip__pills {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 10px;
}
/* Peering group holds a single Ohio IX pill. Use the same 4-col
   grid as the carriers so the Ohio IX pill is exactly the same
   size as one carrier pill — Ohio IX occupies column 1 and the
   remaining 3 columns sit empty. Keeps the two strips visually
   aligned and consistent across all viewports. */
.upstream-strip__pills--peering {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}
.upstream-strip__pill {
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px 12px;
    background: rgba(255, 255, 255, 0.035);
    border: 1px solid rgba(255, 255, 255, 0.10);
    border-radius: 8px;
}
/* Desktop: pull the strip into the column gap so pills get more
   horizontal room than .arch-section__text's 470px max-width
   allows. Logos scale up via the existing object-fit: contain.
   The grid columns are .95fr / 1.25fr with a 64px gap; eating
   48px of that gap still leaves 16px of separation from the
   diagram column on the right. Slight height bump (4px) gives
   the box a touch more presence without making it fatter than
   the logos warrant. */
@media (min-width: 992px) {
    .upstream-strip {
        margin-right: -48px;
    }
    .upstream-strip__pill {
        height: 52px;
    }
    .upstream-strip__pills {
        gap: 12px;
    }
}
.upstream-strip__pill img {
    /* Fill the pill content box exactly, then use object-fit to
       scale the image inside it. More robust than max-width/
       max-height: 100% with width/height: auto, which can let
       taller-aspect logos (e.g. FairlawnGig at 278×110, ratio
       2.53:1) overflow the pill bounds when the browser resolves
       the intrinsic size against percentage max-height in a flex
       container. With explicit 100% width+height, the IMG element
       is always exactly the pill content area, and object-fit:
       contain handles the scaling and centering. */
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* Flatten any brand color to pure white alpha, then dial back a
       touch so pills feel muted rather than blazing. Works on both
       SVG and PNG-with-transparency sources. */
    filter: brightness(0) invert(1) opacity(0.82);
    transition: filter 180ms ease;
}

/* When a pill is a link ([href] attribute selector picks only pills
   that are <a> tags, not plain <div>s), give it hover feedback: drop
   the white-filter so the original brand colour comes through and
   lift the border. Background intentionally stays put — only the
   outline + logo color change on interaction, so the pill's dark
   surface tint remains constant. */
.upstream-strip__pill[href] {
    text-decoration: none;
    transition: border-color 180ms ease;
}
.upstream-strip__pill[href]:hover,
.upstream-strip__pill[href]:focus-visible {
    border-color: rgba(255, 255, 255, 0.32);
    outline: none;
}
.upstream-strip__pill[href]:hover img,
.upstream-strip__pill[href]:focus-visible img {
    filter: none;
}

/* 4-in-a-row holds all the way down to ~560px — at 992-991 the text
   column becomes full container width so there's plenty of room for
   4 pills, and narrower tablets still fit 4 comfortably. Drop to
   2×2 only when the container truly can't fit 4 without squishing.
   Peering pill (single 150px column) is unaffected by either rule. */
@media (max-width: 560px) {
    .upstream-strip__pills {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    /* Scale logos down ~10% inside the 48px pill on phone-portrait
       so taller-aspect logos (e.g. FairlawnGig) don't visually
       overflow the pill bounds. Pill chrome stays the same size;
       only the image content shrinks. */
    .upstream-strip__pill img {
        max-width: 90%;
        max-height: 90%;
    }
}

/* Inset callout card — sits inside .arch-section__text, typically
   below the last prose paragraph. Used to surface a discrete piece
   of spec-flavored info (e.g. client uplink tiers) without adding a
   fourth wall-of-text paragraph. Theme surface switches via the
   --edge/--tor modifier hooks below. */
.arch-inset-card {
    margin: 22px 0 0;
    padding: 18px 20px;
    border-radius: 12px;
    border: 1px solid transparent;
}
/* Standalone variant — used when the card sits directly inside a
   .container (outside .arch-section__text), e.g. as a full-width
   highlight note below a cards grid. Constrained + centered so it
   doesn't span the entire 1140px container and lose its "note"
   feeling. Bottom margin is 0 — when the inset is the last element
   in a section, the section's own padding-bottom handles spacing
   (otherwise we'd stack 32px inset-margin + 96px section-padding =
   too much dead space at the fold). 48px top margin gives a clear
   gap between the cards above and the inset. */
.arch-inset-card--standalone {
    max-width: 860px;
    /* Top + bottom margin both 48px. Vertical margins collapse between
       adjacent block elements, so two consecutive insets still sit
       48px apart (not 96px) — but content that FOLLOWS the last inset
       (e.g., the spec-card grid) gets the breathing room it was
       missing when bottom margin was 0. */
    margin: 48px auto;
    padding: 20px 24px;
}
/* When the inset is the last element in its container, drop the
   48px bottom margin so it doesn't compound with the section's own
   padding-bottom (96px). KEEP the card's internal bottom padding —
   the card has a visible border + background, and zeroing internal
   padding made the last paragraph's text sit against the bottom
   edge with no breathing room (especially noticeable on
   multi-paragraph cards like the cut-through forwarding callout). */
.arch-inset-card--standalone:last-child {
    margin-bottom: 0;
}

/* Storage section overrides default .arch-section__body max-width
   (780px) — the vendor spotlight blocks need more horizontal room so
   prose sits comfortably alongside the logo without wrapping after
   only a few words. */
.arch-section--storage .arch-section__body {
    max-width: 1080px;
}

/* Vendor spotlight blocks for /platform-architecture Section 04
   (Storage & Redundancy). Each block pairs a vendor logo on the left
   with 1-2 paragraphs of prose on the right. Two blocks stack
   vertically — Ceph for MCC, HPE Alletra for GPC. At ≤767px the logo
   stacks above the prose. Logos are scaled to fit a 200px-wide slot;
   shorter logos (HPE wordmark) center vertically in a min-height that
   roughly matches the taller logo (Ceph stacked) so adjacent blocks
   feel balanced. */
.storage-vendor {
    display: flex;
    align-items: center;
    gap: 56px;
    margin-bottom: 40px;
}
.storage-vendor:last-child {
    margin-bottom: 0;
}
.storage-vendor__logo {
    flex: 0 0 200px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.storage-vendor__logo img {
    max-width: 100%;
    height: auto;
    display: block;
}
.storage-vendor__body {
    flex: 1;
    min-width: 0; /* prevents long words from forcing flex overflow */
}
.storage-vendor__body p:last-child {
    margin-bottom: 0;
}

@media (max-width: 767px) {
    .storage-vendor {
        flex-direction: column;
        align-items: flex-start;
        gap: 20px;
    }
    .storage-vendor__logo {
        flex: 0 0 auto;
        max-width: 180px;
        justify-content: flex-start;
    }
}

/* Ohio IX peer marquee at the bottom of Section 01 (dark --edge band).
   Reuses .client-logos__track + .client-logos__row mechanics (defined
   at ~L1600) but with a light-on-dark filter + theme-appropriate
   label colour. Logos are normalised to a near-white alpha via
   `filter: brightness(0) invert(1) opacity(0.82)` so the marquee
   reads as cohesive regardless of each source logo's original
   brand colour — same treatment as the upstream carrier pills
   above in this section. */
.arch-section__peers {
    margin-top: 56px;
    padding-top: 28px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.arch-section__peers-label {
    display: block;
    text-align: center;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.76rem;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.5);
    margin: 0 0 18px;
}
.arch-section__peers-track {
    overflow: hidden;
}
/* Peer items stack vertically: logo on top, ASN label below. Aligned
   flex so both elements stay centered as the marquee scrolls. */
.arch-section__peers-track .client-logos__item {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.arch-section__peers-track .client-logos__item img {
    height: 42px;
    /* Full-strength white with slight opacity so thin-stroke wordmarks
       (single-line text logos) still read clearly on the navy bg.
       brightness(0) flattens any source color to black; invert(1)
       flips that to white; alpha is preserved as the logo silhouette. */
    filter: brightness(0) invert(1) opacity(0.95);
}
/* ASN tag — tiny muted monospace-feel label under each logo. */
.arch-section__peers-track .client-logos__asn {
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    color: rgba(255, 255, 255, 0.4);
    white-space: nowrap;
}
@media (max-width: 640px) {
    .arch-section__peers-track .client-logos__item img { height: 34px; }
    .arch-section__peers-track .client-logos__asn { font-size: 0.62rem; }
}
.arch-inset-card__title {
    display: block;
    font-family: var(--font-heading);
    font-size: 0.82rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    margin: 0 0 8px;
}
.arch-inset-card p {
    margin: 0;
    font-size: 0.98rem;
    line-height: 1.55;
}
.arch-inset-card p + p { margin-top: 0.9rem; }
/* Dark theme surface — subtle white tint + pink-accent left edge. */
.arch-section--edge .arch-inset-card {
    background: rgba(255, 255, 255, 0.035);
    border-color: rgba(255, 255, 255, 0.10);
    border-left: 3px solid var(--cp-pink);
}
.arch-section--edge .arch-inset-card__title { color: var(--cp-pink-light); }
.arch-section--edge .arch-inset-card p { color: rgba(255, 255, 255, 0.78); }
.arch-section--edge .arch-inset-card p strong { color: #ffffff; font-weight: 700; }
/* Light theme surface — white card on light bg, same pink accent. */
/* Light-theme surface for the inset card — used on:
     - /network-architecture sections with .arch-section--tor
     - /platform-architecture sections using the legacy .about-section
       scaffold (both numbered sections + the gray --alt breakout)
   Scoping to both parent types means the inset renders correctly on
   any page that drops it in, regardless of which section chassis the
   page was built on. */
.arch-section--tor .arch-inset-card,
.arch-section--panel .arch-inset-card,
.about-section .arch-inset-card {
    background: #ffffff;
    border-color: rgba(26, 34, 51, 0.10);
    border-left: 3px solid var(--cp-pink);
    box-shadow: 0 6px 18px rgba(26, 34, 51, 0.05);
}
.arch-section--tor .arch-inset-card__title,
.arch-section--panel .arch-inset-card__title,
.about-section .arch-inset-card__title { color: var(--cp-pink); }
.arch-section--tor .arch-inset-card p,
.arch-section--panel .arch-inset-card p,
.about-section .arch-inset-card p { color: var(--cp-text); }
.arch-section--tor .arch-inset-card p strong,
.arch-section--panel .arch-inset-card p strong,
.about-section .arch-inset-card p strong { color: var(--cp-text-heading); font-weight: 700; }

/* Spec-card grid below the split. */
.arch-spec-grid { margin-top: 48px; }

/* Vertical stack: diagram + optional hardware photo. */
.arch-visual-stack {
    display: grid;
    gap: 22px;
    align-content: start;
}

/* Real-hardware photo card — dark default, light variant under --tor. */
.arch-photo-card {
    margin: 0;
    border-radius: 18px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.10);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.22);
}
.arch-photo-card img {
    display: block;
    width: 100%;
    height: auto;
}
.arch-photo-card figcaption {
    padding: 12px 14px;
    font-size: 0.92rem;
    line-height: 1.45;
    color: rgba(255, 255, 255, 0.72);
}
.arch-section--tor .arch-photo-card {
    background: #ffffff;
    border: 1px solid rgba(26, 34, 51, 0.08);
    box-shadow: 0 14px 36px rgba(26, 34, 51, 0.08);
}
.arch-section--tor .arch-photo-card figcaption {
    color: var(--cp-text-muted);
}

/* ==========================================================================
   Hardware comparison table — .hw-compare
   --------------------------------------------------------------------------
   Centerpiece of the page. Semantic <table> with <thead>/<tbody> so
   screen readers get column headers. On desktop: zebra rows, sticky-
   looking pink accent on the MCC column, slate accent on GPC. On
   narrow viewports (≤767px): rows collapse vertically and each <td>
   shows its data-label attribute as a mini-header.
   ========================================================================== */
/* ============================================================
   SLA Explainer Modal — accessible centered popup that opens
   when "six nines" / "four nines" are clicked in the hardware
   comparison table. Shows both tiers side-by-side. Closes on
   backdrop click, Escape key, or close button. Sized to fit
   on mobile portrait, mobile landscape, and desktop.
   ============================================================ */
.sla-modal {
    position: fixed;
    inset: 0;
    z-index: 1100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}
.sla-modal[hidden] { display: none; }
.sla-modal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(15, 25, 40, 0.66);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    cursor: pointer;
}
.sla-modal__panel {
    position: relative;
    background: #ffffff;
    color: var(--cp-text);
    border-radius: 14px;
    width: 100%;
    max-width: 540px;
    max-height: calc(100vh - 32px);
    overflow-y: auto;
    padding: 32px 28px 22px;
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.30);
    animation: slaModalFadeIn 0.18s ease-out;
}
@keyframes slaModalFadeIn {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}
.sla-modal__close {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 36px;
    height: 36px;
    border: none;
    background: transparent;
    color: var(--cp-text-muted);
    font-size: 18px;
    cursor: pointer;
    border-radius: 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s ease, color 0.15s ease;
}
.sla-modal__close:hover,
.sla-modal__close:focus-visible {
    background: rgba(0, 0, 0, 0.06);
    color: var(--cp-text-heading);
    outline: none;
}
.sla-modal h3 {
    font-family: var(--font-heading);
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--cp-text-heading);
    margin: 0 32px 12px 0;
    line-height: 1.3;
}
.sla-modal__intro {
    font-size: 0.95rem;
    line-height: 1.55;
    color: var(--cp-text);
    margin: 0 0 18px;
}
.sla-modal__table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.sla-modal__table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.92rem;
    margin: 0 0 14px;
}
.sla-modal__table th,
.sla-modal__table td {
    padding: 10px 12px;
    text-align: left;
    border-bottom: 1px solid var(--cp-border);
}
.sla-modal__table thead th {
    background: rgba(222, 53, 128, 0.04);
    font-family: var(--font-heading);
    font-weight: 600;
    color: var(--cp-text-heading);
    font-size: 0.82rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    line-height: 1.3;
    border-bottom: 2px solid var(--cp-pink);
    vertical-align: bottom;
}
.sla-modal__table thead th strong { color: var(--cp-pink); }
.sla-modal__pct {
    font-family: var(--font-heading);
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--cp-text-muted);
    letter-spacing: 0.02em;
    text-transform: none;
    display: inline-block;
    margin-top: 2px;
}
.sla-modal__table tbody th {
    font-family: var(--font-heading);
    font-weight: 600;
    color: var(--cp-text-heading);
    width: 30%;
}
.sla-modal__table tbody td {
    font-variant-numeric: tabular-nums;
    color: var(--cp-text);
}
.sla-modal__table tbody tr:last-child th,
.sla-modal__table tbody tr:last-child td { border-bottom: none; }
.sla-modal__attribution {
    font-size: 0.82rem;
    color: var(--cp-text-muted);
    margin: 0;
    text-align: right;
}
.sla-modal__attribution a {
    color: var(--cp-pink);
    border-bottom: 1px solid rgba(222, 53, 128, 0.3);
    text-decoration: none;
    transition: border-color 0.15s ease;
}
.sla-modal__attribution a:hover { border-bottom-color: var(--cp-pink); }

/* Mobile portrait — tighter padding, slightly smaller header. */
@media (max-width: 480px) {
    .sla-modal { padding: 12px; }
    .sla-modal__panel { padding: 26px 20px 18px; border-radius: 12px; }
    .sla-modal h3 { font-size: 1.1rem; margin-right: 28px; }
    .sla-modal__intro { font-size: 0.9rem; }
    .sla-modal__table { font-size: 0.85rem; }
    .sla-modal__table th,
    .sla-modal__table td { padding: 8px 8px; }
}

/* Landscape phones — height-constrained: shrink vertical padding so
   the modal still fits without becoming scrollable when not needed. */
@media (max-width: 900px) and (orientation: landscape) and (max-height: 500px) {
    .sla-modal { padding: 10px; align-items: flex-start; }
    .sla-modal__panel { padding: 20px 22px 14px; max-height: calc(100vh - 20px); }
    .sla-modal h3 { font-size: 1.05rem; margin-bottom: 8px; }
    .sla-modal__intro { font-size: 0.88rem; margin-bottom: 12px; }
    .sla-modal__table { font-size: 0.85rem; }
    .sla-modal__table th,
    .sla-modal__table td { padding: 6px 10px; }
}

/* Trigger styling — make it visually obvious that "six nines" / "four
   nines" are interactive (cursor pointer, dotted underline so it
   doesn't look identical to standard external links). */
.sla-trigger {
    cursor: pointer;
    border-bottom: 1px dotted currentColor;
    text-decoration: none;
}
.sla-trigger:hover,
.sla-trigger:focus-visible {
    border-bottom-style: solid;
    text-decoration: none;
}

.hw-compare {
    max-width: 1140px;
    margin: 48px auto 0;
    background: #ffffff;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r-lg);
    box-shadow: 0 18px 48px rgba(26, 34, 51, 0.08);
    overflow: hidden;
}
/* On phone-size viewports, the default browser scroll behavior for
   #hardware-comparison lands past the eyebrow + h3, dropping the
   reader straight into the table's first body row (Platform
   Generation). Add a positive scroll-margin-top so the page scrolls
   to a position where the "Hardware Comparison" eyebrow sits just
   below the sticky header, giving readers context for what they're
   looking at instead of dumping them mid-table. Desktop behavior is
   left untouched (it already lands cleanly at the spec header row). */
@media (max-width: 600px) {
    #hardware-comparison { scroll-margin-top: 90px; }
}

.hw-compare__header {
    padding: 32px 36px 20px;
    text-align: center;
    border-bottom: 1px solid var(--cp-border);
    background: linear-gradient(180deg, rgba(246, 248, 251, 0.9) 0%, #ffffff 100%);
}
.hw-compare__eyebrow {
    display: inline-block;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--cp-pink);
    margin-bottom: 10px;
}
.hw-compare__title {
    font-family: var(--font-heading);
    font-size: clamp(1.35rem, 2.2vw, 1.8rem);
    font-weight: 700;
    color: var(--cp-text-heading);
    margin: 0 0 10px;
    line-height: 1.25;
}
.hw-compare__note {
    max-width: 680px;
    margin: 0 auto;
    color: var(--cp-text-muted);
    font-size: 0.98rem;
    line-height: 1.6;
}

/* Horizontal scroll wrapper — at widths where the table would overflow
   the card (rare, but possible on narrow tablets before the vertical-
   stack kicks in), lets the user pan horizontally rather than crushing
   the cells. */
.hw-compare__scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.hw-compare__table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.98rem;
    color: var(--cp-text);
}

/* Column header row — pink accent on MCC, slate on GPC */
.hw-compare__table thead th {
    font-family: var(--font-heading);
    font-weight: 700;
    text-align: left;
    padding: 22px 22px 20px;
    vertical-align: bottom;
    background: #fafbfd;
    border-bottom: 2px solid var(--cp-border-strong);
    color: var(--cp-text-heading);
}
.hw-compare__spec-head {
    font-size: 0.78rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--cp-text-muted) !important;
    width: 28%;
}
.hw-compare__col-head {
    width: 36%;
    position: relative;
    padding-top: 26px !important;
}
.hw-compare__col-head::before {
    content: "";
    position: absolute;
    top: 0;
    left: 12px;
    right: 12px;
    height: 4px;
    border-radius: 0 0 3px 3px;
}
.hw-compare__col-head--mcc::before {
    background: linear-gradient(90deg, var(--cp-pink) 0%, var(--cp-pink-light) 100%);
}
.hw-compare__col-head--gpc::before {
    background: linear-gradient(90deg, #5a7a9a 0%, #7a9dbe 100%);
}
.hw-compare__col-tag {
    display: inline-block;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    padding: 3px 9px;
    border-radius: 4px;
    margin-bottom: 8px;
}
.hw-compare__col-head--mcc .hw-compare__col-tag {
    color: var(--cp-pink);
    background: rgba(222, 53, 128, 0.1);
    border: 1px solid rgba(222, 53, 128, 0.25);
}
.hw-compare__col-head--gpc .hw-compare__col-tag {
    color: #2c3e50;
    background: rgba(122, 157, 190, 0.15);
    border: 1px solid rgba(74, 98, 116, 0.25);
}
.hw-compare__col-name {
    display: block;
    font-size: 1.5rem;
    font-weight: 800;
    color: var(--cp-text-heading);
    line-height: 1.1;
}
.hw-compare__col-head--mcc .hw-compare__col-name {
    color: var(--cp-pink);
}
.hw-compare__col-sub {
    display: block;
    font-family: var(--font-body);
    font-size: 0.82rem;
    font-weight: 500;
    color: var(--cp-text-muted);
    letter-spacing: 0;
    text-transform: none;
    margin-top: 2px;
}

/* Body rows — zebra pattern, first-column is the spec label, then
   MCC column (pink left accent), then GPC column (slate left accent). */
.hw-compare__table tbody tr {
    border-bottom: 1px solid var(--cp-border);
}
.hw-compare__table tbody tr:last-child {
    border-bottom: none;
}
.hw-compare__table tbody tr:nth-child(even) {
    background: #fafbfd;
}
.hw-compare__table tbody th,
.hw-compare__table tbody td {
    padding: 18px 22px;
    vertical-align: top;
    line-height: 1.55;
}
.hw-compare__table tbody th {
    font-family: var(--font-heading);
    font-size: 0.92rem;
    font-weight: 600;
    color: var(--cp-text-heading);
    text-align: left;
    letter-spacing: 0.01em;
    width: 28%;
}
.hw-compare__table tbody td {
    font-size: 0.95rem;
    color: var(--cp-text);
}
.hw-compare__table tbody td:nth-child(2) {
    /* MCC column — subtle pink left accent, stronger type */
    box-shadow: inset 3px 0 0 rgba(222, 53, 128, 0.45);
}
.hw-compare__table tbody td:nth-child(3) {
    /* GPC column — slate left accent */
    box-shadow: inset 3px 0 0 rgba(90, 122, 154, 0.45);
}
/* Shared row — colspan="2" cell that applies to BOTH MCC and GPC.
   Match the per-tier rows' accent pattern (left-edge pink stripe
   only, no right border) so the visual rhythm of the column borders
   stays consistent. The "spans both" signal comes from the centered
   text + the colspan width — no extra border treatment needed. */
.hw-compare__table tbody td.hw-compare__shared {
    text-align: center;
    box-shadow: inset 3px 0 0 rgba(222, 53, 128, 0.45);
}
.hw-compare__table tbody td strong {
    color: var(--cp-text-heading);
    font-weight: 700;
}
.hw-compare__muted {
    color: var(--cp-text-muted);
    font-size: 0.88rem;
}
.hw-compare__plus {
    color: var(--cp-pink);
    font-weight: 700;
    padding: 0 2px;
}

/* Pill tags inside table cells (e.g. "current", "previous gen") */
.hw-compare__tag {
    display: inline-block;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    padding: 2px 8px;
    border-radius: 4px;
    margin-left: 6px;
    vertical-align: 2px;
    white-space: nowrap;
}
.hw-compare__tag--current {
    color: #ffffff;
    background: var(--cp-pink);
}
.hw-compare__tag--legacy {
    color: var(--cp-text-muted);
    background: rgba(26, 34, 51, 0.06);
    border: 1px solid var(--cp-border-strong);
}

/* TBD cells — muted italic so they visually recede but are still legible.
   A tiny pink dot marker signals "we know this, it's just pending". */
.hw-compare__tbd {
    color: var(--cp-text-muted) !important;
}
.hw-compare__tbd em {
    font-style: italic;
    font-weight: 500;
    position: relative;
    padding-left: 16px;
}
.hw-compare__tbd em::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.55em;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(222, 53, 128, 0.35);
    box-shadow: 0 0 0 3px rgba(222, 53, 128, 0.1);
}

/* CTA row below the table */
.hw-compare__cta-row {
    display: flex;
    gap: 14px;
    justify-content: center;
    flex-wrap: wrap;
    padding: 28px 36px 36px;
    border-top: 1px solid var(--cp-border);
    background: #fafbfd;
}
/* At desktop width (≥992px), align each CTA under its column header
   (MCC button below MCC column, GPC button below GPC column). The
   grid mirrors the table's column widths: 28% spec column, then 1fr
   each for MCC and GPC. Below 992px the base flex-centered layout
   above takes over. */
@media (min-width: 992px) {
    .hw-compare__cta-row {
        display: grid;
        grid-template-columns: 28% 1fr 1fr;
        gap: 0;
    }
    .hw-compare__cta-row .btn { justify-self: center; }
    .hw-compare__cta-row .btn:nth-child(1) { grid-column: 2; }
    .hw-compare__cta-row .btn:nth-child(2) { grid-column: 3; }
}
/* .btn-ghost is hard-coded white text + white-translucent border for
   dark hero/section backgrounds. On the table CTA row's light gray
   surface it renders invisible. Recolor inline with the same dark
   text + dark-translucent border + pink hover treatment used for
   .category-intro .btn-ghost. */
.hw-compare__cta-row .btn-ghost {
    color: var(--cp-text-heading);
    border-color: rgba(26, 34, 51, 0.32);
}
.hw-compare__cta-row .btn-ghost:hover,
.hw-compare__cta-row .btn-ghost:focus {
    color: var(--cp-pink);
    border-color: var(--cp-pink);
}

/* Tablet — tighten padding, keep table layout */
@media (max-width: 991px) {
    .hw-compare__header {
        padding: 26px 24px 18px;
    }
    .hw-compare__table thead th,
    .hw-compare__table tbody th,
    .hw-compare__table tbody td {
        padding: 16px 16px;
    }
    .hw-compare__col-name { font-size: 1.3rem; }
}

/* Mobile (≤767px) — fully stacked layout. Each row becomes a 3-block
   stack: spec label (full-width), MCC value, GPC value. data-label
   attributes on each <td> render as small uppercase labels so the
   MCC/GPC context stays visible when the column headers are hidden. */
@media (max-width: 767px) {
    .hw-compare {
        border-radius: var(--cp-r);
    }
    .hw-compare__header {
        padding: 22px 20px 16px;
    }
    .hw-compare__table {
        display: block;
    }
    .hw-compare__table thead {
        /* Hide the desktop column header row — mobile shows per-cell
           labels via data-label instead. Visually-hidden so screen
           readers still get the column scope from the thead element. */
        position: absolute;
        left: -9999px;
        width: 1px;
        height: 1px;
        overflow: hidden;
    }
    .hw-compare__table tbody,
    .hw-compare__table tr {
        display: block;
    }
    .hw-compare__table tbody tr {
        padding: 18px 18px 14px;
        border-bottom: 1px solid var(--cp-border);
    }
    .hw-compare__table tbody tr:nth-child(even) {
        background: #fafbfd;
    }
    .hw-compare__table tbody th {
        display: block;
        width: 100%;
        padding: 0 0 10px;
        font-size: 0.78rem;
        font-weight: 700;
        letter-spacing: 0.14em;
        text-transform: uppercase;
        color: var(--cp-text-muted);
        border-bottom: 1px dashed var(--cp-border);
        margin-bottom: 10px;
    }
    .hw-compare__table tbody td {
        display: block;
        width: 100%;
        padding: 10px 0 10px 14px;
        font-size: 0.95rem;
        box-shadow: inset 3px 0 0 rgba(222, 53, 128, 0.35) !important;
        position: relative;
    }
    .hw-compare__table tbody td:nth-child(3) {
        box-shadow: inset 3px 0 0 rgba(90, 122, 154, 0.45) !important;
        margin-top: 4px;
    }
    .hw-compare__table tbody td::before {
        content: attr(data-label);
        display: block;
        font-family: 'Share Tech', var(--font-heading);
        font-size: 0.68rem;
        font-weight: 700;
        letter-spacing: 0.18em;
        text-transform: uppercase;
        color: var(--cp-text-muted);
        margin-bottom: 4px;
    }
    .hw-compare__table tbody td:nth-child(2)::before {
        color: var(--cp-pink);
    }
    .hw-compare__table tbody td:nth-child(3)::before {
        color: #5a7a9a;
    }
    /* Shared rows on mobile: keep left-aligned (no centering), use
       a muted "Both" label color, and stripe just the left edge
       (pink) at the same opacity as per-tier rows. */
    .hw-compare__table tbody td.hw-compare__shared {
        text-align: left;
        box-shadow: inset 3px 0 0 rgba(222, 53, 128, 0.35) !important;
    }
    .hw-compare__table tbody td.hw-compare__shared::before {
        color: var(--cp-text-muted) !important;
    }
    .hw-compare__cta-row {
        padding: 22px 20px 24px;
    }
    .hw-compare__cta-row .btn { width: 100%; }
}

/* Manifesto band (.section-lead.arch-manifesto) — tiny overrides so the
   single-paragraph lead + two-paragraph body reads with the right rhythm
   on this specific page. The stock .section-lead rules handle everything
   else (dark bg, radial gradients, white hierarchy, <strong> bumps). */
.arch-manifesto .section-lead__lead {
    max-width: 720px;
}
.arch-manifesto p:not(.section-lead__lead) {
    margin-bottom: 16px;
}
.arch-manifesto p:not(.section-lead__lead):last-child {
    margin-bottom: 0;
}

/* =========================================================================
   services-and-solutions page
   -------------------------------------------------------------------------
   Portfolio landing page at /services-and-solutions.php. Reuses:
     .category-hero.category-hero--default   — slate gradient hero
     .category-intro                         — light intro band
     .cp-store-card + variants               — home-page compute + backup tiles
     .about-section / .about-section--alt    — numbered narrative sections
     .platform-spec-card--v1                  — white spec cards (support + pro services)
     .page-cta                                — final CTA block
   New blocks introduced below:
     .portfolio-split                         — alternating tile/copy rows (MCC, GPC)
     .portfolio-backup                        — umbrella tile + 3-up paths (backup)
     .portfolio-path                          — individual backup-path card
     .portfolio-cards                         — shared grid wrapper for support +
                                                professional-services cards (3-up
                                                and 4-up variants)
   All color/radius/font values pull from the :root tokens at the top of this
   file. No inline styles in the template; no hard-coded colors below.
   ========================================================================= */

/* Section wrapper — vertical rhythm matches .category-intro + .about-section
   pairing on MCC/GPC/Veeam so this page doesn't feel tighter/looser than the
   others. The --alt modifier paints the band in the site's alt background. */
.portfolio-split {
    padding: 80px 0 56px;
    background: var(--cp-bg);
}
.portfolio-split--alt {
    background: var(--cp-bg-alt);
}
/* On /services-and-solutions, the first .portfolio-split (MCC) sits
   directly under the .category-intro intro block — both with white
   backgrounds and no visible divider. The default 60px-bottom +
   80px-top gap reads as a gulf. Halving the top padding when the
   .portfolio-split immediately follows a .category-intro (with an
   intervening section-anchor span) keeps the ~70px combined gap. */
.category-intro + .section-anchor + .portfolio-split {
    padding-top: 20px;
}

/* Two-column grid on desktop. 1fr 1fr keeps tile and copy roughly balanced;
   align-items center so a shorter copy column doesn't leave the tile
   floating above a big whitespace gap. Gap is generous (60px) to signal
   "these are two peer blocks" rather than "a figure with a caption". */
.portfolio-split__grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 60px;
    align-items: center;
}

/* Mobile: stack, and ALWAYS put the tile first regardless of the desktop
   ordering (the user-facing read on phones is tile-then-copy for both
   rows — the alternation only exists to create visual rhythm on wide
   viewports). The tile-right modifier uses grid row-start to pull the
   tile up on mobile without affecting desktop source order. */
@media (max-width: 991px) {
    .portfolio-split {
        padding: 56px 0;
    }
    .portfolio-split__grid {
        grid-template-columns: 1fr;
        gap: 40px;
    }
    .portfolio-split--tile-right .portfolio-split__tile {
        grid-row: 1;
    }
    .portfolio-split--tile-right .portfolio-split__copy {
        grid-row: 2;
    }
}

/* Tile column — the .cp-store-card inside carries its own height (via
   .cp-store-card min-height rules), so the column just centers it and
   clips nothing. Max-width caps the tile at the home-page size so it
   doesn't stretch to column width on very wide viewports and start
   looking cartoonish. */
.portfolio-split__tile {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 28px;
}
.portfolio-split__tile .cp-store-card {
    width: 100%;
    max-width: 520px;
}
/* Architecture quick-links beneath each card on /services-and-solutions.
   Wings cluster: a "Compare to {platform}" medallion on the left, two
   stacked architecture buttons on the right. Same gradient-ring +
   dark-core medallion design as the home-page wings center. The grid
   keeps the layout unchanged at all viewports — the cluster fits
   inside the 520px tile-cta width even on narrow phones. */
.portfolio-split__tile-cta {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 18px;
    align-items: center;
    width: 100%;
    /* Tuck inward from the card edges (card max-width is 520px). The
       smaller cluster width creates clear visual breathing room on the
       left/right so the CTA reads as a "rest stop" beneath the tile,
       not a full-width continuation of it. */
    max-width: 440px;
}

/* Compare circle medallion. Sized smaller (105px) than the home-page
   wings center (124px) since the tile-cta width is constrained. */
.portfolio-split__compare {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 105px;
    height: 105px;
    border-radius: 50%;
    background: linear-gradient(135deg, #de3580 0%, #a0558a 50%, #5a7a9a 100%);
    color: #ffffff;
    text-decoration: none;
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.18);
    line-height: 1.15;
    text-align: center;
    flex-shrink: 0;
    position: relative;
    transition: transform .18s ease, box-shadow .18s ease;
    overflow: hidden;
}
.portfolio-split__compare::before {
    content: '';
    position: absolute;
    top: 5px; left: 5px; right: 5px; bottom: 5px;
    border-radius: 50%;
    background: #1a3050;
    z-index: 0;
}
.portfolio-split__compare:hover,
.portfolio-split__compare:focus-visible {
    transform: translateY(-2px);
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.24);
    color: #ffffff;
    text-decoration: none;
}
.portfolio-split__compare-top {
    font-size: 0.62rem;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    opacity: 0.92;
    position: relative;
    z-index: 1;
}
.portfolio-split__compare-main {
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 1.2rem;
    letter-spacing: 0.02em;
    margin-top: 3px;
    position: relative;
    z-index: 1;
}

/* Two architecture buttons stacked vertically in the right column. */
.portfolio-split__tile-cta-stack {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.portfolio-split__tile-cta-stack .btn-secondary {
    text-align: center;
    font-size: 0.88rem;
    padding: 10px 14px;
}

/* Copy column */
.portfolio-split__copy {
    max-width: 560px;
}
.portfolio-split__eyebrow {
    display: inline-block;
    font-family: var(--font-tech);
    font-size: 0.85rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--cp-pink);
    margin-bottom: 12px;
}
.portfolio-split__copy h3 {
    font-family: var(--font-heading);
    color: var(--cp-text-heading);
    font-size: clamp(1.55rem, 2.6vw, 2.05rem);
    line-height: 1.2;
    margin: 0 0 18px;
}
.portfolio-split__copy p {
    color: var(--cp-text);
    font-size: 1rem;
    line-height: 1.65;
    margin: 0 0 14px;
}

/* Bulleted highlights — tight, scannable, icon-like check marks. No
   list-style (we draw the check via ::before so color and alignment
   are under our control). */
.portfolio-split__highlights {
    list-style: none;
    padding: 0;
    margin: 22px 0 8px;
}
.portfolio-split__highlights li {
    position: relative;
    padding: 6px 0 6px 28px;
    color: var(--cp-text);
    font-size: 0.97rem;
    line-height: 1.45;
    border-bottom: 1px solid var(--cp-border);
}
.portfolio-split__highlights li:last-child {
    border-bottom: none;
}
.portfolio-split__highlights li::before {
    content: '\f00c'; /* fa-check — shares the Font Awesome font stack */
    font-family: 'Font Awesome 6 Free';
    font-weight: 900;
    position: absolute;
    left: 0;
    top: 8px;
    color: var(--cp-pink);
    font-size: 0.85rem;
}
.portfolio-split__highlights li strong {
    color: var(--cp-text-heading);
}

.portfolio-split__cta {
    margin-top: 10px;
}

/* -------------------------------------------------------------------------
   Backup section — umbrella tile + 3-up sub-path cards
   ------------------------------------------------------------------------- */
.portfolio-backup {
    padding: 80px 0 48px;
    background: var(--cp-bg);
}

/* Dark navy callout band between GPC and Data Protection on
   /services-and-solutions. Single-paragraph "mix and match" story —
   restates the home-page Enterprise Cloud note in a more prominent
   visual placement so the inter-tier compatibility message lands as
   a deliberate beat, not a fine-print footer. */
.cross-platform-band {
    padding: 56px 0;
    background: var(--cp-bg-footer);
    color: rgba(255, 255, 255, 0.85);
}
.cross-platform-band p {
    max-width: 880px;
    margin: 0 auto;
    text-align: center;
    font-size: 1.05rem;
    line-height: 1.7;
    color: rgba(255, 255, 255, 0.85);
}
.cross-platform-band p strong { color: #ffffff; font-weight: 600; }

.portfolio-backup__intro {
    max-width: 780px;
    margin: 0 auto 48px;
    text-align: center;
}
.portfolio-backup__intro h2 {
    font-family: var(--font-heading);
    color: var(--cp-text-heading);
    margin: 12px 0 16px;
}
.portfolio-backup__intro p {
    color: var(--cp-text);
    font-size: 1.05rem;
    line-height: 1.6;
    margin: 0;
}

/* Umbrella tile — full-width treatment of .cp-store-card--veeam. The
   .cp-store-card base is a grid of rows; we override just enough to let
   the card breathe when stretched to 100% width without breaking the
   hover / gradient / pricing behavior defined for the shared class. */
.portfolio-backup__umbrella {
    display: block;
    max-width: 1100px;
    margin: 0 auto 40px;
    padding: 36px 40px;
}
.portfolio-backup__umbrella .cp-store-card__name {
    font-size: 1.55rem;
}
.portfolio-backup__umbrella .cp-store-card__desc {
    font-size: 1rem;
    max-width: 860px;
}
@media (max-width: 767px) {
    .portfolio-backup__umbrella {
        padding: 24px 22px;
    }
    .portfolio-backup__umbrella .cp-store-card__name {
        font-size: 1.2rem;
    }
}

/* 3-up grid of compact path cards. These are intentionally simpler than
   the umbrella tile above (white background, subtle border) so the
   hierarchy reads as "one category, three paths" instead of four equal-
   weight tiles. */
.portfolio-backup__paths {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
    max-width: 1100px;
    margin: 0 auto;
}
@media (max-width: 991px) {
    .portfolio-backup__paths {
        grid-template-columns: 1fr;
        gap: 18px;
    }
}

.portfolio-path {
    display: flex;
    flex-direction: column;
    background: var(--cp-bg);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-r);
    padding: 26px 24px;
    text-decoration: none;
    color: var(--cp-text);
    transition: border-color 0.25s ease, box-shadow 0.25s ease, transform 0.25s ease;
    box-shadow: 0 2px 10px rgba(26, 34, 51, 0.04);
}
@media (hover: hover) {
    .portfolio-path:hover {
        border-color: var(--cp-border-strong);
        box-shadow: var(--cp-shadow-card-hover);
        transform: translateY(-2px);
        text-decoration: none;
        color: var(--cp-text);
    }
    .portfolio-path:hover .portfolio-path__link {
        color: var(--cp-pink-dark);
    }
    .portfolio-path:hover .portfolio-path__link i {
        transform: translateX(3px);
    }
}

.portfolio-path__icon {
    width: 44px;
    height: 44px;
    border-radius: var(--cp-r-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 20px;
    color: #fff;
    margin-bottom: 14px;
}
/* Path icon gradients mirror the home-page veeam variants so the color
   language stays consistent as the user scrolls from tile → sub-cards. */
.portfolio-path--cc   .portfolio-path__icon { background: linear-gradient(135deg, #28a745, #20c997); }
.portfolio-path--br   .portfolio-path__icon { background: linear-gradient(135deg, #20c997, #17a2b8); }
.portfolio-path--m365 .portfolio-path__icon { background: linear-gradient(135deg, #17a2b8, #3b82f6); }

.portfolio-path__eyebrow {
    display: inline-block;
    font-family: var(--font-tech);
    font-size: 0.7rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--cp-text-muted);
    margin-bottom: 6px;
}
.portfolio-path h4 {
    font-family: var(--font-heading);
    color: var(--cp-text-heading);
    font-size: 1.15rem;
    margin: 0 0 10px;
    line-height: 1.25;
}
.portfolio-path p {
    color: var(--cp-text);
    font-size: 0.93rem;
    line-height: 1.55;
    margin: 0 0 16px;
    flex-grow: 1;
}
.portfolio-path__link {
    color: var(--cp-pink);
    font-weight: 600;
    font-size: 0.88rem;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: color 0.2s ease;
}
.portfolio-path__link i {
    transition: transform 0.2s ease;
}

/* -------------------------------------------------------------------------
   Shared grid wrapper for the Support + Professional Services card grids.
   .platform-spec-card--v1 already has its own look (white bg, icon + h4
   + bullet list); this just provides the grid to lay them out in.
   ------------------------------------------------------------------------- */
.portfolio-cards {
    display: grid;
    gap: 24px;
    margin-top: 32px;
    /* Constrain to a comfortable width — full container (~1140px) feels
       overly girthy for 3-card spec layouts. ~960px keeps the cards
       readable without sprawling. */
    max-width: 960px;
    margin-left: auto;
    margin-right: auto;
}
.portfolio-cards--three {
    grid-template-columns: repeat(3, 1fr);
}
.portfolio-cards--four {
    grid-template-columns: repeat(2, 1fr);
}
/* Tablet (768–991px): 3-up cards drop to 2-up with the third card
   centered on its own row at half-width. Mirrors the same 2+1
   pattern used for .cp-store-browse__grid--three (Veeam cards) so
   tablet readers see a consistent grid behavior across the page. */
@media (max-width: 991px) {
    .portfolio-cards--three {
        grid-template-columns: 1fr 1fr;
    }
    .portfolio-cards--three > *:last-child:nth-child(odd) {
        grid-column: 1 / -1;
        max-width: calc(50% - 12px);
        justify-self: center;
    }
}
@media (max-width: 767px) {
    .portfolio-cards--three,
    .portfolio-cards--four {
        grid-template-columns: 1fr;
        gap: 18px;
    }
    .portfolio-cards--three > *:last-child:nth-child(odd) {
        grid-column: auto;
        max-width: 100%;
        justify-self: stretch;
    }
}



/* ==========================================================================
   Floating Table-of-Contents (TOC) — site-wide
   --------------------------------------------------------------------------
   Right-edge pill toggle + slide-in panel. Scans the <main> content for
   h2/h3 on page load (via buildToc() in site.js) and renders a jump
   list; scroll-spy highlights the currently-visible section.
   Colors re-skinned to match CP palette:
     - toggle     = white pill with pink border/icon, pink fill on hover
     - panel      = dark slate (matches --cp-bg-footer) with light text
     - accent     = brand pink (--cp-pink / --cp-pink-light on dark bg)
   Auto-hides on pages that don't have at least one h2/h3 to link to.
   ========================================================================== */

/* TOC toggle pill — child of .cp-floating-stack (above). No own
   position/right/top here: the stack handles alignment for both
   this button and the scroll-to-top below it, so they always
   share the same right-edge at every breakpoint. */
.toc-toggle {
    width: 42px;
    height: 42px;
    border-radius: 10px;
    border: 1px solid var(--cp-border-strong);
    background: #ffffff;
    color: var(--cp-pink);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 14px rgba(26, 34, 51, 0.18);
    transition: background 0.2s ease,
                color 0.2s ease,
                border-color 0.2s ease,
                box-shadow 0.2s ease,
                transform 0.2s ease;
    padding: 0;
    flex: 0 0 auto;
}
/* Hover guarded behind (hover: hover) — without this, iPads fire the
   pink-fill state on first tap and require a second tap to actually
   toggle the TOC panel. :focus-visible kept separate so keyboard
   navigation still gets the highlight. */
@media (hover: hover) {
    .toc-toggle:hover {
        background: var(--cp-pink);
        color: #ffffff;
        border-color: var(--cp-pink);
        box-shadow: 0 8px 22px rgba(222, 53, 128, 0.35);
    }
}
.toc-toggle:focus-visible,
.toc-toggle.is-active {
    background: var(--cp-pink);
    color: #ffffff;
    border-color: var(--cp-pink);
    box-shadow: 0 8px 22px rgba(222, 53, 128, 0.35);
    outline: none;
}
.toc-toggle.hidden {
    display: none;
}
/* Pre-scroll hidden state — distinct from .hidden (which is for
   pages with no headings) because we want a smooth fade-in when
   the user starts scrolling, not a hard flip. The existing
   transition on .toc-toggle already covers opacity/etc. */
.toc-toggle.toc-reveal-pending {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

/* Slide-in panel. Top tracks the sticky chrome (header + breadcrumb)
   which shrinks as the page scrolls, via the --scroll-shrink custom
   property (0→1 over the first 44px of scroll). Without this, the
   panel has a visible gap at scroll=0 where the panel top and the
   breadcrumb bottom don't match. On desktop the breadcrumb top is
   `calc(114px - --scroll-shrink * 44px)` and the breadcrumb itself
   is 48px tall, so breadcrumb-bottom = 162px at rest → 118px
   scrolled. The panel matches. Under 1200 the chrome doesn't shrink
   so a fixed 131px is used (see media query below). */
.toc-panel {
    position: fixed;
    top: 131px;
    bottom: 0;
    right: -320px;
    width: 280px;
    max-width: 85vw;
    z-index: 800;
    background: var(--cp-bg-footer);
    color: rgba(255, 255, 255, 0.88);
    display: flex;
    flex-direction: column;
    justify-content: center;
    box-shadow: -8px 0 28px rgba(0, 0, 0, 0.3);
    transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
@media (min-width: 1200px) {
    .toc-panel {
        top: calc(162px - var(--scroll-shrink, 0) * 44px);
    }
}
.toc-panel.open {
    right: 0;
}
.toc-panel__inner {
    display: flex;
    flex-direction: column;
    min-height: 0;
    max-height: 100%;
    padding: 26px 0;
    overflow-y: auto;
}

/* Custom scrollbar inside the panel — subtle, theme-matched. Now
   on the inner wrapper since the outer panel no longer scrolls. */
.toc-panel__inner::-webkit-scrollbar { width: 6px; }
.toc-panel__inner::-webkit-scrollbar-track { background: transparent; }
.toc-panel__inner::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.15);
    border-radius: 3px;
}
.toc-panel__inner::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.25);
}

/* "On This Page" header label. */
.toc-panel__header {
    padding: 4px 24px 14px;
    font-family: 'Share Tech', var(--font-heading);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.55);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    margin-bottom: 10px;
}

/* Links. H2 default, H3 indented + dimmer via .toc-h3. */
.toc-panel__list a {
    display: block;
    padding: 8px 24px;
    color: rgba(255, 255, 255, 0.85);
    text-decoration: none;
    font-family: var(--font-heading);
    font-size: 0.88rem;
    font-weight: 500;
    line-height: 1.4;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease,
                border-color 0.15s ease;
    border-left: 3px solid transparent;
}
.toc-panel__list a.toc-h3 {
    padding-left: 40px;
    font-size: 0.82rem;
    color: rgba(255, 255, 255, 0.55);
    font-weight: 400;
}
.toc-panel__list a.toc-h4 {
    padding-left: 56px;
    font-size: 0.78rem;
    color: rgba(255, 255, 255, 0.42);
    font-weight: 400;
}
/* Hover styles guarded behind (hover: hover) — without this, iPads
   and other touch devices fire :hover on first tap and require a
   second tap to actually navigate (Mobile Safari's "fast-tap" model
   treats hover-styled elements as tooltips on first touch). Keeping
   :focus-visible separate so keyboard nav still gets the highlight. */
@media (hover: hover) {
    .toc-panel__list a:hover {
        background: rgba(255, 255, 255, 0.05);
        color: var(--cp-pink-light);
    }
}
.toc-panel__list a:focus-visible {
    background: rgba(255, 255, 255, 0.05);
    color: var(--cp-pink-light);
    outline: none;
}
.toc-panel__list a.active {
    color: var(--cp-pink-light);
    border-left-color: var(--cp-pink);
    background: rgba(222, 53, 128, 0.08);
}

/* Mobile: panel slightly wider. TOC toggle position is handled by
   .cp-floating-stack now — no per-breakpoint override needed here. */
@media (max-width: 767px) {
    .toc-panel {
        width: 300px;
        right: -320px;
    }
}

/* ============================================================
   ABOUT US PAGE
   Magazine intro, mission, team, principles, staggered chapters,
   and values. Reuses .arch-section--article + .about-section
   primitives; adds new patterns for team grid, principle cards,
   oversized-numeral chapters, and value cards.
   ============================================================ */

/* --- Story (magazine intro) ----------------------------------- */
.about-story {
    padding: 96px 0 80px;
}
.about-story__figure {
    /* Inherits .arch-diagram + .arch-diagram--float-right. We just
       need to make a photo (vs an SVG) sit naturally in that slot. */
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 18px 48px rgba(26, 34, 51, 0.18);
    background: var(--cp-bg-alt);
    /* Modest top offset so the photo's top edge sits just below the
       eyebrow + h2 instead of awkwardly high. Was 100px which created
       a perceptible "extra padding" void above the photo on wide
       desktops, especially with this short-aspect (1400×933) image
       where paragraphs wrap full-width below it. */
    margin-top: 40px;
}
.about-story__figure img {
    display: block;
    width: 100%;
    height: auto;
}
/* On the widest viewports the photo sits noticeably above the lead
   paragraph; nudge it down so its top edge aligns more closely with
   the body of the story rather than the eyebrow/h2 zone. Scoped to
   xl+ so iPad-landscape (901-1199px) keeps the tighter 40px offset. */
@media (min-width: 1200px) {
    .about-story__figure {
        margin-top: 95px;
    }
}
/* Below the lg breakpoint (<992px) the float-around-text magazine
   pattern starts cramping the photo. Drop the float and let the
   image stack above the prose at full container width — matches
   the behavior we used to scope only to phones. */
@media (max-width: 991px) {
    .about-story .arch-diagram--float-right {
        float: none;
        width: 100%;
        max-width: 100%;
        margin: 0 0 24px;
    }
}
@media (max-width: 767px) {
    .about-story {
        padding: 64px 0 56px;
    }
}

/* --- Centered variants of .about-section ---------------------- */
.about-section .about-section--centered {
    text-align: center;
}
.about-section__meta--centered {
    justify-content: center;
}
.about-section .about-section--centered h2 {
    margin-left: auto;
    margin-right: auto;
}
.about-section .about-section--centered p {
    max-width: 640px;
    margin-left: auto;
    margin-right: auto;
}

/* --- Standalone "lead" label ---------------------------------- */
/* Used directly before an h2 (or sr-only h2) so the floating
   TOC picks up the label text via its eyebrow-first matching
   rule (regex catches `__label` substring). */
.about-section__label--lead,
.arch-section__label--lead {
    display: inline-block;
    margin-bottom: 14px;
}

/* sr-only utility — visually hidden, still in DOM for screen
   readers AND for the TOC scanner (which needs an h2 to anchor). */
.sr-only {
    position: absolute !important;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* --- Mission --------------------------------------------------- */
/* Mission as a display pull-quote: italic body, oversized serif
   quote glyphs (gray, decorative) anchoring top-left + bottom-right.
   Now wrapped in the standard Bootstrap .container parent (matches
   the gold-standard width treatment used by /index.php's Management
   Experience section), so the inner just centers itself with no
   custom width math. */
.about-mission__inner {
    margin: 0 auto;
}

.about-mission__quote {
    position: relative;
    max-width: 100%;
    margin: 6px auto 0;
    padding: 0 72px 8px;
    text-align: center;
}
.about-mission__quote::before,
.about-mission__quote::after {
    position: absolute;
    font-family: 'Georgia', 'Cambria', 'Times New Roman', serif;
    font-size: clamp(6rem, 11vw, 9.5rem);
    font-weight: 700;
    line-height: 1;
    color: var(--cp-text-muted);
    opacity: 0.32;
    pointer-events: none;
    user-select: none;
}
.about-mission__quote::before {
    content: "\201C";       /* left double quotation mark */
    top: -4px;
    left: 0;
}
.about-mission__quote::after {
    content: "\201D";       /* right double quotation mark */
    bottom: -16px;
    right: 0;
}
.about-mission__quote p {
    font-family: var(--font-heading);
    font-style: italic;
    font-size: clamp(1.4rem, 2.3vw, 1.85rem) !important;
    font-weight: 600;
    line-height: 1.5 !important;
    color: var(--cp-text-heading) !important;
    margin: 0 !important;
    /* Override .about-section--centered p max-width: 640px which would
       otherwise pin the wider mission quote to the narrow body width. */
    max-width: none !important;
}
@media (max-width: 640px) {
    .about-mission__quote {
        padding: 16px 36px 36px;
    }
    .about-mission__quote::before { top: 0; left: -4px; }
    .about-mission__quote::after { bottom: -28px; right: -4px; }
}

/* Mission supporting line — sits below the blockquote, smaller
   and not italic, reads as a quiet caption rather than competing
   with the display quote above. White-on-navy via the
   .about-section--navy parent rule. */
.about-mission__support {
    max-width: 720px !important;
    margin: 32px auto 0 !important;
    text-align: center;
    font-size: 1.05rem !important;
    line-height: 1.6 !important;
    font-style: normal;
}

/* --- Engineer-Operated, Not Ticket-Routed (.ops-grid / .ops-card)
   Three centered cards w/ pink circle icon at top. Designed to
   feel mature and operational — replaces what was the team grid. */
.ops-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
    max-width: 1080px;
    margin: 48px auto 0;
}
.ops-card {
    background: #ffffff;
    border-radius: 12px;
    padding: 36px 28px 32px;
    text-align: center;
    box-shadow: 0 8px 24px rgba(26, 34, 51, 0.08);
    transition: transform 0.25s ease, box-shadow 0.25s ease;
}
@media (hover: hover) {
    .ops-card:hover {
        transform: translateY(-4px);
        box-shadow: 0 16px 36px rgba(26, 34, 51, 0.14);
    }
}
.ops-card__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: rgba(222, 53, 128, 0.10);
    color: var(--cp-pink);
    font-size: 1.55rem;
    margin: 0 auto 18px;
}
.ops-card__title {
    font-family: var(--font-heading);
    font-size: 1.18rem;
    font-weight: 700;
    line-height: 1.3;
    margin: 0 0 12px;
    color: var(--cp-text-heading);
}
.ops-card p {
    font-size: 0.98rem !important;
    line-height: 1.6 !important;
    margin: 0 !important;
    color: var(--cp-text);
}
@media (max-width: 991px) {
    .ops-grid {
        grid-template-columns: 1fr;
        max-width: 640px;
    }
}

/* --- Mission envelope: section's actual bottom edge angled --- */
/* Clip-path on the whole section so the gray alt-bg tapers to
   a point at the bottom-center. Both diagonal edges slope from
   the section corners inward to that center point — same idea
   as the Squarespace "pointed" section divider. Content stays
   clear thanks to the extra padding-bottom soaking up the
   clipped area. */
.about-section--envelope-bottom {
    --envelope-depth: 80px;
    padding-top: 48px;
    /* No extra slack below blockquote — corners line up with the
       end of the blockquote so the angle starts right where the
       text does. */
    padding-bottom: var(--envelope-depth);
    clip-path: polygon(
        0 0,
        100% 0,
        100% calc(100% - var(--envelope-depth)),
        50% 100%,
        0 calc(100% - var(--envelope-depth))
    );
}
@media (max-width: 600px) {
    .about-section--envelope-bottom {
        --envelope-depth: 56px;
        padding-bottom: var(--envelope-depth);
    }
}

/* ============================================================
   TEAM SECTION (H-PATTERN) — PARKED, NOT CURRENTLY USED ON ANY PAGE
   ============================================================
   This entire block (.team-heading + .team-grid + .team-card +
   .team-card__photo + .team-card__caption + responsive breakpoints
   below) was used by /about-us before the 2026-04-29 spec rewrite
   that removed the team photo grid in favor of the
   "Engineer-Operated, Not Ticket-Routed" operational section.

   Kept intact so the design can be reused — e.g., a dedicated
   /team page, a careers page, or partial revival on /about-us.

   The H pattern places 5 figures in a 3-column grid with named
   areas: Salima top-left, Brent bottom-left, Petar centered as
   the "bar", Josip top-right, Emiliya bottom-right. Heading
   lives INSIDE the grid via grid-area: heading.

   Markup template:
     <div class="team-grid">
       <h2 class="team-heading">Meet the <strong>team</strong></h2>
       <figure class="team-card team-card--salima">
         <div class="team-card__photo">
           <img src="..." alt="..." loading="lazy">
           <figcaption class="team-card__caption">Name / Role</figcaption>
         </div>
       </figure>
       ... (brent, petar, josip, emiliya) ...
     </div>

   Note: caption lives INSIDE .team-card__photo (not as figure
   sibling) so it anchors to the photo box, not the figure's
   stretched grid cell — fixes Petar's caption hanging below
   the photo when his card spans 2 rows.

   Memory: ~/.claude/projects/-home-peconi/memory/newsite_team_grid_h_pattern.md
   ============================================================ */
/* --- Team grid (H pattern with named areas) ------------------- */
.team-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-areas:
        "salima heading josip"
        "salima petar   josip"
        "brent  petar   emiliya"
        "brent  .       emiliya";
    column-gap: 44px;
    row-gap: 20px;
    /* Section is full-bleed (no .container wrapper). Grid takes
       the section's full width minus 75px on each side, capped
       so it doesn't grow comically wide on ultrawide displays. */
    width: calc(100% - 150px);
    max-width: 1600px;
    margin: 56px auto 0;
}
.team-heading        { grid-area: heading; }
.team-card--salima   { grid-area: salima; }
.team-card--brent    { grid-area: brent; }
.team-card--petar    { grid-area: petar; }
.team-card--josip    { grid-area: josip; }
.team-card--emiliya  { grid-area: emiliya; }

/* Display header, sits in top center grid cell, pulled UP via
   translateY so it lands well above the tops of the side photos
   (matches the spacing of the original Squarespace layout). */
.about-section h2.team-heading {
    align-self: start;
    justify-self: center;
    font-size: clamp(2.8rem, 6.8vw, 5.2rem);
    line-height: 1.0;
    text-align: center;
    margin: 0;
    padding-top: 0;
    font-weight: 600;
    max-width: 100%;
    transform: translateY(-70px);
}
.about-section h2.team-heading strong {
    font-weight: 800;
}

/* Card = positioning context for the absolutely-positioned
   caption that sits OVER the bottom portion of the photo. */
.team-card {
    position: relative;
    margin: 0;
    background: transparent;
    box-shadow: none;
    border-radius: 0;
    overflow: visible;
    transition: transform 0.25s ease;
}
@media (hover: hover) {
    .team-card:hover {
        transform: translateY(-4px);
    }
}
.team-card__photo {
    position: relative;          /* positioning context for caption */
    width: 100%;
    /* 3:4 portrait — matches source images' native aspect. */
    aspect-ratio: 3 / 4;
    overflow: hidden;
    background: var(--cp-bg-alt);
    border-radius: 20px;
    box-shadow: 0 8px 24px rgba(26, 34, 51, 0.10);
    transition: box-shadow 0.25s ease;
}
@media (hover: hover) {
    .team-card:hover .team-card__photo {
        box-shadow: 0 18px 40px rgba(26, 34, 51, 0.18);
    }
}
.team-card__photo img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center top;
    transition: transform 0.6s ease;
}
@media (hover: hover) {
    .team-card:hover .team-card__photo img {
        transform: scale(1.03);
    }
}
/* Caption pill — absolutely positioned at the bottom of the
   photo, translucent white panel with rounded corners. Matches
   the original Squarespace overlay treatment. */
.team-card__caption {
    position: absolute;
    left: 24px;
    right: 24px;
    bottom: 16px;
    z-index: 2;
    text-align: center;
    padding: 16px 8px;
    font-size: 0.92rem;
    line-height: 1.35;
    font-weight: 600;
    color: var(--cp-text-heading);
    background: rgba(255, 255, 255, 0.92);
    border-radius: 12px;
    margin: 0;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    box-shadow: 0 4px 16px rgba(26, 34, 51, 0.12);
}

/* Tablet: H collapses to 2-col grid; heading spans full row,
   then 4 cards in 2x2, Petar centered on his own row. */
@media (max-width: 991px) {
    .team-grid {
        grid-template-columns: repeat(2, 1fr);
        grid-template-areas:
            "heading heading"
            "salima  josip"
            "petar   petar"
            "brent   emiliya";
        max-width: 680px;
        row-gap: 24px;
    }
    .team-card--petar {
        max-width: calc(50% - 12px);
        justify-self: center;
    }
    .about-section h2.team-heading {
        margin: 0 auto 8px;
    }
}
@media (max-width: 600px) {
    .team-grid {
        grid-template-columns: 1fr;
        grid-template-areas:
            "heading"
            "salima"
            "brent"
            "petar"
            "josip"
            "emiliya";
        max-width: 340px;
        row-gap: 22px;
    }
    .team-card--petar {
        max-width: none;
        justify-self: stretch;
    }
}

/* --- Navy variant of .about-section (used by /about-us
   Principles, mirroring the network-architecture --edge style) -- */
.about-section--navy {
    background: var(--cp-bg-footer);
    color: rgba(255, 255, 255, 0.82);
}
.about-section--navy h2,
.about-section--navy h3 {
    color: #ffffff;
}
.about-section--navy p {
    color: rgba(255, 255, 255, 0.78);
}
.about-section--navy .about-section__label {
    color: var(--cp-pink-light);
}
/* Mission blockquote on a navy section: body text becomes white
   (was --cp-text-heading dark), and the decorative serif quote
   glyphs go light-translucent so they read as subtle accents
   instead of disappearing into the navy. */
.about-section--navy .about-mission__quote p {
    color: #ffffff !important;
}
.about-section--navy .about-mission__quote::before,
.about-section--navy .about-mission__quote::after {
    color: rgba(255, 255, 255, 0.55);
    opacity: 0.6;
}

/* --- Principles grid ------------------------------------------ */
.principle-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
    max-width: 1080px;
    margin: 48px auto 0;
}
.principle-card {
    background: #ffffff;
    border-radius: 12px;
    padding: 32px 28px;
    box-shadow: 0 8px 24px rgba(26, 34, 51, 0.08);
    border-top: 3px solid var(--cp-pink);
    position: relative;
    transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.principle-card:hover {
    box-shadow: 0 14px 32px rgba(26, 34, 51, 0.12);
    transform: translateY(-1px);
}
.principle-card__num {
    display: inline-block;
    font-family: var(--font-heading);
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.18em;
    color: var(--cp-pink);
    margin-bottom: 10px;
}
.principle-card__title {
    font-family: var(--font-heading);
    font-size: 1.2rem;
    line-height: 1.35;
    margin: 0 0 12px;
    color: var(--cp-text-heading);
}
.principle-card p {
    font-size: 0.98rem !important;
    line-height: 1.6 !important;
    margin: 0 !important;
    color: var(--cp-text);
}
@media (max-width: 991px) {
    .principle-grid {
        grid-template-columns: 1fr;
        max-width: 640px;
    }
}

/* --- Staggered numbered chapters ------------------------------ */
/* PLACEHOLDER — NOT CURRENTLY USED ON ANY PAGE.
   Keep this design ready for future reuse (e.g. an FAQ page, or
   another long-form numbered narrative). The pattern: each
   section flips text-left / numeral-right, with an oversized
   hollow numeral acting as a graphic accent on the opposite side
   of the body copy. Markup template:

   <section class="stagger-section [stagger-section--alt] [stagger-section--flip]">
     <div class="container">
       <div class="stagger-section__grid">
         <aside class="stagger-section__numeral" aria-hidden="true">01</aside>
         <div class="stagger-section__copy">
           <span class="about-section__label about-section__label--lead">Section Label</span>
           <h2>Section heading</h2>
           <p>Body...</p>
         </div>
       </div>
     </div>
   </section>

   --flip swaps numeral side; --alt applies the gray bg variant.
   Source-order swap (numeral first vs copy first) controls which
   side the numeral sits on; --flip handles the column ordering. */
.stagger-section {
    padding: 96px 0;
    overflow: hidden;
}
.stagger-section--alt { background: var(--cp-bg-alt); }
.stagger-section__grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr);
    align-items: center;
    gap: 48px;
    max-width: 1180px;
    margin: 0 auto;
}
.stagger-section--flip .stagger-section__grid {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr);
}
.stagger-section__copy h2 {
    font-size: clamp(1.65rem, 2.8vw, 2.2rem);
    line-height: 1.3;
    margin-bottom: 20px;
}
.stagger-section__copy p {
    font-size: 1.05rem;
    line-height: 1.7;
    color: var(--cp-text);
    margin-bottom: 16px;
}
.stagger-section__copy p:last-child { margin-bottom: 0; }
.stagger-section__numeral {
    font-family: var(--font-heading);
    font-weight: 800;
    font-size: clamp(8rem, 18vw, 16rem);
    line-height: 0.85;
    letter-spacing: -0.04em;
    color: transparent;
    -webkit-text-stroke: 2px rgba(222, 53, 128, 0.35);
    text-stroke: 2px rgba(222, 53, 128, 0.35);
    text-align: center;
    user-select: none;
    pointer-events: none;
    /* Subtle gradient fill so it has presence on alt-bg too */
    background: linear-gradient(135deg, rgba(222, 53, 128, 0.10) 0%, rgba(222, 53, 128, 0.02) 100%);
    -webkit-background-clip: text;
    background-clip: text;
}
@media (max-width: 767px) {
    .stagger-section { padding: 64px 0; }
    .stagger-section__grid,
    .stagger-section--flip .stagger-section__grid {
        grid-template-columns: 1fr;
        gap: 24px;
    }
    /* On mobile, drop the giant numeral — the small numeric pill in
       .about-section__meta already carries the chapter index. */
    .stagger-section__numeral { display: none; }
}

/* --- Values grid ---------------------------------------------- */
.value-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 22px;
    max-width: 1080px;
    margin: 48px auto 0;
}
.value-card {
    background: #ffffff;
    border-radius: 10px;
    padding: 28px 24px;
    box-shadow: 0 6px 18px rgba(26, 34, 51, 0.06);
    border-left: 3px solid var(--cp-pink);
    transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.value-card:hover {
    box-shadow: 0 12px 28px rgba(26, 34, 51, 0.10);
    transform: translateY(-1px);
}
.value-card__title {
    font-family: var(--font-heading);
    font-size: 1.05rem;
    font-weight: 700;
    margin: 0 0 10px;
    color: var(--cp-text-heading);
    line-height: 1.3;
}
.value-card p {
    font-size: 0.94rem !important;
    line-height: 1.55 !important;
    margin: 0 !important;
    color: var(--cp-text);
}
@media (max-width: 991px) {
    .value-grid {
        grid-template-columns: repeat(2, 1fr);
        max-width: 720px;
    }
}
@media (max-width: 560px) {
    .value-grid { grid-template-columns: 1fr; max-width: 420px; }
}
