/* =====================================================================
   MOBILE LAYER — phones and small tablets (<= 768px).

   Approach: each section is kept EXACTLY as designed — its internal absolute
   layout is never touched — and the sections are stacked one after another,
   each scaled to the phone's width, like a series of pictures. The stacking
   itself is done by js/mobile-sections.js, which measures the canvas band
   each section occupies and gives it a window of the right height.

   This file only does what CSS must: stop the page scrolling sideways, let
   the canvas be a plain column, and keep the desktop scale rules from
   fighting the stack. No colour, font-family, logo or asset is touched.
   ===================================================================== */

@media (max-width: 768px) {

  /* clip, not hidden: overflow-x:hidden turns these into scroll containers,
     which silently disables position:sticky for everything inside (it is what
     stopped the insights deck from stacking). clip crops without that. */
  html, body { overflow-x: clip; max-width: 100%; }

  /* Long words must break rather than run off the card.
     Everything below the hero is CMS copy, so its length is whatever an editor
     types: a product code, a pasted URL or an unspaced compound has no break
     opportunity, and the line simply kept going. Because the column is clipped
     (above) the overspill was not even scrollable — it was invisible. Measured
     before this rule: .mv-card-title ran 1576px past a 375px viewport and
     .mv-hero-title 1248px.

     Deliberately scoped to the element rather than to a container: the home
     page keeps its #stage canvas, while js/mobile-view.js rebuilds the
     subpages as body.mv-on > main.mv, so a #stage-based selector misses half
     the site. `anywhere` rather than `break-all` so only a word that genuinely
     cannot fit is broken — ordinary prose wraps exactly as before. */
  h1, h2, h3, h4, h5, h6,
  p, li, a, td, th, dd, dt, blockquote, figcaption, label, span {
    overflow-wrap: anywhere;
    word-break: normal;
  }
  body {
    height: auto !important;
    /* same value base.css already sets on html,body — needed because
       #stage no longer covers the viewport once it is a plain column */
    background: #0a1420;
  }

  /* the canvas becomes a simple vertical column of section windows */
  #stage {
    position: relative !important;
    width: 100% !important;
    max-width: 100%;
    height: auto !important;
    min-height: 0 !important;
    transform: none !important;
    margin-left: 0 !important;
    overflow: hidden !important;
    background-size: 100% 100% !important;
  }

  /* one window per section, sized by mobile-sections.js to the scaled
     height of the band that section occupies on the canvas */
  .m-sec-window {
    position: relative;
    width: 100%;
    overflow: hidden;
  }

  /* the full-canvas decorative glow layers span the whole page, so as a
     stacked band they would be one enormous empty picture */
  .sec-decor_under, .sec-decor_mid, .sec-decor_over { display: none !important; }

  /* Sections keep their designed height on purpose: several have children
     that bleed outside them (the hero photo card sits at top:-347px) and are
     clipped by the section's own overflow. Collapsing the height to auto
     would un-clip that bleed and throw the measured band right off. */
  #stage > [class*="sec-"]:not(.sec-hero) { transform: none; }

  /* sticky-header.js stands down on mobile, so this host is never built —
     hidden defensively in case a cached copy of the old script runs */
  #fixedHeaderHost { display: none !important; }

  /* forms should never overflow the viewport */
  input, textarea, select, button { max-width: 100%; box-sizing: border-box; }

  /* ==================================================================
     MOBILE VIEW — a real phone layout built by js/mobile-view.js from the
     page's own content. Palette and type families are the site's own:
     navy #0a1420, red #80121d, the light page tint #eef5fa, white,
     Space Grotesk for headings and Inter for copy.
     ================================================================== */
  .mv { display: block; }
  .mv * { box-sizing: border-box; }

  .mv-sec { padding: 40px 20px; }
  .mv-sec--light { background: #eef5fa; }

  /* the Services page's own silver band, from services-page.css, so the cards
     sit on the same surface they do on desktop */
  .mv-sec--services {
    background-color: #d9e4eb;
    background-image: linear-gradient(174.59deg,
      rgb(217, 228, 235) 23.085%,
      rgb(78, 99, 128) 113.18%);
  }
  /* The Solutions band. solutions.css draws .sol-card as a 239.47deg diagonal
     sweep - dark, light, dark - which reads well across a WIDE desktop card.
     Rotated onto a 375px-wide, 790px-tall phone box the same angle compresses
     the first dark stop into a bar down the left-hand edge, with a hard enough
     shoulder to read as a rule drawn on the page: the line flagged in review.
     Same three colours, redistributed as a radial so the panel is light in the
     middle and falls off gently to the corners - which is what the diagonal
     achieves on desktop, and what the artwork sitting on it expects. */
  .mv-sec--dark {
    /* Stretched to fill, not vignetted. The desktop diagonal and the radial
       that replaced it both put their falloff INSIDE a 375px viewport, which
       darkened the left and right edges - measured at mid-band, the left edge
       read 151 against 183 in the middle. A vertical gradient has no
       horizontal variation at all, so the wash covers the full width evenly at
       every height.

       The stops keep .sol-card's own dark - light - dark structure and its two
       end colours, only reoriented: dark behind the "OUR SOLUTIONS" heading at
       the top, light through the middle where the render sits, dark again
       under the white heading and copy in the lower half. All three of those
       need it - the type over this band is white, and both dark runs exist so
       it clears 4.5:1. */
    background: linear-gradient(180deg,
      rgb(26, 43, 66)     0%,
      rgb(104, 121, 145) 20%,
      rgb(205, 213, 220) 42%,
      rgb(150, 166, 185) 54%,
      rgb(96, 116, 142)  63%,
      rgb(60, 81, 110)   74%,
      rgb(22, 39, 62)   100%);
    position: relative;
  }
  /* No fade into the sections either side. One was tried and removed: the
     "OUR SOLUTIONS" heading sits only ~27px below the band's top edge, so a
     top fade to the page tint washed the ground out from under it and took
     white-on-background down to 3.07:1. The band opens and closes dark, the
     way .sol-card does on desktop, and the heading has something to sit on. */

  .mv-kicker {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 26px; font-weight: 700; letter-spacing: .5px;
    text-transform: uppercase; color: #80121d; margin-bottom: 12px;
  }
  /* The logo is an SVG with no intrinsic size, so the browser fell back to
     the spec default 300x150: height:auto gave 150px and squashed a 204x88
     mark into a 190x150 box. aspect-ratio states the real shape, and it is
     smaller now so it sits with the copy rather than shouting over it. */
  .mv-wordmark { width: 150px; aspect-ratio: 204 / 88; height: auto;
                 object-fit: contain; display: block; margin-bottom: 18px; }

  .mv-h2 {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 26px; line-height: 1.15; font-weight: 700;
    text-transform: uppercase; color: #0d2f52; margin-bottom: 12px;
  }
  .mv-h2--light  { color: #ffffff; }
  .mv-h2--center { text-align: center; }

  .mv-copy {
    font-family: 'Inter', sans-serif;
    font-size: 15px; line-height: 1.6; color: #333333; margin-bottom: 18px;
  }
  .mv-copy--light { color: rgba(255,255,255,.86); }

  /* The site's button: a white block with an Inter label in #80121d and a
     solid red square carrying the arrow. Values lifted from .svc-cta /
     .svc-cta-label / .svc-cta-icon-bg in services.css. */
  /* Sized down from 17.5px/54px on client review: at the old size "Explore
     Solutions" was 282px of a 375px viewport (75%) and every "see more" read
     as oversized. Label, height, padding and the arrow square are reduced
     together so the proportions of the desktop original are kept - shrinking
     the font alone would have left the red square looking bolted on. */
  /* Proportioned from the desktop buttons rather than guessed, so the phone
     shows the same control at a smaller size. Measured on desktop, the three
     variants (.hero-cta, .svc-cta, .hero-header-contact) agree closely:

         box height    3.45 - 3.54 x the label size
         arrow square  0.66 - 0.71 x the box height, 2.55 - 2.60 x the label
         inset right   8 - 10px of button BEHIND the arrow square

     The phone had none of that last one - the square sat hard against the
     right edge and stood 0.83 of the box height - which is what read as
     cropped. At a 15px label the desktop ratios give 52px tall, a 39x35
     square, and a 9px inset around it. */
  .mv-btn {
    display: inline-flex; align-items: center; text-decoration: none;
    background: #ffffff; color: #80121d;
    font-family:'Inter',sans-serif;
    font-weight:500; font-size: 15px; line-height: 1;
    text-transform: uppercase; letter-spacing: .4px;
    padding: 0 9px 0 20px;        /* the 9px is the inset the desktop has */
    min-height: 52px;             /* 3.47 x the 15px label */
    box-shadow: 0 2px 10px rgba(0,0,0,.12);
  }
  .mv-btn-t { display: inline-block; }
  .mv-btn-i {
    display: inline-flex; align-items: center; justify-content: center;
    width: 39px; height: 35px;    /* 2.60 x label, 0.67 x box height */
    margin-left: 14px; flex: 0 0 auto;
    background: #80121d;
  }
  .mv-btn-i svg { transform: rotate(-45deg); }   /* same as .btn-kite on desktop */
  .mv-btn--light { background: #ffffff; color: #80121d; }
  /* mirrors .dc-btn--red: maroon body, WHITE square, maroon kite. The
     shared ARROW glyph carries fill="white" as a presentation attribute,
     which any CSS rule outranks, so restating the fill here is enough. */
  .mv-btn--red { background: #80121d; color: #ffffff; }
  .mv-btn--red .mv-btn-i { background: #ffffff; }
  .mv-btn--red .mv-btn-i svg path { fill: #80121d; }

  /* ---- hero ---- */
  .mv-hero {
    position: relative;
    padding: 34px 20px 44px;
    background: #0a1420 center/cover no-repeat;
    text-align: center;
    display: flex; flex-direction: column; align-items: center; gap: 14px;
  }
  .mv-hero::after {                       /* keeps the copy legible on the photo */
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(10,20,32,.55), rgba(10,20,32,.75));
  }
  .mv-hero > * { position: relative; z-index: 1; }
  /* Inner-page banner: the page's own render fills it and the copy sits over
     the artwork, the way the desktop hero composes — rather than an image
     with the text stacked underneath it. The navy shows through wherever the
     render does not reach, and the scrim inherited from .mv-hero keeps the
     copy legible over the bright parts of the artwork. */
  .mv-hero--inner {
    background-color: #0a1420;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    min-height: 400px;
    justify-content: center;
    padding: 54px 20px 48px;
  }

  .mv-hero-art img { width: 190px; height: auto; display: block; }
  .mv-hero-title {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 30px; line-height: 1.1; font-weight: 700;
    text-transform: uppercase; color: #ffffff;
  }
  .mv-hero-sub {
    font-family: 'Inter', sans-serif;
    font-size: 14px; line-height: 1.55; color: rgba(255,255,255,.85);
  }

  /* let the hero artwork read — it is the page's product shot, so give it
     room rather than cropping it to a thin band */
  .mv-hero--inner { min-height: 460px; background-size: contain; }
  /* renders are shown whole; photographs fill the hero instead */
  .mv-hero--photo { background-size: cover; background-position: center; }

  /* No top fade on the banner itself: it began at full opacity, which simply
     hid the top of the picture, and #mNav::before already carries the
     darkening the logo needs. Two overlapping fades also made the join
     between them readable as a band. */

  /* The maroon statement band between the solutions and the scope. Short by
     design — it is one line of type on the page's own surface. Background is
     #stage's gradient and the type keeps its maroon-to-navy gradient fill,
     both from data-center-page.css. */
  .mv-statement {
    padding: 30px 20px;
    background-image: linear-gradient(179.78deg,
      rgb(217, 228, 235) 20.393%,
      rgb(78, 99, 128) 99.948%);
  }
  .mv-statement p {
    margin: 0;
    font-family: 'Inter', sans-serif;
    font-weight: 700;
    font-size: 21px;
    line-height: 1.15;
    text-align: center;
    text-transform: uppercase;
    background-image: linear-gradient(to right, #80121d, #213a5d);
    background-clip: text;
    -webkit-background-clip: text;
    color: transparent;
  }

  /* the solutions band and its cards, from data-center-page.css: the maroon
     band (.dc-band) behind, and the cards on .cd-bg's off-white rather than
     flat white */
  /* Reworked to the approved desktop design. The phone still had the older
     maroon band with solid off-white cards; the desktop was rebuilt as a
     steel-to-slate band carrying translucent "glass" cards with a cyan glow
     and a cyan line-glyph. Values below are taken from the desktop rules
     (.dc-band behind, .cd-bg on the card) rather than re-invented, so the two
     read as the same design at any width. */
  /* Both solution bands are the same design now — Oil & Gas was redesigned
     on desktop to match Data Center, so keeping the old steel-blue band here
     would make this page differ from its OWN desktop. Same reasoning as
     before, same conclusion the other way round. */
  .mv-sec--ogband,
  .mv-sec--dcband {
    background-image: linear-gradient(179.78deg,
      rgb(217, 228, 235) 20.393%,
      rgb(78, 99, 128) 99.948%);
  }
  /* .cd-bg: translucent fill, 12px radius, cyan bloom + a hairline inset
     border. The bloom is what makes the card read as "techy" rather than as
     a plain panel, so it is kept at full strength. */
  .mv-sec--ogband .mv-card--sys,
  .mv-sec--dcband .mv-card--sys {
    background: linear-gradient(to left,
      rgba(127, 144, 163, .12), rgba(0, 49, 89, .12));
    background-color: rgba(10, 28, 48, .34);
    border: 0;
    border-radius: 12px;
    box-shadow: 0 0 22px rgba(110, 189, 244, .55),
                inset 0 0 0 1px rgba(255, 255, 255, .20);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
  }

  /* the solutions heading sits on the page's light band above the coloured
     one, "OUR" in red over the name in navy, as on desktop */
  .mv-solhead {
    padding: 34px 20px 26px;
    background-image: linear-gradient(179.78deg,
      rgb(217, 228, 235) 20.393%,
      rgb(233, 239, 244) 99.948%);
  }
  .mv-solh { margin: 0; font-family: 'Space Grotesk', sans-serif; font-weight: 700;
             text-transform: uppercase; line-height: 1.02; }
  .mv-solh-a { display: block; font-size: 22px; color: #80121d; }
  .mv-solh-b { display: block; font-size: 34px; color: #0d2f52; }

  /* Oil & Gas runs the same section in steel blue with glass cards, not the
     maroon band — values from oil-and-gas-page.css (.sol-tint over #stage,
     .cd-bg at rgba(252,252,252,.2), white type, white icon discs) */
  /* .sol-tint is 38% over the page gradient, which is dark where this section
     sits on desktop. Stacking it over the gradient's light end here made the
     band pale and the glass cards read as solid white, so the tint's own
     colours are used at full strength instead. */
  /* The solution bands meet the light heading strip above them and the light
     statement below them at a hard tonal jump - #e9eff4 straight into
     #21395d - which read as a rule across the page, the same fault as the
     header. Each band now begins and ends in the colour of the section it
     meets, over 120px, so the change is gradual. Values are the neighbours'
     own: .mv-solhead ends rgb(233,239,244); .mv-statement opens
     rgb(217,228,235). The Data Center band already OPENS light, so only its
     bottom edge needs one. */
  .mv-sec--ogband, .mv-sec--dcband { position: relative; }
  .mv-sec--ogband::after,
  .mv-sec--dcband::after {
    content: '';
    position: absolute; left: 0; right: 0; height: 120px;
    pointer-events: none; z-index: 0;
  }
  .mv-sec--ogband::after,
  .mv-sec--dcband::after {
    bottom: 0;
    background: linear-gradient(to top, rgb(217, 228, 235) 0%, rgba(217, 228, 235, 0) 100%);
  }
  /* keep each band's own content above its fades */
  .mv-sec--ogband > *, .mv-sec--dcband > * { position: relative; z-index: 1; }

  /* the plain card paints its body white, which sat on top of the glass and
     hid the light copy — the body stays transparent on both bands */
  .mv-sec--dcband .mv-card--sys .mv-card-body,
  .mv-sec--ogband .mv-card--sys .mv-card-body { background: transparent; }

  /* .mv-card--sys is in the selector so this outranks the plain-card colour.
     Title white and list rgba(203,227,247,.9), both from the desktop card. */
  .mv-sec--dcband .mv-card--sys .mv-card-title,
  .mv-sec--ogband .mv-card--sys .mv-card-title { color: #ffffff; }
  .mv-sec--dcband .mv-card--sys .mv-list li,
  .mv-sec--ogband .mv-card--sys .mv-list li { color: rgba(203, 227, 247, .9); }

  /* system cards: the pictogram sits on the navy disc, as on desktop */
  .mv-sys-badge {
    width: 64px; height: 64px; border-radius: 50%;
    background: #1e3a5f;
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 6px; flex: 0 0 auto;
    /* the builder may place a zoomed sprite inside and crop it the way the
       desktop card does, which needs a positioned, clipping box */
    position: relative; overflow: hidden;
  }
  .mv-sys-badge img { width: 34px; height: 34px; object-fit: contain; display: block; }

  /* The line-glyph sits INSIDE the disc, not across it. Two things were wrong:
     this block used to be declared above .mv-sys-badge, and with equal
     specificity the later rule won - so the variant never applied at all - and
     the glyph was sized at 100% of a 64px badge, which put its strokes hard
     against the circle's edge. Sized to match the bitmap pictogram it sits
     beside (34px in a 64px disc, ~53%), so both read the same. */
  .mv-sys-badge--glyph svg {
    width: 53%; height: 53%; display: block;
    color: #7fd8ff; stroke: #7fd8ff; fill: none;
  }
  .mv-list { margin: 0; padding-left: 18px; list-style: disc; }
  .mv-list li {
    font-family: 'Inter', sans-serif; font-size: 14px; line-height: 1.7;
    color: #333333;
  }

  /* Scope of service — the desktop band and glass tiles, taken from
     data-center-page.css rather than approximated: the same radial artwork
     behind, and .sc-panel's translucent fill on the tiles. */
  .mv-sec--scope {
    background-color: #0e1635;
    background-image: url("data:image/svg+xml;utf8,<svg viewBox='0 0 1316 613' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><rect x='0' y='0' height='100%' width='100%' fill='url(%23grad)' opacity='1'/><defs><radialGradient id='grad' gradientUnits='userSpaceOnUse' cx='0' cy='0' r='10' gradientTransform='matrix(84.259 41.8 -89.738 211.07 110.85 79.097)'><stop stop-color='rgba(14,22,53,1)' offset='0.26927'/><stop stop-color='rgba(11,37,76,1)' offset='0.35147'/><stop stop-color='rgba(8,52,100,1)' offset='0.43366'/><stop stop-color='rgba(2,82,146,1)' offset='0.59805'/><stop stop-color='rgba(6,67,119,1)' offset='0.69854'/><stop stop-color='rgba(11,52,91,1)' offset='0.79902'/><stop stop-color='rgba(15,37,63,1)' offset='0.89951'/><stop stop-color='rgba(19,23,36,1)' offset='1'/></radialGradient></defs></svg>");
    background-size: 100% 100%;
    background-repeat: no-repeat;
  }

  .mv-scope { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .mv-scope-item {
    background-image: linear-gradient(to left, rgba(127,144,163,.12), rgba(0,49,89,.12));
    border: 1px solid rgba(255,255,255,.10);
    border-radius: 12px;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    padding: 18px 12px;
    display: flex; flex-direction: column; align-items: center; gap: 12px;
    text-align: center;
  }
  .mv-scope-item img { width: 56px; height: auto; }
  .mv-scope-item p {
    font-family: 'Space Grotesk', sans-serif; font-weight: 500;
    font-size: 13px; line-height: 1.2;
    text-transform: uppercase; color: #ffffff; margin: 0;
  }

  /* the glass panel the desktop hero puts its copy and CTA in */
  .mv-hero-panel {
    width: 100%;
    background: rgba(255, 255, 255, .07);
    border: 1px solid rgba(255, 255, 255, .12);
    border-radius: 14px;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    padding: 18px 16px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    text-align: center;
  }
  .mv-hero-panel .mv-hero-sub { margin: 0; }

  /* ---- stat cards ---- */
  .mv-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 22px 0 16px; }
  .mv-stat {
    background: #ffffff; border-radius: 12px; padding: 18px 14px;
    box-shadow: 0 6px 18px rgba(13,47,82,.08);
    display: flex; flex-direction: column; gap: 6px;
  }
  .mv-stat-n {
    font-family: 'Sora', 'Space Grotesk', sans-serif; font-weight: 700; font-size: 30px; line-height: 1;
    background: linear-gradient(180deg, #003159, #6bbcff);
    -webkit-background-clip: text; background-clip: text; color: transparent;
  }
  .mv-stat-l { font-family: 'Inter', sans-serif; font-size: 12px; line-height: 1.35; color: #213a5d; }

  /* ---- image cards ---- */
  /* inner pages: derived layout, so give the pieces sane rhythm */
  .mv-title-dark { color: #0d2f52; margin: 6px 0 2px; }
  .mv-sec > .mv-btn { margin: 4px 0 18px; }
  .mv-sec > .mv-shot { margin-bottom: 16px; }

  .mv-shots { display: grid; gap: 12px; }
  .mv-shot { margin: 0; border-radius: 12px; overflow: hidden; background: #0a1420; }
  /* video as well as img: two of the about_stats renders are <video> now
     (they were animated WebPs — see index.html). Same box, same crop. */
  .mv-shot img, .mv-shot video { width: 100%; height: 190px; object-fit: cover; display: block; }

  /* ---- About: the vision / mission pair and the "learn more" line --------
     Both are static labels on the desktop page, not controls, so they are
     reproduced as text with the same emphasis: "vision" carried at full
     strength, "mission" lighter and at 72% (values from .g2-vision /
     .g2-mission on about.html). */
  .mv-vm { display: flex; align-items: baseline; gap: 14px; margin-bottom: 10px; }
  .mv-vm-a, .mv-vm-b {
    font-family: 'Space Grotesk', sans-serif;
    font-size: 20px; line-height: 1.1; text-transform: lowercase;
  }
  .mv-vm-a { color: rgb(33, 58, 93); font-weight: 400; }
  .mv-vm-b { color: rgba(33, 58, 93, .72); font-weight: 200; }
  .mv-more {
    font-family: 'Inter', sans-serif;
    font-size: 15px; font-weight: 700; color: rgb(0, 49, 89);
    margin-top: 4px;
  }

  /* ---- logo strip ---- */
  /* One scrolling line, exactly like the desktop band: same panel colour
     (rgba(31,72,119,.2) from trusted.css) and the same continuous drift.
     The track is duplicated in mobile-view.js so the loop never shows a gap. */
  .mv-logos {
    background: rgba(31, 72, 119, 0.2);
    border-radius: 28px;
    padding: 20px 0;
    overflow: hidden;
  }
  .mv-logos-track {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 34px;
    width: max-content;
    animation: mv-marquee 22s linear infinite;
  }
  .mv-logos-track img {
    height: 30px; width: auto; flex: 0 0 auto; max-width: none; object-fit: contain;
  }
  @keyframes mv-marquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }   /* one full copy of the set */
  }
  @media (prefers-reduced-motion: reduce) {
    .mv-logos-track { animation: none; }
  }

  /* ---- content cards ---- */
  /* the card carries the site's own gradient, not a flat white panel —
     values lifted from .svc-card-gradient in services.css */
  .mv-card {
    /* the scrim is layered over the gradient across the WHOLE card, so the
       card reads as one surface — applying it to the body alone left a pale
       strip of raw gradient showing beneath it */
    background-image:
      linear-gradient(rgba(10, 20, 32, .55), rgba(10, 20, 32, .55)),
      linear-gradient(
        244.96deg,
        rgb(250, 243, 243) 1.8888%,
        rgb(255, 255, 255) 35.525%,
        rgb(128, 18, 29) 99.035%
      );
    border-radius: 22px; overflow: hidden;
    box-shadow: 0 8px 22px rgba(13,47,82,.10);
    margin-bottom: 16px;
  }
  /* the body sits over the deep end of the gradient, so its copy is white */
  .mv-card .mv-card-title  { color: #ffffff; }
  .mv-card .mv-card-copy   { color: rgba(255,255,255,.92); }
  .mv-card .mv-card-kicker { color: rgba(255,255,255,.88); }

  .mv-card--dark { background-image: none; background: #11203a; }

  /* ---- insights: navy band + a deck that stacks as you scroll ---------
     The desktop pins the canvas and climbs the cards on scroll. Here the
     same read is achieved with position:sticky — each card parks under the
     one before it with a 12px step, the deck offset the desktop uses — so
     the browser drives it on the compositor and there is no scroll handler
     to jitter on a phone. */
  .mv-sec--insights { background: #0a1420; }
  .mv-band { width: 100%; height: auto; display: block; border-radius: 12px; margin-bottom: 18px; }

  .mv-stack { display: flex; flex-direction: column; gap: 18px; margin-bottom: 22px; }
  .mv-stack-card {
    position: sticky;
    top: calc(72px + var(--i, 0) * 12px);   /* clears the fixed bar, then decks */
    margin-bottom: 0;
  }
  @media (prefers-reduced-motion: reduce) {
    .mv-stack-card { position: static; }
  }

  /* the news/insights cards read as plain white cards, no gradient */
  .mv-card--plain { background-image: none; background: #ffffff; }
  .mv-card--plain .mv-card-body   { background: #ffffff; }
  .mv-card--plain .mv-card-title  { color: #0d2f52; }
  .mv-card--plain .mv-card-copy   { color: #333333; }
  .mv-card--plain .mv-card-kicker { color: #80121d; }

  /* Solutions panel: no card. The render sits straight on the band and is
     shown whole (contain, not cover) — cropping it to a card was cutting the
     data centre off. Copy carries a soft shade so it stays legible wherever
     the band is light. */
  .mv-solution { background: none; box-shadow: none; margin: 0; }
  .mv-solution .mv-card-img {
    width: 100%; height: auto; max-height: 320px;
    object-fit: contain; display: block; background: none;
  }
  .mv-solution .mv-card-body { padding: 18px 0 0; background: none; }
  .mv-solution .mv-card-title {
    color: #ffffff; font-size: 22px;
    text-shadow: 0 1px 10px rgba(10, 20, 32, .55);
  }
  .mv-solution .mv-card-copy {
    color: rgba(255, 255, 255, .94);
    text-shadow: 0 1px 8px rgba(10, 20, 32, .5);
  }

  /* solutions: the desktop tab pair, stacked for a phone */
  .mv-tabs { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
  .mv-tab {
    width: 100%; text-align: center; cursor: pointer;
    font-family: 'Space Grotesk', sans-serif; font-size: 15px; font-weight: 700;
    letter-spacing: .4px; text-transform: uppercase;
    padding: 14px 16px; border: 0; border-radius: 8px;
    /* The label was rgba(255,255,255,.75). Fading the TEXT to signal
       "not selected" put it at 3.6:1 against the band, under the 4.5:1 a
       15px label needs. The tab already reads as secondary through its
       background - translucent navy against the selected tab's solid white -
       so the type itself does not have to be faded to say so. */
    background: rgba(31, 72, 119, 0.28); color: #ffffff;
    transition: background .25s ease, color .25s ease;
  }
  .mv-tab.is-on { background: #ffffff; color: #80121d; }

  /* services: the two variants on a track that glides between them.
     Swapping display was an abrupt cut — this moves, so it reads as a slide. */
  .mv-slider { position: relative; overflow: hidden; }
  .mv-slider-track {
    display: flex;
    transition: transform .75s cubic-bezier(.33, 1, .68, 1);   /* calm ease-out */
    will-change: transform;
  }
  .mv-slider-track.is-dragging { transition: none; }           /* follow the finger */
  .mv-slider .mv-card { flex: 0 0 100%; margin-bottom: 0; }

  /* ---- clickable service cards --------------------------------------
     The two OUR SERVICES tiles look tappable and were not: several render no
     CTA at all, so there was no route from the home page to the services
     page. .mv-card-hit is a stretched link covering the card. It is placed
     under any real control inside the card (z-index 0 against the CTA's 1),
     so the CTA still wins its own taps, and text stays selectable because the
     overlay only takes pointer events, not the text itself. */
  .mv-card--link { position: relative; }
  .mv-card-hit {
    position: absolute; inset: 0; z-index: 0;
    border-radius: inherit;
    font-size: 0; color: transparent; text-decoration: none;
    -webkit-tap-highlight-color: rgba(255,255,255,.12);
  }
  .mv-card--link .mv-card-body { position: relative; z-index: 1; pointer-events: none; }
  /* give the real controls their taps back */
  .mv-card--link .mv-card-body a,
  .mv-card--link .mv-card-body button { pointer-events: auto; position: relative; z-index: 2; }
  .mv-card-hit:focus-visible { outline: 3px solid #7fd8ff; outline-offset: 2px; }
  @media (prefers-reduced-motion: reduce) {
    .mv-slider-track { transition: none; }
  }
  .mv-dots { display: flex; justify-content: center; gap: 0; margin-top: 6px; }
  /* The painted dot stays 8px in the same spot: padding grows only the hit
     area, and background-clip:content-box keeps the colour off the padding.
     That takes the target to 24x24 without changing a single painted pixel
     of the dot itself; the dots sit 4px further apart. */
  .mv-dot {
    width: 8px; height: 8px; border-radius: 50%; border: 0;
    padding: 8px; background-clip: content-box; box-sizing: content-box;
    background-color: rgba(13,47,82,.25); cursor: pointer;
  }
  .mv-dot.is-on { background-color: #80121d; }
  .mv-card-img { width: 100%; height: 200px; object-fit: cover; display: block; }

  /* whole-card link: it must not look or behave like a text link */
  .mv-card--link { display: block; text-decoration: none; color: inherit; }

  /* Some of the service artwork carries a watermark baked into its left and
     right edges ("2023-2024", "X_CHAOQUN"). A slight scale pushes those past
     the card's clipped bounds without touching the asset itself. Scoped to
     that section — the project and news photos are clean, and zooming them
     would just crop the subject out. */
  .mv-sec--services .mv-card--link .mv-card-img { transform: scale(1.3); transform-origin: center; }
  .mv-card-body { padding: 18px 16px 20px; display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
  /* the scrim now lives on the card itself (see .mv-card above) so the whole
     surface is even; the body just sits on it */
  .mv-card-kicker {
    font-family: 'Inter', sans-serif; font-size: 11px; letter-spacing: 1.2px;
    text-transform: uppercase; color: #80121d;
  }
  .mv-card--dark .mv-card-kicker { color: #6bbcff; }
  .mv-card-title {
    font-family: 'Space Grotesk', sans-serif; font-size: 20px; line-height: 1.2;
    font-weight: 700; text-transform: uppercase; color: #0d2f52;
  }
  .mv-card--dark .mv-card-title { color: #ffffff; }
  .mv-card-copy { font-family: 'Inter', sans-serif; font-size: 14px; line-height: 1.6; color: #444444; }
  .mv-card--dark .mv-card-copy { color: rgba(255,255,255,.82); }

  /* ---- certificate deck: swipeable row ---- */
  .mv-deck {
    display: flex; gap: 12px; overflow-x: auto; padding-bottom: 6px; margin-bottom: 18px;
    scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
  }
  .mv-deck img {
    width: 210px; flex: 0 0 auto; border-radius: 10px; scroll-snap-align: start;
    background: #ffffff; box-shadow: 0 6px 18px rgba(13,47,82,.10);
  }

  /* =================================================================
     PROJECTS — filter chips over a one-up card grid
     ================================================================= */
  /* the desktop tab bar is a single row of four; on a phone it scrolls
     sideways rather than wrapping into a block of buttons */
  /* The desktop filter is one joined bar: a translucent panel with a hairline
     border, 1px dividers between the segments and a maroon block behind the
     active one (.pj-tabbar / .pj-tab-divider / .pj-tab-highlight). These were
     detached rounded pills on a scrolling row, which also pushed the fourth
     category off screen. Same element now — square, joined, bordered, maroon
     active — laid out two-by-two so all four are visible at once the way they
     are on desktop. The desktop bar is white-on-navy; this sits on the light
     mobile section, so the same hairlines and text are drawn in the page navy
     instead of white. */
  /* Colours sampled from the rendered desktop bar so the two match exactly:
     an unselected segment composites to rgb(141,168,191), the active one is
     #80121d, and the frame, dividers and type are white. Taking the composited
     value rather than desktop's rgba(255,255,255,.41) means it looks the same
     here even though this section is light rather than navy. */
  /* One row, exactly like desktop, scrolling sideways because four labels
     this long will not fit across a phone. The frame stays put at the width
     of the section and the segments scroll inside it. */
  .mv-chips {
    display: flex; flex-wrap: nowrap;
    overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
    margin-bottom: 20px;
    border: 1px solid #ffffff;
    background: rgb(141, 168, 191);
  }
  .mv-chips::-webkit-scrollbar { display: none; }
  .mv-chip {
    flex: 0 0 auto;
    border: 0; border-radius: 0; cursor: pointer;
    border-right: 1px solid rgba(255, 255, 255, .6);
    padding: 13px 18px; min-height: 46px;
    font-family: 'Space Grotesk', sans-serif; font-size: 13px; font-weight: 400;
    letter-spacing: .3px; text-transform: uppercase;
    white-space: nowrap; text-align: center; line-height: 1.25;
    background: transparent; color: #ffffff;
    transition: background .18s ease, color .18s ease;
  }
  .mv-chip:last-child { border-right: 0; }
  .mv-chip.is-on { background: #80121d; color: #ffffff; }

  .mv-grid { display: grid; gap: 16px; margin-bottom: 20px; }
  .mv-grid .mv-card { margin-bottom: 0; }

  /* the card's own "see more", in the site's red with its arrow */
  /* the projects "load more" button - distinct from .mv-more, which labels
     the see-more span inside each card */
  .mv-loadmore { margin-top: 4px; }

  .mv-more {
    display: inline-flex; align-items: center; gap: 8px;
    font-family:'Inter',sans-serif; font-size: 14px;
    text-transform: uppercase; letter-spacing: .5px; color: #80121d; font-weight:500;}
  .mv-more svg { transform: rotate(-45deg); }
  .mv-more svg path { fill: #80121d; }

  /* =================================================================
     NEWS — the page's own gradient panel behind the article cards
     (values from .nw-panel in news-page.css)
     ================================================================= */
  .mv-sec--news {
    background-image: linear-gradient(207.78deg,
      rgb(33, 58, 93) 5.5593%,
      rgb(110, 189, 244) 37.903%,
      rgb(154, 183, 215) 63.594%,
      rgb(78, 95, 122) 99.554%);
  }
  .mv-sec--news .mv-h2 { margin-bottom: 20px; }

  /* =================================================================
     ABOUT — the wordmark under the title, and the team portraits
     ================================================================= */
  .mv-hero-mark { width: 200px; height: auto; display: block; margin: 6px 0 16px; }
  /* the three portraits overlap on desktop; here they read as a row that
     scrolls, so no face is cropped to fit */
  .mv-team {
    display: flex; gap: 12px; overflow-x: auto; margin: 4px 0 18px;
    padding-bottom: 6px; -webkit-overflow-scrolling: touch;
    scroll-snap-type: x mandatory;
  }
  .mv-portrait { margin: 0; flex: 0 0 auto; scroll-snap-align: start; }
  .mv-portrait img {
    width: 180px; height: 230px; object-fit: cover; display: block;
    border-radius: 14px; box-shadow: 0 8px 22px rgba(13, 47, 82, .14);
  }

  /* =================================================================
     CONTACT — the three detail tiles, then the real form
     ================================================================= */
  .mv-contact-card {
    display: block; text-decoration: none; margin-bottom: 12px;
    padding: 18px 16px; border-radius: 14px;
    background: #ffffff; box-shadow: 0 6px 18px rgba(13, 47, 82, .10);
  }
  .mv-contact-icon { width: 32px; height: 32px; object-fit: contain; display: block; margin-bottom: 12px; }
  .mv-contact-h {
    font-family: 'Space Grotesk', sans-serif; font-size: 15px; font-weight: 700;
    text-transform: uppercase; color: #80121d; margin-bottom: 4px;
  }
  .mv-contact-v { font-family: 'Inter', sans-serif; font-size: 14px; line-height: 1.5; color: #213a5d; }

  /* The form node itself is moved here from the canvas, so its desktop rules
     still apply — every one of them absolute. Unpin the whole subtree and let
     it flow, then restyle the fields for touch. */
  .mv-form, .mv-form * { position: static !important; }
  .mv-form {
    margin-top: 24px; padding: 20px 16px; border-radius: 14px;
    background: #213a5d;
    display: flex; flex-direction: column; gap: 12px;
    width: auto !important; height: auto !important;
  }
  .mv-form .ct-field {
    width: 100% !important; height: auto !important;
    background: rgba(255, 255, 255, .12); border-radius: 10px;
  }
  .mv-form .ct-input {
    width: 100% !important; height: auto !important;
    padding: 15px 14px; font-size: 16px;      /* 16px stops iOS zooming on focus */
    background: transparent; border: 0; border-radius: 10px; color: #ffffff;
  }
  .mv-form .ct-textarea { min-height: 130px; resize: vertical; }
  .mv-form .ct-input::placeholder { color: rgba(255, 255, 255, .6); }
  .mv-form .ct-submit {
    width: 100% !important; height: auto !important;
    display: flex; align-items: center; justify-content: center; gap: 10px;
    padding: 15px 18px; background: #80121d; border: 0; border-radius: 0;
    text-align: center;
  }
  .mv-form .ct-submit-label {
    width: auto !important; height: auto !important;
    font-family:'Inter',sans-serif; font-size: 16px;
    text-transform: uppercase; color: #ffffff; font-weight:500; letter-spacing:0.6px;}
  /* the icon is a white square carrying the red arrow, the mirror of the red
     square on .mv-btn — unpinning it had collapsed the square to a sliver */
  .mv-form .ct-submit-icon {
    width: 34px !important; height: 31px !important; flex: 0 0 auto;
    display: inline-flex; align-items: center; justify-content: center;
    background: #ffffff;
  }
  .mv-form .ct-submit-icon svg { width: 18px; height: 10px; }
  .mv-form .ct-thanks {
    font-family: 'Inter', sans-serif; font-size: 14px; color: #ffffff;
    text-align: center; width: auto !important; height: auto !important;
  }

  /* =================================================================
     CERTIFICATIONS — the fanned strip becomes a plain two-up grid
     ================================================================= */
  .mv-certs { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .mv-cert {
    margin: 0; border-radius: 10px; overflow: hidden; background: #ffffff;
    box-shadow: 0 6px 18px rgba(13, 47, 82, .10);
  }
  /* certificates are documents — show the whole page, never crop one */
  .mv-cert img { width: 100%; height: 210px; object-fit: contain; display: block; padding: 8px; }

  /* the certificates are controls now, not decoration (see the lightbox
     block at the end of js/mobile-view.js) */
  .mv-cert img, .mv-certs img, .mv-deck img { cursor: zoom-in; }

  /* ---- certificate lightbox ----------------------------------------
     A certificate is a dense A4 document shown at ~170px wide here, so it
     cannot be read in place. Tapping opens it full screen. Fixed to the
     viewport rather than the column: the mobile layout is one long
     scrolling stack, and an absolutely-positioned overlay would sit at
     whatever offset the page happened to be at. */
  .mv-lb {
    position: fixed; inset: 0; z-index: 2147483000;
    background: rgba(6, 14, 24, .95);
    display: flex; align-items: center; justify-content: center;
    padding: max(14px, env(safe-area-inset-top)) 14px 14px;
  }
  .mv-lb[hidden] { display: none; }
  .mv-lb-stage {
    width: 100%; height: 100%;
    display: flex; align-items: center; justify-content: center;
    overflow: auto; -webkit-overflow-scrolling: touch;
  }
  .mv-lb-img {
    max-width: 100%; max-height: 100%;
    width: auto; height: auto;
    object-fit: contain;
    background: #ffffff; border-radius: 8px;
    box-shadow: 0 18px 50px rgba(0,0,0,.55);
  }
  .mv-lb-x {
    position: absolute; top: max(10px, env(safe-area-inset-top)); right: 10px;
    width: 46px; height: 46px;          /* >= the 44px minimum touch target */
    display: flex; align-items: center; justify-content: center;
    border: 0; border-radius: 50%; padding: 0;
    background: rgba(255,255,255,.14); color: #ffffff;
    -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
    cursor: pointer; z-index: 1;
  }
  .mv-lb-x svg { width: 22px; height: 22px; display: block; }
  .mv-lb-x:active { background: rgba(255,255,255,.26); }
  /* hold the page still behind the overlay */
  body.mv-lb-open { overflow: hidden; }

  /* =================================================================
     ARTICLE / PROJECT VIEW — long-form copy
     ================================================================= */
  /* a comfortable measure for a full article rather than a caption */
  .mv-copy--read { font-size: 15px; line-height: 1.75; }
  .mv-list--dark li { color: #213a5d; }

  /* ---- footer ---- */
  /* ---------------------------------------------------------------
     The video band.

     Deliberately reuses .en-media / .en-play so js/video-embed.js binds
     to it unchanged - which means the frame has to carry the positioning
     the injected <video> assumes: it is inserted with position:absolute
     and inset:0, so the frame is the containing block. 16:9 via
     aspect-ratio rather than a fixed height, so it holds its shape at any
     phone width and reserves the space before the poster loads.

     The play badge overlays the frame instead of following it, so the
     margin-top pulls it back up over the frame it belongs to. */
  .mv-video { background: #0d1b2c; text-align: center; }
  .mv-video .mv-h2 { color: #fff; }
  /* Defined HERE, not with the other .mv-ic- rules: those live in
     css/integration-center.css, which only that page loads, so the
     eyebrow was unstyled on data-center and oil-and-gas and inherited the
     dark body colour. */
  .mv-video-eyebrow {
    margin: 0 0 10px;
    font-family: 'Space Grotesk', sans-serif;
    font-weight: 500; font-size: 11px; letter-spacing: 3px;
    text-transform: uppercase; color: rgba(255, 255, 255, .72);
  }
  /* the positioned parent the play button centres against */
  .mv-video-stage { position: relative; margin-top: 18px; }
  .mv-video-frame {
    position: relative; width: 100%; aspect-ratio: 16 / 9;
    border-radius: 18px; overflow: hidden;
    background: #060d16;
  }
  .mv-video-frame img {
    width: 100%; height: 100%; object-fit: cover; display: block;
  }
  /* dead centre of the picture, which holds at any width because it is a
     percentage of the frame rather than a fixed offset from its edge */
  .mv-video-play {
    position: absolute; z-index: 2;
    left: 50%; top: 50%; transform: translate(-50%, -50%);
    width: 64px; height: 64px;
    border-radius: 50%; background: rgba(0, 49, 89, .92);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .45);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
  }
  /* Polygon1.svg is drawn pointing UP - every desktop page rotates it to
     make a play glyph, so this has to as well or it reads as an upload
     arrow. The optical nudge rotates with it: shifting the triangle
     toward its own point is margin-top once the box is turned. */
  .mv-video-play i { display: block; line-height: 0; transform: rotate(90deg); }
  .mv-video-play img { width: 20px; height: 20px; margin-top: 3px; display: block; }

  /* ---------------------------------------------------------------
     The closing Integration Center band, carrying the desktop treatment
     rather than a flat restatement of it.

     Desktop sits this over body #4e6380 lit by Ellipse18, a #213a5d ->
     #e6f0ff soft glow. That is reproduced as a radial here rather than
     shipping a 100KB asset to draw a blur. */
  .mv-partner {
    text-align: center;
    background-color: #4e6380;
    background-image: radial-gradient(130% 85% at 50% 45%,
      rgba(230, 240, 255, .55) 0%,
      rgba(33, 58, 93, 0) 72%);
  }
  /* the plate's gradient is .pt-plate's own background-image, lifted
     verbatim: viewBox 1005x345 with preserveAspectRatio='none', so at
     background-size:100% 100% it stretches to a phone-shaped box */
  .mv-partner-plate {
    position: relative; overflow: hidden;
    border-radius: 8px; padding: 30px 18px 28px;
    background-image:url("data:image/svg+xml;utf8,<svg viewBox='0 0 1005 345' xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='none'><rect x='0' y='0' height='100%' width='100%' fill='url(%23grad)' opacity='1'/><defs><radialGradient id='grad' gradientUnits='userSpaceOnUse' cx='0' cy='0' r='10' gradientTransform='matrix(3.0769e-15 17.25 -50.25 1.0563e-15 502.5 172.5)'><stop stop-color='rgba(26,43,66,1)' offset='0'/><stop stop-color='rgba(57,74,96,1)' offset='0.000025'/><stop stop-color='rgba(88,105,125,1)' offset='0.00005'/><stop stop-color='rgba(118,135,155,1)' offset='0.000075'/><stop stop-color='rgba(149,166,184,1)' offset='0.0001'/><stop stop-color='rgba(103,120,140,1)' offset='0.0002'/><stop stop-color='rgba(63,79,101,1)' offset='0.47609'/><stop stop-color='rgba(42,59,82,1)' offset='0.71404'/><stop stop-color='rgba(22,39,62,1)' offset='0.95198'/></radialGradient></defs></svg>");
    background-size: 100% 100%; background-repeat: no-repeat;
  }
  /* .pt-orb. Sized off the plate the way desktop does: the sphere is 159%
     of the plate's height (549 on 345) and sits 38px below its centre,
     which is 6.9% of the sphere - so it overflows and reads as a glowing
     band through the middle rather than a visible ball. */
  .mv-partner-orb {
    position: absolute; left: 50%; top: 50%;
    transform: translate(-50%, -43.1%);
    height: 159%; aspect-ratio: 554 / 549;
    mix-blend-mode: lighten; opacity: .48;
    overflow: hidden; pointer-events: none;
  }
  .mv-partner-orb img {
    position: absolute; left: -10.73%; top: -23.15%;
    width: 121.95%; height: 123.15%; display: block; max-width: none;
  }
  /* .pt-text. letter-spacing is .04em rather than desktop's 1.6px so it
     scales with the smaller size instead of shouting at it; everything
     else is the desktop value. */
  .mv-partner-t {
    position: relative; z-index: 1;
    margin: 0 0 22px;
    font-family: 'Inter', sans-serif;
    font-weight: 700; font-size: 22px; line-height: .93;
    letter-spacing: .04em; text-transform: uppercase;
    background-image: linear-gradient(to right, #ffffff, #e8f3ff);
    background-clip: text; -webkit-background-clip: text; color: transparent;
    filter: drop-shadow(0 4px 20px #213a5d);
  }
  /* the three weights inside the one sentence */
  .mv-partner-t .r { font-weight: 400; }
  .mv-partner-t .l { font-weight: 300; }
  .mv-partner-t .s { font-weight: 600; }
  .mv-partner .mv-btn { position: relative; z-index: 1; margin: 0 auto; }

  .mv-footer { background: #0a1420; padding: 40px 20px 28px; }
  /* same fallback: a 154x67 mark was being drawn into a 150x150 box */
  .mv-footer-logo { width: 132px; aspect-ratio: 154 / 67; height: auto;
                    object-fit: contain; display: block; margin: 22px 0 18px; }

  /* Social icons, mirroring the desktop footer: same 24px artwork, same 24px
     gap. The links are given real URLs by js/social-links.js from whatever is
     set in the admin's Contact info page. */
  .mv-social { display: flex; align-items: center; gap: 24px; margin: 0 0 22px; }
  .mv-social-link { display: block; width: 24px; height: 24px; }
  .mv-social-link img { display: block; width: 100%; height: 100%; }
  /* The columns are plain siblings inside the footer, so as block-level
     boxes LEARN MORE sat on top of SUPPORT. inline-flex puts them on one
     line while each keeps its own vertical stack, and matches the desktop
     footer where the two columns sit side by side. */
  .mv-fcol { margin-bottom: 18px; display: inline-flex; flex-direction: column;
             gap: 0; vertical-align: top; width: 48%; }
  .mv-fcol-h {
    font-family: 'Space Grotesk', sans-serif; font-size: 14px; text-transform: uppercase;
    letter-spacing: .6px; color: #ffffff; margin-bottom: 2px;
  }
  /* 17px tall on a 23px pitch failed the 24x24 tap-target audit. Padding
     lifts the hit box to 24 and the gap below lifts the pitch to 24 - the
     rows move down by 1, 2 and 3px respectively and the footer grows 1px.
     The text itself is not resized or re-coloured. */
  .mv-fcol-a { font-family: 'Inter', sans-serif; font-size: 14px; color: rgba(255,255,255,.75);
    text-decoration: none; display: block; min-height: 24px; padding: 3px 0 4px; }
  .mv-copyright {
    font-family: 'Inter', sans-serif; font-size: 11px; text-transform: uppercase;
    color: rgba(255,255,255,.55); text-align: center; margin-top: 18px;
  }

  /* ---- mobile nav: fixed bar + slide-in sidebar ---------------------
     Built by js/mobile-nav.js from the page's own links. The in-canvas
     header pill is hidden here because at ~30% it is far too small to tap —
     the bar below replaces it. Colours are the ones already in the design:
     the page navy from base.css and the white the nav links already use. */
  .hero-header, [class$="-header"] { visibility: hidden !important; }

  /* Slides away on the way down and returns on any nudge up, mirroring the
     desktop bar. js/mobile-nav.js drives the class with the same thresholds
     sticky-header.js uses, so the two behave the same. */
  #mNav.is-hidden { transform: translateY(-100%); }

  #mNav {
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 56px;
    transition: transform .28s cubic-bezier(.4, 0, .2, 1);
    will-change: transform;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 16px;
    /* No background of its own - see #mNav::before. A gradient painted ON the
       bar cannot solve this, because the bar is only 56px tall: whatever
       alpha it still has at its bottom edge ends there, and that step IS the
       line. The overlay below is taller than the bar and reaches zero. */
    background: none;
    z-index: 1000;
  }
  /* The scrim that keeps the logo legible. 140px tall against a 56px bar, and
     it finishes at fully transparent, so there is no edge anywhere: the
     darkening simply runs out. Sits behind the bar's own contents. */
  #mNav::before {
    content: '';
    position: absolute; left: 0; right: 0; top: 0;
    height: 140px;
    background: linear-gradient(to bottom,
      rgba(10, 20, 32, .96) 0%,
      rgba(10, 20, 32, .88) 22%,
      rgba(10, 20, 32, .62) 46%,
      rgba(10, 20, 32, .30) 70%,
      rgba(10, 20, 32, .10) 87%,
      rgba(10, 20, 32, 0) 100%);
    pointer-events: none;
    z-index: -1;
  }
  /* clear the fixed bar on <body>, never on #stage — the stack measures
     against the stage box, so padding there would shift every band */
  body { padding-top: 56px; }

  /* Let the banner run up behind the bar, the way the desktop hero does, so
     the picture starts at the top of the screen rather than below a slab.
     The 56px the body reserves is given back inside the hero, so nothing the
     hero contains moves. Only the first section is pulled up; everything
     after it keeps the reserved space. */
  body.mv-on .mv > .mv-hero:first-child {
    margin-top: -56px;
    padding-top: 110px;          /* 54px designed inset + the 56px bar */
  }

  .mnav-logo { display: flex; align-items: center; width: 116px; }
  .mnav-logo svg { width: 100%; height: auto; display: block; }

  .mnav-burger {
    width: 42px; height: 42px;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: 5px;
    background: none; border: 0; padding: 0; cursor: pointer;
  }
  .mnav-burger span {
    display: block; width: 22px; height: 2px;
    background: #ffffff;
    transition: transform .25s ease, opacity .2s ease;
  }
  .mnav-open .mnav-burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .mnav-open .mnav-burger span:nth-child(2) { opacity: 0; }
  .mnav-open .mnav-burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  .mnav-scrim {
    position: fixed; inset: 0;
    background: rgba(10, 20, 32, .55);
    opacity: 0; pointer-events: none;
    transition: opacity .25s ease;
    z-index: 1001;
  }
  .mnav-open .mnav-scrim { opacity: 1; pointer-events: auto; }

  .mnav-side {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: min(78vw, 300px);
    background: #0a1420;
    z-index: 1002;
    padding: 72px 22px 28px;
    display: flex; flex-direction: column; gap: 2px;
    transform: translateX(100%);
    transition: transform .28s ease;
    overflow-y: auto;
  }
  .mnav-open .mnav-side { transform: translateX(0); }

  .mnav-link {
    font-family: 'Inter', sans-serif;
    font-size: 16px;
    color: #ffffff;
    text-decoration: none;
    padding: 14px 4px;
    border-bottom: 1px solid rgba(255, 255, 255, .12);
  }
  .mnav-link.is-sub { font-size: 14px; padding-left: 16px; opacity: .85; }
  .mnav-link.is-cta {
    margin-top: 16px;
    border: 0;
    text-align: center;
    padding: 13px 16px;
    background: #ffffff;
    color: #0a1420;
    font-weight: 600;
  }
}

  /* Contact: the country picker. Desktop uses a custom dropdown inside the
     canvas; a phone gets the native control, which is what people expect to
     tap and what the OS renders a proper wheel for. */
  .mv-contact-select {
    display: block; width: 100%; margin-top: 6px; padding: 10px 12px;
    font: inherit; font-size: 15px; color: #213a5d;
    background: rgba(255,255,255,.9); border: 1px solid rgba(33,58,93,.22);
    border-radius: 10px; -webkit-appearance: menulist; appearance: menulist;
  }
  .mv-contact-select:focus-visible { outline: 2px solid #80121d; outline-offset: 2px; }

/* Visually hidden: read by crawlers and screen readers, painted nowhere.
   "see more" on its own tells neither what it leads to, and Lighthouse's
   link-text audit reads the link's TEXT - an aria-label alone does not
   satisfy it, which is why naming them that way left the audit failing. */
.vh{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

  /* Services: the Integration Center tagline, between the card title and copy */
  .mv-card-tagline {
    margin: 2px 0 8px; font-family: 'Space Grotesk', sans-serif;
    font-weight: 600; font-size: 14.5px; line-height: 1.3; color: #80121d;
  }

  /* Integration Center: the capability icon badge on a phone */
  .mv-cap-badge{
    display:flex; align-items:center; justify-content:center;
    width:52px; height:52px; margin:0 0 12px;
    border-radius:50%; background:#003159; color:#a8c4dc;
  }
  .mv-cap-badge svg{ width:24px; height:24px; display:block; }
