/* ==========================================================================
   JMV Water Solutions — responsive layer
   Loaded after style.css. Breakpoints follow the approved design:
   1440/1280 desktop · 1024 laptop · 834/768 tablet · 430–390 mobile · 320 floor
   ========================================================================== */

/* --------------------------------------------------------------------------
   Wide desktops — the container grows with the viewport so laptops and large
   monitors use the available width, while keeping professional side margins.
   Text blocks stay capped in `ch` units, so line length never suffers.
   -------------------------------------------------------------------------- */
@media (min-width: 1400px) {
  :root {
    --container: min(1360px, 92vw);
    --gutter: 1.75rem;
  }
}
@media (min-width: 1600px) {
  :root {
    --container: min(1480px, 91vw);
    --gutter: 2rem;
  }
}
@media (min-width: 1800px) {
  :root { --container: min(1600px, 90vw); }
  /* At this width the widest article title fits two lines rather than
     three. See `#bd-hero .bd-hero__pending` in style.css. */
  #bd-hero .bd-hero__pending { min-height: 163px; }      /* floor 226px @1920 */
}
@media (min-width: 2200px) {
  :root { --container: 1720px; }
}

/* The droplet family grid grows with the container above the mobile
   breakpoint, so the height held for it before it mounts grows too.
   See `#td-circles:empty` in style.css. */
@media (min-width: 992px) {
  #td-circles:empty { min-height: 405px; }
  #tech-circles:empty { min-height: 190px; }
}
@media (min-width: 1400px) {
  #td-circles:empty { min-height: 490px; }
}

/* --------------------------------------------------------------------------
   ≤ 1280px — tighten the wide gaps
   -------------------------------------------------------------------------- */
@media (max-width: 1280px) {
  .primary-nav__list { gap: 0; }
  .primary-nav__link { padding-inline: .55rem; }
  .site-header__inner { gap: var(--sp-4); }
}

/* --------------------------------------------------------------------------
   ≤ 1199px — laptop / small desktop
   -------------------------------------------------------------------------- */
@media (max-width: 1199px) {
  /* Keep one primary CTA in the header so the bar never overflows */
  .header-actions .btn-desktop-only { display: none; }

  /* The article heading has the whole container to itself here, and the
     lead runs narrower, so the block it needs is smaller again. */
  #bd-hero .bd-hero__pending { min-height: 195px; }      /* floor 258px @700 */

  /* Below this width the contents rail would squeeze the reading column,
     so the article takes the whole container and the rail is dropped. */
  .article-layout,
  .article-layout:has(> .article-aside:not([hidden])) {
    grid-template-columns: minmax(0, 1fr);
  }
  .article-aside { display: none; }

  .site-footer__main {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .footer-brand { grid-column: 1 / -1; }

  /* Smaller hero visual so it never crowds the headline */
  .hero-visual { width: min(30%, 320px); }

  /* Narrower family rail so the product columns keep their width. This is
     the tightest the product cards ever get — below 992px the family panel
     stacks and the cards take the full shell — so the rail gives back the
     80px that was making the longest product names wrap to a third line. */
  .mega--split .mega__inner { grid-template-columns: minmax(0, 210px) minmax(0, 1fr); }
  .family { grid-template-columns: minmax(0, 240px) minmax(0, 1fr); }

  /* Five industry tiles need a full desktop to hold their names */
  .industry-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* --------------------------------------------------------------------------
   Grid step-downs — every card grid narrows on the same ladder, so a row of
   cards holds the same number of columns whatever page it is on.
     .grid--cards   3 → 2 (991) → 1 (575)
     .grid--triple  3 → 2 (991) → 1 (480)
     .grid--pair    2 → 1 (767)
     .grid--pair-lg 2 → 1 (991)   [page columns, not cards]
   The auto-fit grids (.grid--3, .grid--4) step down on their own.
   -------------------------------------------------------------------------- */
@media (max-width: 991px) {
  .grid--cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid--triple { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid--pair-lg { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 767px) {
  .grid--pair { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 575px) {
  .grid--cards { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 480px) {
  .grid--triple { grid-template-columns: minmax(0, 1fr); }
}

/* --------------------------------------------------------------------------
   ≤ 991px — tablet: switch to mobile navigation
   -------------------------------------------------------------------------- */
@media (max-width: 991px) {
  :root {
    --header-h: 65px;
    /* Topbar (34px) + the shorter header bar (81px) */
    --chrome-h: 115px;
  }
  .primary-nav { display: none; }
  .nav-toggle { display: inline-flex; }
  .site-header__inner { justify-content: space-between; min-height: 64px; }

  /* The family panel stacks, and its summary turns side by side to save the
     height: photo on the left, the naming block and description on the
     right. Placed explicitly, because the source order is head → photo →
     description and auto-placement would break the pairing. */
  .family { grid-template-columns: 1fr; }
  .family__aside {
    grid-template-columns: minmax(0, 240px) minmax(0, 1fr);
    align-items: start;
    gap: var(--sp-4) var(--sp-5);
  }
  .family__aside > .media { grid-area: 1 / 1 / 3 / 2; }
  .family__head { grid-area: 1 / 2 / 2 / 3; }
  .family__text { grid-area: 2 / 2 / 3 / 3; }

  /* Stacked from here down, so the hero is roughly twice as tall and the
     placeholder reserves accordingly. See `.pd-hero__pending`. */
  .pd-hero { grid-template-columns: 1fr; }
  .pd-hero__pending { min-height: 1080px; }
  .pd-specs { grid-template-columns: minmax(0, 1fr); }
  .contact-layout { grid-template-columns: 1fr; }

  /* A split page hero stacks: two columns leave the headline about 170px
     of width on a phone, and the droplet grid beside it cannot shrink. */
  .page-hero--split .page-hero__inner { grid-template-columns: minmax(0, 1fr); }
  .page-hero__drops { max-width: 420px; }

  /* ---- The numbered flow, turned through ninety degrees ---------------
     Six steps will not sit side by side on a tablet, and five full
     sentences certainly will not, so from here down the flow runs vertically
     instead: the steps down the page, the number beside each one.

     What runs down with them is the point. The dashed connector and the
     travelling droplet used to be treated as desktop-only decoration — the
     connector was switched off here, but the droplet was left animating
     sideways across the top of the list, over a line that was no longer
     there. The steps read downwards and the flow appeared to run across
     them, which is not what the same page does on a desktop.

     So the connector and the droplet rotate with the layout. Same droplet,
     same dashed line, same fourteen seconds, same fade in and out, and the
     same sequence: it enters at step 01 and travels through the steps in
     order to the last one. Only the axis changes, because that is the one
     thing a phone cannot keep.

     Applies to both flows — the home page's short labels and the technology
     pages' sentences — so the two read identically. */
  .process,
  .process.process--wide {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--sp-5);
    /* A single column of short labels left sitting in a 940px container
       reads as a narrow strip against a lot of empty page. Capped and
       centred it reads as a deliberate list — and on a phone the cap is
       wider than the container, so it simply has no effect there. */
    max-width: 42rem;
    margin-inline: auto;
  }
  .process li {
    grid-template-columns: var(--flow-col) minmax(0, 1fr);
    align-items: center;
    justify-items: start;
    column-gap: var(--sp-4);
    text-align: left;
  }
  .process .process__disc { grid-row: span 2; width: var(--flow-col); }

  /* The connector, down the centre of the number column. Inset top and
     bottom by the same 8% the desktop line is inset left and right, so it
     ends just short of the first and last droplets exactly as it does
     there. */
  .process::before {
    display: block;
    top: 8%;
    bottom: 8%;
    left: calc(var(--flow-col) / 2);
    right: auto;
    border-top: 0;
    border-left: 1.5px dashed var(--border-deepest);
  }
  /* The droplet travels down that line. `top` rather than a transform
     because the distance is the height of the list, which is content
     dependent and has no CSS length — a percentage of the list is the only
     expression of it. It is one nine-pixel absolutely positioned
     pseudo-element, so the layout it costs per frame is negligible, and
     `prefers-reduced-motion` switches it off entirely (see style.css). */
  .process::after {
    top: 8%;
    left: calc(var(--flow-col) / 2 - 4.5px);
    animation-name: process-travel-y;
  }

  .hero-home__inner { min-height: 0; }

  /* Hero visual on tablets and phones.
     Beside the copy there is no room for it — that is why it used to be
     hidden outright — so instead it leaves the absolute layer and becomes a
     block of its own below the copy. The halo, the rounded frame and the
     crossfade are the desktop ones untouched; only the placement changes.
     `.hero` turns into a column so the visual can be ordered after the
     copy; the decorative water layers inside it are absolutely positioned
     and so stay out of that flow. */
  .hero { display: flex; flex-direction: column; }
  .hero-home__inner { order: 1; }
  .hero-visual {
    position: static;
    order: 2;
    z-index: 2;
    width: min(100%, 460px);
    margin: 0 auto;
    padding-inline: var(--gutter);
    padding-bottom: clamp(2rem, 1.2rem + 3.6vw, 4rem);
    transform: none;
  }
  /* The frame keeps the 7:8 of the photographs at every width, so the unit
     is shown whole and at full width — the banners are transparent cut-outs,
     which have no background to crop into and blend on their own. The splash
     behind them is what ties them into the wash, exactly as on desktop, so
     no extra fade is needed here. */

  /* The two floating cards hang off the desktop visual's edges. Against a
     centred block they would sit half outside the gutter, and they repeat
     figures the page states again further down. */
  .hero-visual .glass-card { display: none; }

  .hero-controls { padding-top: var(--sp-6); }

  .stats-strip__card { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5); }

  .split__orb { display: none; }
}

/* Scroll hint on the filter row once the pills stop fitting */
@media (max-width: 991px) {
  .filter-bar { position: sticky; }
  .filter-bar__inner { position: relative; flex-wrap: nowrap; overflow-x: auto; }
  /* One scrolling row instead of a wrapped block, so less height to hold */
  #product-filters:empty { min-height: 82px; }
  .filter-bar > .shell { position: relative; }
  .filter-bar > .shell::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 36px;
    background: linear-gradient(90deg, rgba(247, 250, 255, 0), var(--bg) 70%);
    pointer-events: none;
  }
}

/* --------------------------------------------------------------------------
   ≤ 834px — small tablet
   -------------------------------------------------------------------------- */
@media (max-width: 834px) {
  /* Top bar: the phone number used to be the only thing showing on a phone —
     the email address and the opening hours were both hidden, and those are
     the two things a visitor on a phone is most likely to be looking for.
     All three now show at every width, wrapping onto a second line below
     about 500px where they do not fit on one.
     What gives way instead is the strapline: it is decorative, and below
     834px keeping it forced the contact details to wrap a line earlier. The
     pipe separators go with it — once the row wraps they read as stray marks
     at the start or end of a line rather than as dividers. */
  .topbar__tagline { display: none; }
  .topbar__inner { justify-content: center; }
  .topbar__meta {
    justify-content: center;
    /* Tighter than the desktop `--sp-6`: at 390px the row has about 358px to
       work with and the three items measure 432px between them, so the gap
       is what decides whether this takes two lines or three. */
    gap: .15rem .8rem;
    text-align: center;
  }
  .topbar__sep { display: none; }

  .cta-band__inner { flex-direction: column; align-items: flex-start; }
  .cta-band__actions { width: 100%; }
  .cta-band__actions .btn-jmv { flex: 1 1 200px; }

  .flow-between { align-items: flex-start; }
}

/* --------------------------------------------------------------------------
   ≤ 767px — phones (design reference: 390px)
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {
  :root {
    --section-y: 3rem;
    --section-y-tight: 2.25rem;
    --fs-md: 1rem;
    /* Topbar (34px, one row) + the phone header bar (73px). Held from here
       rather than from 575px: the header bar shrinks at this breakpoint, so
       between 576 and 767 the old 115px reserved 8px more than the chrome
       actually takes and the page settled upwards. */
    --chrome-h: 107px;
  }

  /* Header keeps the brand and the menu button only; the sticky action bar
     carries the primary CTA (mobile design) */
  .header-actions .btn-jmv { display: none; }

  .topbar { font-size: var(--fs-xs); }
  .brand__logo { height: 48px; }
  .site-header__inner { min-height: 72px; }

  /* Hero */
  .hero-title { font-size: clamp(2rem, 1.4rem + 3.6vw, 2.75rem); }
  .hero-text { font-size: var(--fs-base); margin-bottom: var(--sp-6); }
  .hero-actions { flex-direction: column; align-items: stretch; }
  .hero-actions .btn-jmv { width: 100%; }
  .hero-segments { gap: var(--sp-2) var(--sp-4); font-size: var(--fs-xs); }
  .hero-segments li { gap: var(--sp-4); }
  .hero-controls { padding-top: var(--sp-7); gap: var(--sp-4); }
  /* Slider dots: a 44px touch target, with the active one drawn wider */
  .hero-dot { width: 28px; height: 44px; }
  .hero-dot[aria-selected="true"] { width: 52px; }
  .hero-home__inner { padding-block: var(--sp-8) var(--sp-7); }

  /* Stats — 2 × 2 cards, matching the mobile design */
  .stats-strip { padding-block: var(--sp-7) 0; }
  .stats-strip__card {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-4);
  }
  .stat { min-height: 104px; padding: var(--sp-5) var(--sp-4); border-radius: var(--card-r-sm); }
  .stat::after { top: -28px; right: -12px; width: 74px; }
  .stat__value { font-size: 1.6rem; }
  .stat__label { font-size: var(--fs-sm); }

  /* Sections & headings */
  .section-head { max-width: none; }
  .flow-between { flex-direction: column; align-items: flex-start; gap: var(--sp-4); }

  /* 21 · Products list: the category tab row is desktop/tablet only */
  .filter-bar { display: none; }
  .filter-pill { min-height: 44px; padding-inline: 1.1rem; }

  /* Product family blocks become single column, image on top */
  .family { padding: var(--sp-5); }
  /* Back to one column, in source order */
  .family__aside { grid-template-columns: minmax(0, 1fr); }
  .family__aside > .media,
  .family__head,
  .family__text { grid-area: auto; }
  .variant-grid { grid-template-columns: 1fr; gap: var(--sp-3); }
  .panel-cta { padding: var(--card-pad); }
  .panel-cta::after { display: none; }
  /* A phone shows the name and what the product is for; the applications
     line and the explore affordance belong to the wider layouts. */
  .variant-card { padding: var(--card-pad-sm); gap: var(--sp-2); }
  .variant-card__meta,
  .variant-card__foot { display: none; }

  /* Mobile product list card: image left, copy right (mobile design) */
  .product-card--mobile-row { flex-direction: row; align-items: stretch; }
  .product-card--mobile-row > .card-jmv__media { flex: none; width: 112px; }
  .product-card--mobile-row .media {
    width: 100%;
    height: 100%;
    min-height: 112px;
    aspect-ratio: auto;
    border-radius: 0;
  }
  .product-card--mobile-row .card-jmv__body { padding: var(--sp-4) var(--sp-5); gap: var(--sp-1); }
  /* A fixed number of lines per row, so the list reads as one even column.
     The selector matches the two-line reservation in style.css, which the
     row card does not need — its height comes from the thumbnail. */
  .grid > .product-card--mobile-row .card-jmv__title {
    min-height: 0;
    font-size: var(--fs-base);
    -webkit-line-clamp: 1;
    line-clamp: 1;
  }
  .product-card--mobile-row .card-jmv__text { font-size: var(--fs-sm); -webkit-line-clamp: 2; line-clamp: 2; }
  .product-card--mobile-row .chip-list { display: none; }
  .product-card--mobile-row .product-card__variants {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 1;
    line-clamp: 1;
    overflow: hidden;
    font-size: var(--fs-sm);
    color: var(--body);
  }

  /* Industries */
  .industry-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Two tiles across a phone leaves the caption 88-141px depending on the
     handset, which is narrower than the word "Pharmaceutical" at the
     desktop size — and `overflow-wrap: anywhere` duly broke it as
     "Pharmaceutica / l". The title is therefore sized from the column
     rather than from the type scale, so the longest industry name stays on
     one line all the way down to a 320px screen. `hyphens` is the backstop
     for any longer name added later: a hyphenated break reads as a word,
     a mid-word one reads as a bug. */
  .industry-grid .overlay-card__title {
    font-size: clamp(.6875rem, 3.6vw, 1rem);
    hyphens: auto;
    -webkit-hyphens: auto;
  }
  .industry-grid .overlay-card__meta { font-size: .8125rem; }


  /* Product detail */
  .pd-title { font-size: clamp(1.75rem, 1.4rem + 2.4vw, 2.25rem); }
  .pd-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pd-actions { flex-direction: column; }
  .pd-actions .btn-jmv { width: 100%; }
  .feature-list { grid-template-columns: 1fr; }

  /* The specification sheet stacks into label/value rows. Article tables
     keep their columns and scroll inside .table-wrap instead — a stacked
     cell would lose the column heading that gives it meaning. */
  /* The generic label/value sheet stacks. A model range keeps its columns —
     stacking would separate a value from the model it belongs to — and
     scrolls inside .table-wrap instead. */
  .pd-specs .spec-table:not(.spec-table--models),
  .pd-specs .spec-table:not(.spec-table--models) tbody,
  .pd-specs .spec-table:not(.spec-table--models) tr,
  .pd-specs .spec-table:not(.spec-table--models) th,
  .pd-specs .spec-table:not(.spec-table--models) td { display: block; width: 100%; }
  .pd-specs .spec-table:not(.spec-table--models) { border-radius: var(--r-md); }
  .pd-specs .spec-table:not(.spec-table--models) tr { border-bottom: 1px solid var(--border); }
  .pd-specs .spec-table:not(.spec-table--models) tr:last-child { border-bottom: 0; }
  .pd-specs .spec-table:not(.spec-table--models) th { padding-bottom: 0; font-size: var(--fs-sm); color: var(--muted); }
  .pd-specs .spec-table:not(.spec-table--models) td { padding-top: .25rem; color: var(--ink); font-weight: 600; }
  .pd-specs .spec-table:not(.spec-table--models) tbody tr:nth-child(even) { background: var(--bg); }
  .pd-specs--wide .pd-specs__aside { grid-template-columns: 1fr; }

  /* Forms */
  .form-grid { grid-template-columns: 1fr; gap: var(--sp-4); }
  .form-card { padding: var(--sp-5); }
  .info-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* Testimonials */
  .testimonial__foot { flex-wrap: wrap; }
  .testimonial__dots { margin-left: 0; width: 100%; }

  /* Footer */
  .site-footer__main { grid-template-columns: 1fr; gap: var(--sp-7); }
  .site-footer__bottom-inner { flex-direction: column; align-items: flex-start; }
  .legal-links { gap: var(--sp-4); }

  /* Touch targets: small controls grow on phones */
  .dot-btn { width: 44px; height: 44px; }

  /* Floating actions: sticky bar replaces the desktop stack */
  .wa-fab, .quote-rail { display: none; }
  .action-bar { display: flex; }
  body.has-action-bar { padding-bottom: 84px; }

  /* Article */
  .article h2 { margin-top: var(--sp-8); }
}

/* --------------------------------------------------------------------------
   ≤ 575px
   -------------------------------------------------------------------------- */
@media (max-width: 575px) {
  /* The topbar's three contact items total about 432px of text, so somewhere
     below 500px they stop fitting one row. Left to wrap on their own the
     changeover lands wherever the text happens to measure — which moves if
     the email address or the opening hours are ever edited, and the height
     reserved for the chrome below would then be wrong at some widths. So the
     hours take their own line from this breakpoint down, by construction:
     two rows here, one row above, and `--chrome-h` can state both exactly. */
  .topbar__hours { flex-basis: 100%; }

  /* Topbar (52px, two rows) + the phone header bar (73px) */
  :root { --chrome-h: 125px; }

  /* A phone-width title runs to four or five lines, so the block held for
     it is taller again. See `#bd-hero .bd-hero__pending` in style.css. */
  #bd-hero .bd-hero__pending { min-height: 217px; }      /* floor 280px @575 */

  /* The technology row drops to two columns here, so it holds more height
     before it mounts, not less. See `#tech-circles:empty` in style.css. */
  #tech-circles:empty { min-height: 385px; }

  .filter-bar__inner { padding-block: var(--sp-3); }
  .grid { gap: var(--sp-4); }
  .client-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pd-thumbs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .also-serving { padding: var(--sp-5); }
  .card-jmv__body { padding: var(--sp-5); }
  .mobile-menu__panel { width: 100%; }
}

/* --------------------------------------------------------------------------
   ≤ 430px — iPhone Pro Max class
   -------------------------------------------------------------------------- */
@media (max-width: 430px) {
  .info-tiles { grid-template-columns: 1fr; }
  .pd-facts { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   ≤ 359px — 320px floor
   -------------------------------------------------------------------------- */
@media (max-width: 359px) {
  :root { --gutter: .875rem; }
  /* Last 16px of caption width on a 320px screen, which is what puts
     "Pharmaceutical" on one line down here too. */
  .industry-grid .overlay-card__content { padding-left: var(--sp-2); padding-right: var(--sp-2); }
  .brand__logo { height: 42px; }
  .stats-strip__card { grid-template-columns: 1fr; }
  .client-strip { grid-template-columns: 1fr; }
  .action-bar { gap: var(--sp-2); }
}

/* --------------------------------------------------------------------------
   Landscape phones — keep the sticky bar from eating the viewport
   -------------------------------------------------------------------------- */
@media (max-width: 991px) and (max-height: 480px) {
  :root { --header-h: 0px; }
  .site-header { position: static; }
  .action-bar { position: static; }
  body.has-action-bar { padding-bottom: 0; }
}

/* --------------------------------------------------------------------------
   Print
   -------------------------------------------------------------------------- */
@media print {
  .topbar, .site-header, .mobile-menu, .wa-fab, .quote-rail,
  .action-bar, .filter-bar, .cta-band, .site-footer { display: none !important; }
  body { color: #000; background: #fff; }
  .media, .overlay-card { background: #f2f2f2; }
  a { color: #000; text-decoration: underline; }
}
