/* vietnamese */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url(../fonts/archivo-variable-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url(../fonts/archivo-variable-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url(../fonts/archivo-variable-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

    body { margin: 0; background: #ffffff; font-family: 'Archivo', sans-serif; color: #4a5b70; }
    h1, h2, h3 { overflow-wrap: anywhere; }
    a { color: #14335c; }
    a:hover { color: #8a6a1f !important; }
    ::selection { background: #14335c; color: #fff; }

    /* Utility strip. It and the sticky header below it were both pure white
       with a 1px rule between, so the whole top of the page read as one flat
       slab and the header had nothing to sit against. The strip takes the
       deep navy instead: it caps the page and pushes the white header forward.
       (In B this was the concept's ink, which also served to keep B distinct
       from A at the top of the page. D inherits the treatment, not that
       reason: D is the chosen direction, not a fourth option to tell apart.)
       The strip's own links need a lighter amber than the global a:hover,
       which is tuned for hovering on white. */
    #utility-strip a:hover, #utility-strip a:focus-visible { color: #e8a33d !important; }
    #utility-strip a:focus-visible { outline-color: #e8a33d; }

    /* The footer takes the same deep navy as the strip, for the same reason:
       white on white read as nothing at all. Together they bookend the page,
       so the dark ground reads as a system rather than a one-off band, and it
       lets the white logo and the amber accent carry the bottom of the page,
       which white could not.
       The two amber rules below exist because the global hover, #8a6a1f, is
       tuned for a white ground and goes muddy on navy. */
    #contact a:hover, #contact a:focus-visible { color: #e8a33d !important; }
    #contact a:focus-visible { outline-color: #e8a33d; }
    @keyframes logoSlide { from { transform: translateX(0); } to { transform: translateX(-50%); } }

    /* Visible keyboard focus, all interactive elements */
    a:focus-visible, button:focus-visible, input:focus-visible {
      outline: 3px solid #8a6a1f;
      outline-offset: 2px;
    }

    /* Desktop nav dropdowns (Buy / Hire taxonomy panels) */
    .nav-drop { position: relative; }
    .nav-drop-btn {
      font: inherit; display: flex; align-items: center; gap: 6px;
      background: none; border: none; padding: 0; margin: 0;
      color: #14335c; cursor: pointer; transition: color .15s ease;
    }
    .nav-drop-btn:hover, .nav-drop-btn:focus-visible { color: #8a6a1f; }
    .nav-drop-caret { transition: transform .2s ease; flex: 0 0 auto; }
    .nav-drop.is-open .nav-drop-caret { transform: rotate(180deg); }
    .nav-drop-panel {
      display: none; flex-direction: column; position: absolute; top: 100%; left: 0;
      margin-top: 16px; padding: 10px; min-width: 250px;
      background: #fff; border-radius: 8px; box-shadow: 0 12px 32px rgba(14,36,64,.16);
      z-index: 60;
    }
    .nav-drop-panel a {
      display: block; padding: 10px 14px; border-radius: 6px;
      color: #14335c; text-decoration: none; font-weight: 600; font-size: 14.5px; white-space: nowrap;
    }
    .nav-drop-panel a:hover, .nav-drop-panel a:focus-visible { background: #f6f8fa; }
    .nav-drop.is-open .nav-drop-panel, .nav-drop:hover .nav-drop-panel { display: flex; }

    /* Button / tile hover states (scp0-scp6, ported from the approved concept, one rule per shared visual role) */
    .scp0 { transition: filter .18s ease; }
    .scp0:hover, .scp0:focus-visible { filter: brightness(1.06); }
    .scp1 span { transition: border-color .18s ease; }
    .scp1:hover span, .scp1:focus-visible span { border-color: #e8a33d !important; }
    .scp2 { transition: transform .25s ease; }
    .scp2:hover, .scp2:focus-visible { transform: translateY(-4px); }
    .scp3 { transition: box-shadow .25s ease; }
    .scp3:hover, .scp3:focus-visible { box-shadow: 0 20px 44px rgba(14,36,64,.24); }
    .scp4 { transition: filter .18s ease; }
    .scp4:hover, .scp4:focus-visible { filter: brightness(1.5); }
    .scp5 { transition: background .18s ease, color .18s ease; }
    .scp5:hover, .scp5:focus-visible { background: #14335c !important; color: #fff !important; }
    .scp6 { transition: box-shadow .25s ease; }
    .scp6:hover, .scp6:focus-visible { box-shadow: 0 16px 40px rgba(14,36,64,.24); }

    /* Mobile menu accordions (Buy / Hire taxonomy lists) */
    .m-acc { border-bottom: 1px solid #e3e9f0; }
    .m-acc-btn {
      width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px;
      background: none; border: none; text-align: left; font: inherit;
      color: #14335c; font-weight: 700; font-size: 21px; padding: 18px 0; cursor: pointer;
    }
    .m-acc-btn:hover, .m-acc-btn:focus-visible { color: #8a6a1f; }
    [data-menu-close]:hover, [data-menu-close]:focus-visible { color: #8a6a1f !important; }
    .m-acc-caret { transition: transform .2s; flex: 0 0 auto; }
    .m-acc-btn[aria-expanded="true"] .m-acc-caret { transform: rotate(180deg); }
    .m-acc-panel { display: none; flex-direction: column; padding: 0 0 12px; }
    .m-acc-panel.is-open { display: flex; }
    .m-acc-panel a {
      text-decoration: none; color: #4a5b70; font-weight: 600; font-size: 17px;
      padding: 13px 0 13px 14px; box-sizing: border-box;
    }

    /* Testimonials slider: native scroll-snap track, two-up on desktop, one-up on mobile */
    /* Quotes vary a lot in length; anchor the attribution to the card's bottom edge
       instead of letting the paragraph's flex-grow strand it under short quotes. */
    .t-card p { flex: none !important; }
    .t-card footer { margin-top: auto; }
    .t-viewport {
      overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
      scrollbar-width: none; -ms-overflow-style: none;
    }
    .t-viewport::-webkit-scrollbar { display: none; }
    .t-track { display: flex; gap: 24px; }
    .t-card { flex: 0 0 calc(50% - 12px); box-sizing: border-box; scroll-snap-align: start; }
    .t-controls { display: flex; align-items: center; justify-content: center; gap: 18px; margin-top: 32px; }
    /* Controls hide only when the computed page count is one, so that a set small
       enough to fit in a single view never shows a dead arrow pair. With the
       current set there is always more than one page, so this does not fire. It
       stays as a guard in case the set is ever cut back. */
    .t-controls.is-single-page { display: none; }
    .t-arrow {
      width: 44px; height: 44px; flex: 0 0 auto; border-radius: 50%; padding: 0;
      background: transparent; border: 1px solid rgba(255,255,255,.3); color: #fff;
      display: flex; align-items: center; justify-content: center; cursor: pointer;
      transition: background .18s ease, border-color .18s ease;
    }
    .t-arrow:hover:not(:disabled), .t-arrow:focus-visible:not(:disabled) {
      background: rgba(255,255,255,.12); border-color: rgba(255,255,255,.6);
    }
    .t-arrow:disabled { opacity: .3; cursor: default; }
    /* Desktop only: two-up means three pages at most for the current set, so
       the dots always fit a single row here, no wrap needed. Mobile swaps
       these for a "1 of 6" counter instead (below), since six one-up pages
       cannot fit six 44px dot targets in the ~234px between the arrows. */
    .t-dots { display: flex; align-items: center; justify-content: center; gap: 8px; }
    /* Real hit area is 44x44 (invisible); the visible pill is a ::after so the
       8px-to-22px "active dot widens" look is unchanged. */
    .t-dot {
      width: 44px; height: 44px; padding: 0; border: none; background: transparent;
      display: flex; align-items: center; justify-content: center; cursor: pointer;
    }
    .t-dot::after {
      content: ""; width: 8px; height: 8px; border-radius: 4px;
      background: rgba(255,255,255,.3); transition: width .18s ease, background .18s ease;
    }
    .t-dot.is-active::after { width: 22px; background: #e8a33d; }
    .t-dot:hover:not(.is-active)::after, .t-dot:focus-visible:not(.is-active)::after { background: rgba(255,255,255,.55); }
    /* Mobile position counter, replaces the dots (see media query below) */
    .t-counter {
      display: none; min-width: 64px; text-align: center;
      font-size: 14px; color: rgba(255,255,255,.55); font-variant-numeric: tabular-nums;
    }

    /* --- Concept D additions --------------------------------------------
       D is concept B with concept A's blue palette and the four changes Dom
       asked for on 29 Jul 2026. Everything above this line is B's, recoloured
       token for token. Everything below is new. */

    /* Buy/Hire fork. The ask was for the two paths to be "a little more
       prominent". The section takes its own light ground so it reads as a
       decision point rather than the top of the range section, gains a
       heading, and each card gains three supporting points. Round 4 fix B2
       added the top padding that keeps these cards clear of the hero band, so
       prominence comes from ground, framing and size, never from moving them
       back up into it. */
    /* The text scrim is anchored to the text box, not to the card.
       B's cards carried the scrim as a bottom-weighted gradient over the whole
       card, which worked at 340px because the text filled most of it. At 440px
       the same gradient puts the eyebrow and the heading up in the photo's
       mid-tones, and the amber eyebrow in particular dropped to about 1.3:1.
       Scoping the scrim to the body box makes contrast independent of both the
       card height and the photo: the fade completes inside the box's own 36px
       top padding, so every pixel of text sits on at least 0.94 navy while the
       top ~110px of the photo still reads clean. */
    .fork-body {
      position: relative; width: 100%; box-sizing: border-box;
      padding: 36px 38px; display: flex; flex-direction: column; gap: 10px;
      background: linear-gradient(rgba(14,36,64,0) 0%, rgba(14,36,64,.94) 12%, rgba(14,36,64,.97) 100%);
    }
    .fork-points { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
    .fork-point {
      display: flex; gap: 10px; align-items: flex-start;
      color: #d5dfec; font-size: 15px; line-height: 1.4;
    }
    .fork-point svg { flex: 0 0 auto; margin-top: 3px; }

    /* Video showcase. The client's homepage video is a 34.5MB, 53 second,
       1080p MP4 served straight out of their WordPress uploads folder with no
       poster frame. Autoloading that would cost the contract's 90+ PageSpeed
       target on its own, so this is a click-to-load facade: the section
       renders a poster image and a button, and the <video> element is created
       only when the button is pressed. Before the press the section costs one
       76KB image. The file shipped here is a re-encoded 720p copy, 9.8MB. */
    .video-frame {
      position: relative; border-radius: 10px; overflow: hidden;
      background: #0a1a30; box-shadow: 0 24px 60px rgba(0,0,0,.42);
    }
    .video-play {
      display: block; width: 100%; padding: 0; margin: 0; border: none;
      background: none; cursor: pointer; position: relative; line-height: 0;
    }
    .video-poster { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; }
    .video-play::after {
      content: ""; position: absolute; inset: 0;
      background: linear-gradient(rgba(14,36,64,0) 45%, rgba(14,36,64,.5) 100%);
      transition: background .25s ease;
    }
    .video-play:hover::after, .video-play:focus-visible::after {
      background: linear-gradient(rgba(14,36,64,.14) 0%, rgba(14,36,64,.55) 100%);
    }
    .video-play-btn {
      position: absolute; top: 50%; left: 50%; z-index: 1;
      transform: translate(-50%, -50%);
      width: 88px; height: 88px; border-radius: 50%;
      background: #e8a33d; color: #0e2440;
      display: flex; align-items: center; justify-content: center;
      padding-left: 7px; box-sizing: border-box;
      transition: transform .25s ease;
    }
    .video-play:hover .video-play-btn, .video-play:focus-visible .video-play-btn {
      transform: translate(-50%, -50%) scale(1.08);
    }
    .video-duration {
      position: absolute; right: 16px; bottom: 14px; z-index: 1;
      background: rgba(10,26,48,.85); color: #fff;
      font-size: 13px; font-weight: 700; line-height: 1;
      padding: 6px 10px; border-radius: 4px; font-variant-numeric: tabular-nums;
    }
    .video-frame video {
      display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; background: #000;
    }

    /* "Why customers keep coming back", ported from concept A's feature list.
       In A it runs on navy. Here it lands between the navy testimonial band
       and the light about band, so it runs on white instead, and the ticks
       take the contrast-safe amber #8a6a1f (4.6:1 on white). #e8a33d is
       2.1:1 on white and only ever appears on dark in this concept. */
    .why-row {
      display: grid; grid-template-columns: 22px 1fr; gap: 16px; align-items: start;
      padding: 22px 0; border-top: 1px solid #e3e9f0;
    }
    .why-row svg { margin-top: 2px; }
    .why-row-last { border-bottom: 1px solid #e3e9f0; }

    /* scp7: the "Get to know us" text link under the why list, ported from A */
    .scp7 { transition: border-bottom-width .2s ease; }
    .scp7:hover, .scp7:focus-visible { border-bottom-width: 3px !important; }

    @media (max-width: 900px) {
      #desktop-nav { display: none !important; }
      #hamburger-btn { display: flex !important; }
      #header-row { gap: 16px !important; padding: 16px 20px !important; justify-content: space-between !important; }
      #header-cta { display: none !important; }
      #utility-address, #utility-hours, #utility-divider { display: none !important; }
      #utility-bar { justify-content: center !important; }
      #utility-right { width: 100%; justify-content: center !important; }
      #utility-right a { padding: 15px 10px; box-sizing: border-box; }
    }
    @media (max-width: 768px) {
      #mobile-cta-bar { display: flex !important; }
      #hero-h1 { font-size: 38px !important; }
      #range-grid { grid-template-columns: 1fr !important; }
      #industries-grid { grid-template-columns: repeat(2, 1fr) !important; }
      #header-row { gap: 12px !important; padding: 14px 16px !important; }
      #header-logo { height: 36px !important; }
      #buyhire-grid, #visit-grid, #hire-grid, #help-grid, #footer-grid, #why-grid { grid-template-columns: 1fr !important; gap: 34px !important; }
      #process-grid { grid-template-columns: 1fr 1fr !important; gap: 32px 20px !important; }

      /* "Get to know us" is a text link with a 2px amber underline, 19px of
         line box, which fails the 44px minimum tap target. Pad the TOP rather
         than the bottom so the underline stays tight under the text where the
         design puts it, and pull the same amount back off the margin so the
         visual spacing above the link does not change. 19 + 24 + 3 = 46. */
      .scp7 { padding-top: 24px !important; margin-top: -24px !important; }

      /* Section headings were never stepped down for mobile. B carries every
         H2 at 42-46px while its H1 drops to 38px (and 30px below 480), so on a
         phone the section headings rendered larger than the page's own H1.
         Step the H2s below the H1 at both breakpoints. */
      section h2 { font-size: 32px !important; line-height: 1.1 !important; }

      /* The range section's "Also available:" links compute to 43px tall
         (13px padding either side of a 17px line box), 1px under the minimum.
         Inherited from B; caught at the 768 breakpoint. */
      #range a { min-height: 44px; }

      /* Video facade: the 88px desktop play button crowds a 334px poster */
      .video-play-btn { width: 62px !important; height: 62px !important; padding-left: 5px !important; }
      .video-play-btn svg { width: 22px; height: 25px; }
      .video-duration { right: 12px; bottom: 10px; }
      #custom-grid { grid-template-columns: 1fr !important; grid-auto-rows: 200px !important; }
      #custom-grid > a { grid-row: auto !important; grid-column: auto !important; }
      .t-card { flex: 0 0 100% !important; scroll-snap-align: center; }
      /* Six one-up mobile pages cannot fit six 44px dot targets between the
         arrows here (~234px available, six dots plus gaps need ~264px), and
         wrapping them to a second row read as broken. A counter always fits. */
      .t-dots { display: none; }
      .t-counter { display: block; }
      #custom-header-row { flex-direction: column !important; align-items: flex-start !important; }
      #custom-header-copy { width: 100% !important; max-width: 100% !important; box-sizing: border-box !important; }
      #custom-header-row a { align-self: stretch !important; text-align: center; }

      /* Footer content centres and stacks below 768px */
      #footer-grid { text-align: center; }
      #footer-grid > div { align-items: center; }
      #footer-bottom { flex-direction: column; align-items: center; text-align: center; }
      #footer-legal { margin-left: 0 !important; justify-content: center; }

      /* Tap targets: footer-bottom's two legal links sit side by side (a
         horizontal gap), min-height doesn't stack with that, so it's untouched */
      #footer-bottom a {
        min-height: 44px; display: flex; align-items: center; justify-content: center;
        box-sizing: border-box; padding: 0 10px; margin: 0 -10px;
      }

      /* Footer spacing system (main columns): one gap between links in a
         group, one gap under each heading, one gap between groups (this
         grid's own 34px above, untouched, already the largest of the three).
         The previous min-height:44px fix stacked with the column's own 10px
         gap, ~54px between links, nearly the same as the 34px between
         groups, so nothing read as a group. Height (not min-height) plus a
         zeroed column gap fixes that: the 44px tap target lives entirely
         inside the link's own box, with no extra gap stacking on top of it. */
      /* Zeroed at both levels: within a group (below) and between groups
         (here, overriding the shared 34px grid gap from the rule above so
         the three tiers can't fight or double up with it). Hierarchy comes
         entirely from the heading's own margin, not from gap. */
      #footer-grid { gap: 0 !important; }
      #footer-grid > div { gap: 0 !important; }
      #footer-grid a {
        height: 44px; min-width: 44px; box-sizing: border-box;
        display: flex; align-items: center; justify-content: center;
        padding: 0 10px; margin: 0 -10px;
      }
      /* Get In Touch's address/hours are plain text, not links, but get the
         same box height so all four items in that group read as one list */
      #footer-contact-col span {
        height: 44px; box-sizing: border-box;
        display: flex; align-items: center; justify-content: center;
        padding: 0 10px; margin: 0 -10px;
      }
      /* Three tiers, not two: 44 within a group (above), 12 binding a heading
         to its own list, 56 separating one group from the next. The first
         heading's margin-top does double duty as "space after the brand
         block", so that block needs no spacing rule of its own for this. */
      #footer-grid strong { margin-top: 56px !important; margin-bottom: 12px !important; }

      /* Brand block: logo, tagline and finance line were jammed together once
         the list gap dropped to zero elsewhere in the footer; keep this
         cluster's own breathing room explicit rather than inherited */
      #footer-brand img { margin-bottom: 22px !important; }
      #footer-brand p:first-of-type { margin-bottom: 14px !important; }
      #footer-brand p:last-of-type { margin-top: 0 !important; }
      /* text-align: center on the grid centres the words inside each paragraph
         but not the paragraph's own box, and both carry an inline
         max-width: 300px. In a 334px column that left-aligns the box, so the
         tagline sat 17px left of the centred logo and lists below it. */
      #footer-brand p { margin-left: auto !important; margin-right: auto !important; }

      /* Mobile vertical rhythm: same scale, reduced value (Part 3.4) */
      #buyhire, #range, #video, #testimonial-slider, #why, #visit, #custom, #process, #industry-slider, #help {
        padding-top: 60px !important; padding-bottom: 60px !important;
      }
      /* In B, #buyhire sat directly on #range with no colour break between
         them (both white), so its bottom padding was dropped to stop the two
         stacking into dead space. In D the fork has its own light ground, so
         the break is real and the padding is kept. */
      #hire { padding-bottom: 60px !important; }
      #help-grid { padding-top: 48px !important; }
    }

    /* The H1 only had a single step at 768px. That was sized for the old
       48-character headline; the corrected one runs ~62 characters and at 38px
       it broke into six choppy lines on a 390px screen, several holding one
       word. Step it down again below 480px. Matches C's mobile H1 size. */
    @media (max-width: 480px) {
      #hero-h1 { font-size: 30px !important; }
      section h2 { font-size: 27px !important; }
    }

    /* "How it works" holds four steps two-up from 768 down. At 390 that still
       reads well (roughly 155px columns), but by 360 the 64px numerals and the
       step descriptions are squeezed, so it goes single column below 380
       rather than at the 480 the plan assumed. The breakpoint is set by where
       the content actually breaks, checked at 320, 360 and 390. */
    @media (max-width: 380px) {
      #process-grid { grid-template-columns: 1fr !important; gap: 28px !important; }
    }

    @media (prefers-reduced-motion: reduce) {
      #logo-marquee-track { animation: none !important; }
      [data-hero-layer] { transition: none !important; }
      .scp2:hover { transform: none; }
      .t-viewport { scroll-behavior: auto; }
      /* The play button's hover scale is the only transform added in D */
      .video-play:hover .video-play-btn, .video-play:focus-visible .video-play-btn {
        transform: translate(-50%, -50%) !important;
      }
    }
