/* ==========================================================================
   Responsive layer — desktop-down overrides.
   Mobile is the priority: the sticky call/WhatsApp/quote bar appears below
   1024px, and the hero form stays above the fold on phones.
   ========================================================================== */

/*
 * The header holds seven navigation items, a language switcher and two
 * buttons, and `.header-cta { flex: none }` means it never shrinks — so it
 * runs off the page rather than wrapping. Adding Projects and Reviews pushed
 * it over at every desktop width, 37px at 1440 and 116px at 1025.
 *
 * It gives way in stages, cheapest thing first: the WhatsApp label goes (the
 * icon is unmistakable and the button keeps its aria-label), then the nav
 * padding tightens, then the phone number drops to its icon. Nothing is ever
 * removed — every one of them is still in the mobile menu below 1024px.
 *
 * The first stage starts at 1500 rather than at some rounder number because
 * that is where it measured over: 1440 was 37px past the viewport with every
 * label showing.
 */
@media (max-width: 1500px) {
  .header-cta .btn-gold span { display: none; }
  .header-cta .btn-gold { padding-inline: 0.85rem; }
}

/* ---------- Large desktop ---------- */
@media (max-width: 1200px) {
  :root { --fs-4xl: 2.4rem; --fs-3xl: 1.95rem; }
  .hero-inner { gap: var(--sp-6); }
  .nav-link { padding-inline: 0.5rem; font-size: var(--fs-xs); }
  .header-inner { gap: var(--sp-3); }
  .header-cta { gap: var(--sp-2); }
  .nav-item-lang { margin-inline-start: 0; }
  .nav-lang { padding-inline: var(--sp-2); }
}

/* ---------- Small desktop / large tablet ---------- */
@media (max-width: 1080px) {
  /* 1025px is the tightest the horizontal nav ever gets — one pixel above the
     width where it collapses into the toggle. The phone number gives up its
     label here and the switcher its globe, which is the last of the slack. */
  .nav-link { padding-inline: 0.35rem; }
  .header-cta .btn-phone span { display: none; }
  .header-cta .btn-phone { padding-inline: 0.85rem; }
  .nav-lang .icon { display: none; }
  .header-phone-text small { display: none; }
  .dropdown-wide { min-width: 460px; }
  .steps-5 { grid-template-columns: repeat(3, 1fr); }
  .grid-4 { grid-template-columns: repeat(3, 1fr); }
  .footer-top { grid-template-columns: 1.4fr 1fr 1fr; }
  .footer-top .footer-col:last-child { grid-column: 2 / -1; }

  .service-strip, .service-strip-wrap { grid-template-columns: repeat(4, 1fr) !important; }
  .blog-grid { grid-template-columns: 1fr; }
  .blog-cards { grid-template-columns: repeat(3, 1fr); }
}

/* ---------- Tablet: collapse navigation, show mobile CTA bar ---------- */
@media (max-width: 1024px) {
  :root { --header-h: 68px; }

  body { padding-bottom: 62px; } /* room for the sticky bar */

  .mobile-bar { display: flex; }

  .header-cta { display: none; }

  .nav-toggle {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    order: 3;
    margin-left: auto;
    width: 46px;
    height: 46px;
    padding: 11px;
    background: var(--surface-alt);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    cursor: pointer;
  }
  .nav-toggle-bar {
    display: block;
    height: 2px;
    background: var(--navy-800);
    border-radius: 2px;
    transition: transform .18s ease, opacity .18s ease;
  }
  .nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { opacity: 0; }
  .nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  .primary-nav {
    position: fixed;
    top: calc(var(--header-h) + 38px);
    left: 0;
    right: 0;
    bottom: 0;
    margin: 0;
    padding: var(--sp-4) var(--sp-5) calc(var(--sp-8) + 62px);
    background: var(--surface);
    border-top: 1px solid var(--line);
    overflow-y: auto;
    /* Fades rather than sliding in from translateX(100%). A fixed panel
       parked outside the viewport widens the scrollable area on a phone,
       and being fixed it is not clipped by overflow on html or body. */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-10px);
    transition: opacity .18s ease, transform .18s ease, visibility .18s;
    z-index: 150;
  }
  .primary-nav.is-open { opacity: 1; visibility: visible; transform: translateY(0); }

  .nav-list { flex-direction: column; align-items: stretch; gap: 0; }
  .nav-item { border-bottom: 1px solid var(--line); }
  .nav-link {
    justify-content: space-between;
    width: 100%;
    padding: 0.95rem 0.25rem;
    font-size: var(--fs-base);
    border-radius: 0;
  }
  .nav-link:hover { background: transparent; }

  .dropdown {
    position: static;
    transform: none;
    min-width: 0;
    max-height: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    opacity: 1;
    visibility: visible;
    overflow: hidden;
    transition: max-height .25s ease, padding .2s ease;
  }
  .has-dropdown:hover > .dropdown { max-height: 0; }
  .has-dropdown.is-open > .dropdown {
    max-height: 720px;
    padding: 0 0 var(--sp-3) var(--sp-2);
    transform: none;
  }
  .dropdown-wide .dropdown-list { grid-template-columns: 1fr; }
  .dropdown-list a { padding: 0.6rem 0.5rem; }
  .dropdown-foot { border-top: 0; padding-top: 0; }

  .nav-cta-mobile { display: grid; gap: var(--sp-3); margin-top: var(--sp-5); }

  .hero-inner { grid-template-columns: 1fr; }
  .hero-copy { max-width: 100%; }
  .split, .split-reverse { grid-template-columns: 1fr; gap: var(--sp-6); }
  .trust-grid { grid-template-columns: 1fr 1fr; }

  /* Homepage sections */
  /*
   * The photograph stays the hero's background here, as it is on a desktop.
   *
   * What has to change is the scrim. Once the hero stacks, the copy sits over
   * the middle of the picture rather than beside it, and a near-white scrim
   * heavy enough to carry navy body text hides the photograph completely —
   * which is how this hero came to render as an empty white block on a phone.
   *
   * So the scrim goes navy and the copy inverts to light-on-dark. The picture
   * reads properly through it, and white on this depth of navy has more
   * contrast than the navy-on-white it replaces.
   */
  .hero-home {
    height: auto;
    min-height: 30rem;
    background: var(--navy-800);
  }
  .hero-home-inner {
    grid-template-columns: 1fr;
    min-height: 0;
    height: auto;
    align-items: center;
  }
  .hero-trust { max-width: none; }
  .hero-home-copy { max-width: 100%; padding-block: var(--sp-7) var(--sp-6); }

  .hero-home-media { position: absolute; inset: 0; width: 100%; min-height: 0; margin: 0; }
  .hero-home-media img:not(.hero-home-backdrop),
  .hero-home-media .img-placeholder {
    object-fit: cover;
    object-position: center;
  }
  /* The stacked photo fills the section, so the blurred fill has nothing to
     hide behind the sharp copy. */
  .hero-home-backdrop { display: none; }
  .hero-home-media::before { display: none; }
  /*
   * Measured against the hero photograph: at these stops the worst-case
   * contrast for white body text over the brightest part of the picture is
   * 5.6:1, comfortably past the 4.5:1 AA needs, while 32% of the photograph
   * still shows through. Loosening them to .62 in the middle drops it to
   * 4.6:1 — fine for this photo, no margin at all for a brighter one on a
   * service page.
   */
  .hero-home-media::after {
    display: block;
    background: linear-gradient(180deg,
      rgba(13, 36, 64, .80) 0%,
      rgba(13, 36, 64, .68) 42%,
      rgba(13, 36, 64, .86) 100%);
  }

  /* Light-on-dark copy to match the scrim. */
  .hero-home .eyebrow { color: var(--accent-400); }
  .hero-home h1 { color: #fff; }
  .hero-home-sub { color: rgba(255, 255, 255, .88); }
  .hero-home .post-meta,
  .hero-home .post-meta time { color: rgba(255, 255, 255, .82); }
  .hero-trust {
    border-top-color: rgba(255, 255, 255, .22);
    border-bottom-color: rgba(255, 255, 255, .22);
  }
  .hero-trust-item .icon { color: var(--accent-400); }
  .hero-trust-item span { color: #fff; }
  /* The reviews hero shows the average rating in the copy block, so it
     inverts with everything else — dark navy on a dark scrim was invisible. */
  .hero-rating-text { color: rgba(255, 255, 255, .85); }
  .hero-rating-text strong { color: #fff; }
  /* The navy phone button would disappear into a navy scrim. */
  .hero-home .btn-phone {
    background: rgba(255, 255, 255, .1);
    border: 1px solid rgba(255, 255, 255, .45);
    backdrop-filter: blur(2px);
  }
  .hero-home .btn-phone:hover { background: rgba(255, 255, 255, .18); }
  .hero-home .btn-outline { color: #fff; border-color: rgba(255, 255, 255, .5); }
  .hero-home .btn-outline:hover { background: rgba(255, 255, 255, .12); color: #fff; }

  /*
   * iOS Safari zooms the page in whenever a focused field is smaller than 16px,
   * and the visitor has to pinch back out to carry on. On a site whose entire
   * job is getting a quote form completed, that is a conversion problem rather
   * than a cosmetic one.
   */
  .field input,
  .field select,
  .field textarea { font-size: 1rem; }

  /*
   * 12px floor on the conversion elements. These are all touch widths, and the
   * sticky bar and the phone button's caption were rendering at 11px — the two
   * things a visitor on a phone is most likely to be reaching for.
   * Desktop typography is left exactly as approved.
   */
  .mobile-bar-item { font-size: 0.75rem; }
  .btn-stack small { font-size: 0.75rem; }

  /* Touch targets. A 21px link is a miss waiting to happen; 44px is the size
     both Apple and Google publish as the minimum. */
  .dropdown-list a { min-height: 44px; }
  .footer-list li, .footer-contact li { margin-bottom: 0; }
  .footer-list a { display: block; padding-block: 0.55rem; }
  .footer-legal a { display: inline-block; padding-block: 0.4rem; }
  .breadcrumb-item a { display: inline-block; padding-block: 0.35rem; }
  .why-grid { grid-template-columns: 1fr; gap: var(--sp-5); min-height: 0; }
  .why-grid > *:not(.why-media) { grid-column: auto; }
  .why-media {
    position: relative;
    left: auto;
    top: auto;
    bottom: auto;
    width: auto;
    margin-inline: calc(var(--sp-5) * -1);
    aspect-ratio: 16 / 9;
  }
  .why-media img, .why-media .img-placeholder { border-radius: 0; }
  .serve-grid { grid-template-columns: 1fr; gap: var(--sp-6); }
  .process-row { grid-template-columns: repeat(3, 1fr); gap: var(--sp-5); }
  .process-item:nth-child(3n)::after { display: none; }
  .contact-grid, .contact-grid-reverse { grid-template-columns: 1fr; gap: var(--sp-5); }
  .reviews-grid { grid-template-columns: 1fr; gap: var(--sp-5); }
  .reviews-intro { text-align: center; }
  .reviews-intro .stars { justify-content: center; }
  .cta-gold-inner { grid-template-columns: 1fr; text-align: center; justify-items: center; }
  .cta-gold-media { display: none; }
  .cta-gold-actions { justify-content: center; }
}

/* ---------- Small tablet ---------- */
@media (max-width: 860px) {
  :root { --fs-4xl: 2.1rem; --fs-3xl: 1.75rem; --fs-2xl: 1.5rem; }

  .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .project-grid, .review-wall { grid-template-columns: repeat(2, 1fr); }
  .steps-4, .steps-5 { grid-template-columns: repeat(2, 1fr); }
  .section { padding-block: var(--sp-7); }
  .cta-band-inner { flex-direction: column; align-items: flex-start; }
  .footer-top { grid-template-columns: 1fr 1fr; }
  .footer-top .footer-col:last-child { grid-column: auto; }
  .topbar-item:first-child { display: none; }
  .topbar-inner { justify-content: center; }

  .service-strip, .service-strip-wrap { grid-template-columns: repeat(2, 1fr) !important; }
  .city-cards { grid-template-columns: 1fr; }
  .review-cards { grid-template-columns: 1fr; }
  .blog-cards { grid-template-columns: 1fr; }
  .why-list { grid-template-columns: 1fr; }
  .process-row { grid-template-columns: repeat(2, 1fr); }
  .process-item::after { display: none !important; }
  .heading-rule::before, .heading-rule::after { width: 28px; }
}

/* ---------- Phone ---------- */
@media (max-width: 600px) {
  :root { --fs-4xl: 1.85rem; --fs-3xl: 1.55rem; --fs-base: 1rem; --sp-8: 3rem; }

  .container { padding-inline: var(--sp-4); }

  /*
   * A bleed to the screen edges is pulled out by the container's padding, and
   * the padding changes here — so the bleed has to change with it. Left at the
   * -sp-5 set above, the photograph hung 8px past the viewport on each side.
   */
  .why-media { margin-inline: calc(var(--sp-4) * -1); }

  /* Shorter hero on a phone: there is less copy on screen to fill it. */
  .hero-home { min-height: 26rem; }

  /* The compact form sets its own smaller size, so the floor has to be
     matched on specificity to beat it. */
  .form-legal,
  .quote-mini .form-legal { font-size: 0.75rem; }

  /* The compact form's 40px fields are below the touch minimum too. */
  .quote-mini .field input,
  .quote-mini .field select { min-height: 46px; }

  /* Remaining touch targets: footer contact rows, legal links, the social
     icons and the dropdown's "view all" link were all in the 21-34px range. */
  .footer-list a { padding-block: 0.65rem; }
  .footer-contact li { padding-block: 0.4rem; }
  .footer-contact a { display: inline-block; padding-block: 0.3rem; }
  .footer-legal a { padding-block: 0.55rem; }
  .footer-social a { display: inline-flex; padding: 0.6rem; }
  .dropdown-foot .dropdown-all { display: inline-flex; align-items: center; min-height: 44px; }
  .topbar-phone a { display: inline-block; padding-block: 0.5rem; }

  /* Checklists are used as navigation on the location pages — twelve service
     links at 25px each. Inline links inside running prose are left alone:
     padding them out to 44px would break the paragraph they sit in. */
  .checklist a { display: inline-block; padding-block: 0.55rem; }
  .breadcrumb-item a { padding-block: 0.5rem; }

  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
  .project-grid, .review-wall, .project-gallery { grid-template-columns: 1fr; }
  .rating-stars label .icon { width: 34px; height: 34px; }
  .steps-4, .steps-5 { grid-template-columns: 1fr; }
  .checklist-2 { grid-template-columns: 1fr; }
  .trust-grid { grid-template-columns: 1fr; }

  .form-grid { grid-template-columns: 1fr; }

  .hero-inner { padding-block: var(--sp-6); }
  .hero-sub { font-size: var(--fs-base); }
  .hero-actions .btn { width: 100%; }
  .hero-assurance { gap: var(--sp-3); flex-direction: column; }

  .quote-card-head, .quote-card-body { padding: var(--sp-4); }

  .btn { width: auto; }
  .btn-row .btn { flex: 1 1 100%; }
  .cta-band-actions { width: 100%; }
  .cta-band-actions .btn { flex: 1 1 100%; }

  .footer-top { grid-template-columns: 1fr; gap: var(--sp-6); }
  .footer-bottom-inner { flex-direction: column; align-items: flex-start; gap: var(--sp-2); }
  .footer-legal { flex-wrap: wrap; gap: var(--sp-3); }

  .error-code { font-size: 3.5rem; }

  .service-strip, .service-strip-wrap { grid-template-columns: 1fr !important; gap: var(--sp-2); }
  /* The sliding strip keeps its column tiles — the row layout below is for the
     stacked grids, and a row tile in a marquee would be far too wide to read
     as it passes. Two and a bit tiles on screen at 390px. */
  .service-marquee .service-tile { flex: 0 0 165px; width: 165px; }
  .service-tile { flex-direction: row; text-align: left; align-items: center; gap: var(--sp-4); }
  .service-marquee .service-tile { flex-direction: column; text-align: center; }
  .service-tile-icon { width: 40px; height: 40px; margin-bottom: 0; }
  .svc-icon { width: 38px; height: 38px; }
  .service-tile h3 { margin-top: 0; }
  .process-row { grid-template-columns: 1fr; gap: var(--sp-4); }
  .hero-trust { grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
  .help-box { flex-direction: column; text-align: center; }
  .heading-rule { gap: var(--sp-3); }
  .heading-rule h2 { font-size: var(--fs-xl); }
  .cta-gold-actions .btn { flex: 1 1 100%; }
}

/* ---------- Very small phone ---------- */
@media (max-width: 380px) {
  .brand-text strong { font-size: 0.95rem; }
  /* Shrink the icon and the padding rather than the label — the label is what
     makes the button unambiguous, and these three are the site's primary
     conversion path. 12px is the floor. */
  .mobile-bar-item { font-size: 0.75rem; padding-inline: 2px; gap: 1px; }
  .mobile-bar-item .icon { width: 18px; height: 18px; }
}
