/**
 * SUREFLAP-2281 - "Find an installer" (/where-to-buy/recommended_fitters).
 *
 * This page used to carry its CSS in a <style> block inside the template, which
 * Blade emitted BEFORE <!DOCTYPE html>. That put the whole page in quirks mode
 * (document.doctype null, document.compatMode "BackCompat"), where Chromium
 * ignores ::-webkit-scrollbar among other things - see SUREFLAP-2384. Moving the
 * rules into this sheet, loaded from the cssjs section in <head>, is what puts
 * the page back in standards mode.
 *
 * Only this page loads it, so selectors do not need defensive scoping, but they
 * are named for their component rather than their position.
 */
/* ---------------------------------------------------------------- lookup ---- */
/* County name and its installer count on one row, count to the right, so a
   column of counts is scannable while typing. */
.fittersListItem {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.fittersListCount {
  padding-left: 14px;
  font-size: 0.85em;
  opacity: 0.75;
  white-space: nowrap;
}
/* Counties with nobody yet stay listed but read as unavailable, so a visitor can
   see we know about their county and simply have no installer there - rather than
   the county being absent and the search looking broken. */
.fittersListItemEmpty .fittersListCounty {
  opacity: 0.6;
}
.fittersListItemEmpty .fittersListCount {
  font-style: italic;
}
/* Ten suggestions stand 352px tall, which runs off the bottom of a short phone
   screen. Cap the panel at six and a half rows - a row deliberately clipped in
   half is the clearest signal that there is more below. */
.fittersListClass {
  max-height: 208px;
  overflow-y: auto;
  /* Scrolling the end of the list must not start scrolling the page. */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
/* Explicit widths stop WebKit and Blink using an overlay scrollbar, which is
   invisible until touched. #657f91 is the colour the list already uses for a
   hovered row.

   These rules were definitely inert while the page was in quirks mode, because
   Chromium does not honour ::-webkit-scrollbar there, and that blocker is now
   gone. Whether they actually paint is NOT verified: headless Chromium draws
   overlay scrollbars, so a plain scrolling div measures 0px of gutter too, and
   the 4px on this list turns out to be its own 2px borders. So treat these as
   best-effort - the affordance that is measured to work is the half-clipped row
   plus the shading below, which also covers iOS where no CSS can pin a scrollbar
   open. */
.fittersListClass::-webkit-scrollbar {
  width: 10px;
}
.fittersListClass::-webkit-scrollbar-track {
  background: #ececec;
  border-radius: 7px;
}
.fittersListClass::-webkit-scrollbar-thumb {
  background: #657f91;
  border: 2px solid #ececec;
  border-radius: 7px;
}
/* The scrollbar cannot be the only affordance: iOS overlay scrollbars are
   transient and no CSS pins them open. So a half-clipped row plus this shading
   carries it there. Inset shadows do not scroll with the content, so this stays
   pinned to the bottom edge. The outer shadow from addedCss.css is repeated
   because box-shadow does not merge. Spread decides how wide the visible band
   is: at -14px it was measurably present but far too tight to notice. */
.fittersListClass.fittersListHasMore {
  box-shadow: inset 0 -20px 16px -8px rgba(0, 0, 0, 0.28), 0px 2px 8px #d4d4d4;
}
/* 🚨 The lookup box carried 30px of dead space beneath it, and not from anything
   on this page: fa-subscribe_save.css sets

     @media screen and (min-width: 767px) {
       input[type="text"], ... { margin-bottom: 30px; }
     }

   which lands on every text input on the site. (Below 767px the same sheet still
   applies 15px through `margin: 0 0 15px`.) Keyed off the id so the FormAssembly
   sheet cannot outrank it whatever the load order, and set at every width. */
#fittersLookup {
  margin-bottom: 0;
}
/* The "we don't recognise that place" message, as plain text under the search box.

   It was an absolutely positioned tooltip in addedCss.css - grey panel, border, a
   CSS pointer, and a question-mark PNG as a background image. The icon was both
   sized (12%) and placed (10.5%) in percentages of the box while its gutter was a
   fixed 58px, so the longer two-line copy widened the box, grew the icon and slid
   it on top of the text. Undone here rather than patched: it sits in the flow
   under the input, in the white the rest of the hero uses. */
.noResultsDiv {
  position: static;
  max-width: 520px;
  margin: 12px auto 0;
  /* A hairline rather than the old panel: enough to mark the message off from
       the hero behind it without reading as a tooltip. Semi-transparent white so
       it sits on the photograph rather than cutting a hard box out of it, and
       padding so the text is not touching the rule. */
  padding: 10px 14px;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 6px;
  background: none;
  text-align: center;
}
/* The tooltip's pointer. */
.noResultsDiv:before {
  content: none;
  display: none;
}
.noResultsDiv p {
  margin: 0;
  color: #fff;
}
.fitter_geolocate_container {
  text-align: center;
  color: #fff;
}
.fitter_geolocate {
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  border: 2px white solid;
  padding: 9px;
  border-radius: 6px;
  background-color: #328ea7;
  margin-top: 10px;
  color: #fff;
}
.fitter_geolocate_message {
  margin: 10px 0 10px 0;
  padding: 10px;
  border: solid 1px white;
  background-color: #f74a4a;
  border-radius: 10px;
  display: none;
}
/* --------------------------------------------------------------- results ---- */
/* The results used to be one <table>: the "Become a listed installer" box lived
   in a cell with rowspan = installer count + 1, which the controller had to
   calculate and the AJAX fragment had to re-send on every search. Flex removes
   both - the box is page furniture that stays put, and a search only replaces
   the cards. */
/* The heading is a sibling of the columns, not a child of one, so the aside and
   the cards start level. .fittersListings already supplies the 940px centred
   box, so both only need the matching side padding to line up with each other. */
.fittersResultsHeading {
  margin: 40px 0 16px 0;
  padding: 0 10px;
}
.fittersResults {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  /* The bottom padding is the gap between the last card and the site footer,
       which used to be flush against it (Charlie, 13 Oct). */
  padding: 0 10px 60px 10px;
  box-sizing: border-box;
}
.fittersAside {
  flex: 0 0 250px;
}
/* min-width:0 is load-bearing: a flex item's floor is its content's intrinsic
   width, so without it one long unbroken URL widens the column and pushes the
   card past the edge of the page - which is exactly what the old table did. */
.fitterCards {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
/* ------------------------------------------------------------ one record ---- */
.fitterCard {
  border: 1px solid #d2d3d4;
  border-radius: 7px;
  padding: 20px;
  color: #657f91;
  box-sizing: border-box;
  transition: box-shadow 0.18s ease, border-color 0.18s ease;
}
/* Pointing at a card lifts it off the page and picks out its name in the link
   teal the page already uses (#16a6b6).

   :focus-within as well as :hover, so tabbing to a link inside a card gives a
   keyboard user the same cue a mouse user gets.

   Deliberately no cursor:pointer - the card itself does nothing when clicked,
   only the links inside it do, and a pointer would promise otherwise. Only
   colour and shadow change: the name's weight is set below and left alone here,
   because animating weight would reflow the text under the cursor. */
.fitterCard:hover,
.fitterCard:focus-within {
  border-color: #16a6b6;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.13);
}
.fitterCard:hover .fitterCardName,
.fitterCard:focus-within .fitterCardName {
  color: #16a6b6;
}
@media (prefers-reduced-motion: reduce) {
  .fitterCard {
    transition: none;
  }
}
/* Logo beside the contact details. The areas covered are deliberately NOT in
   this row - see fitter-card.blade.php - so they get the full width of the card
   rather than the column left over beside a 103px logo. */
.fitterCardTop {
  display: flex;
  align-items: flex-start;
  /* 35px rather than 20px. The addresses afford it now that the website reads
       "AylesburyGlazing.Com" instead of the full URL. */
  gap: 35px;
}
.fitterCardMedia {
  flex: 0 0 103px;
}
.fitterCardBody {
  flex: 1 1 auto;
  min-width: 0;
}
/* 600 rather than bold: fonts.css ships a real Source Sans Pro semibold file, so
   this is a drawn weight and not a browser-synthesised one, which at 21px is the
   difference between crisp and smeared. It was 400, which left the name no
   heavier than the address under it. */
.fitterCardName {
  margin: 0 0 14px 0;
  color: #657f91;
  font-size: 21px;
  font-weight: 600;
  line-height: 1.2;
  transition: color 0.18s ease;
}
/* Contact details are a list because that is what they are. The gap is the
   breathing room between the email, the website and the phone numbers - they
   used to be table rows 5px apart, with the website floated up alongside the
   email. */
.fitterContact {
  list-style: none;
  /* No bottom margin: the areas block below owns the gap, so a card with no
       areas listed does not end in dead space. */
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 11px;
}
.fitterContact li {
  margin: 0;
  /* A URL or a long address is a single unbreakable "word". */
  overflow-wrap: break-word;
}
.fitterAreas {
  margin: 16px 0 0 0;
}
.fitterAreasTitle {
  margin: 0 0 4px 0;
  font-weight: bold;
}
.fitterAreasList {
  margin: 0;
}
/* ------------------------------------------------------------- monogram ---- */
.fitterLogoImg {
  display: block;
  width: 103px;
  height: auto;
  border-radius: 10px;
}
/* Installers with no logo on file get their initials instead, so the slot reads
   as a deliberate blank rather than a broken image. Matches the logo geometry.
   Centred with line-height rather than flex so it cannot be thrown off by the
   font metrics of a single line of text. */
.fitterMonogram {
  display: block;
  width: 103px;
  height: 103px;
  line-height: 103px;
  border-radius: 10px;
  text-align: center;
  font-size: 58px;
  font-weight: bold;
  color: #fff;
  text-decoration: none;
}
/* The tile is wrapped in the installer's website link, whose colour and
   underline would otherwise win. */
a .fitterMonogram {
  color: #fff;
  text-decoration: none;
}
/* Twelve muted pastels. Every one carries white text at 3.40:1, which clears the
   WCAG AA 3:1 bar for large bold text - a true pastel (#f2c0cd) manages only
   1.59:1 against white and is unreadable. Generated and contrast-checked by
   .scratch-2281/palette_tune.py.

   Deliberately NOT in hue order. fitter-block.blade.php starts from a colour
   hashed off the installer's name and steps to the next slot when that one is
   taken, so consecutive slots are what a clash falls back to - in hue order that
   handed out moss, then sage, then teal, and a county came out three shades of
   the same green. Listed every fifth hue instead (5 and 12 share no factor, so it
   still visits all twelve), which puts at least 118 degrees between any two
   neighbouring slots. */
.fitterTile0 {
  background-color: #bc7889;
}
/* dusty rose   345 */
.fitterTile1 {
  background-color: #4c9799;
}
/* soft teal    182 */
.fitterTile2 {
  background-color: #b079ac;
}
/* mauve        305 */
.fitterTile3 {
  background-color: #759550;
}
/* moss          88 */
.fitterTile4 {
  background-color: #8886be;
}
/* periwinkle   242 */
.fitterTile5 {
  background-color: #bb7b68;
}
/* clay          14 */
.fitterTile6 {
  background-color: #6290b2;
}
/* dusty blue   205 */
.fitterTile7 {
  background-color: #b6789c;
}
/* plum rose    325 */
.fitterTile8 {
  background-color: #569877;
}
/* sage         150 */
.fitterTile9 {
  background-color: #9a80b8;
}
/* lavender     268 */
.fitterTile10 {
  background-color: #a98648;
}
/* warm ochre    38 */
.fitterTile11 {
  background-color: #7b8bb1;
}
/* slate blue   222 */
/* ------------------------------------------- become an installer: modal ---- */
/* 🚨 Above the site header, which carries z-index 99999 while a Bootstrap modal
   only gets 1050. Measured: at 768px the header covered the close chip, and
   document.elementFromPoint() on the middle of the button returned
   .mobile-header - so the one control that dismisses the dialog could not be
   clicked at all. Scoped to this modal so no other dialog's stacking changes. */
.installerModal {
  z-index: 100010;
}
/* Anchors the close button, which sits outside the white panel. */
.installerModal .modal-dialog {
  position: relative;
  width: auto;
  max-width: 680px;
  /* Top margin leaves room for the close chip to sit above the panel edge
       without being clipped by the viewport. The bottom needs no such allowance,
       so it is tighter - part of getting the whole dialog inside a 919px-tall
       window without scrolling. */
  margin: 52px auto 36px;
}
/* Outside the content, over the backdrop, as asked. The icon itself is mid-grey
   so it needs the white chip to read against a dark overlay; the shadow keeps it
   from merging into a pale page behind. */
.installerModalClose {
  position: absolute;
  top: -20px;
  right: -20px;
  z-index: 2;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
  cursor: pointer;
  line-height: 0;
  transition: background-color 0.15s ease;
}
.installerModalClose img {
  display: inline-block;
  width: 28px;
  height: 28px;
  vertical-align: middle;
}
.installerModalClose:hover,
.installerModalClose:focus {
  background: #eef1f2;
}
/* The white panel: a border of its own and room to breathe.

   Selector is deliberately four classes deep. sureflap.css sets
   `.modal .modal-dialog .modal-content { padding: 5px }` at four breakpoints,
   which outranks a single class whatever the load order, so padding here was
   silently losing - measured 5px against the 42px asked for. Matching its depth
   and then some wins on specificity rather than on which file happens to load
   last. */
.modal.installerModal .modal-dialog .installerModalContent {
  background: #fff;
  border: 1px solid #d2d3d4;
  border-radius: 10px;
  /* A little more above the title than beside it, so the heading is not crowded
       against the panel edge. */
  padding: 52px 46px 46px;
}
.installerModalTitle {
  margin: 0 0 34px 0;
  text-align: center;
  color: #16a6b6;
  font-size: 30px;
  font-weight: 600;
  line-height: 1.2;
}
.installerModalBody {
  color: #657f91;
  font-size: 16px;
}
/* The copy opens with its own hook line, which arrives as an <h2> inside the
   language string. Sized below the dialog's <h1> so the two read as a title and a
   lead rather than competing. */
.installerModalBody h2 {
  margin: 0 0 16px 0;
  color: #657f91;
  font-size: 21px;
  font-weight: 600;
  line-height: 1.25;
}
.installerModalBody p {
  margin: 0 0 14px 0;
  /* 1.1em of the body's 16px, so ~17.6px. Black rather than the page's slate
       (#657f91) - this is the one block of prose a tradesperson is asked to read
       and act on. The links inside keep their own teal. */
  font-size: 1.1em;
  color: #000;
}
.installerModalBody p:last-child {
  margin-bottom: 0;
}
/* The montage: the flap going in leads across the full width, then three finished
   installations beneath it.

   The cells carry the aspect ratio and the images fill them with object-fit,
   rather than letting each image size itself. The three photographs are 16:9, 3:2
   and 10:7, so left to themselves the row came out ragged; cropping them to a
   common 4:3 keeps the row square and loses nothing important from any of them.

   🚨 Every ratio is escaped. LESS reads a bare slash as division - see the note on
   grid-column below, where `1 / -1` compiled to `-1`. */
.installerModalMontage {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin: 26px 0 0 0;
  padding: 0;
  list-style: none;
}
.installerModalMontage li {
  margin: 0;
  aspect-ratio: 4 / 3;
}
/* 🚨 Escaped on purpose. Written plainly as `grid-column: 1 / -1` the LESS
   compiler reads the slash as division and emits `grid-column: -1`, which puts
   this image on the last grid line instead of spanning the row: measured, the
   three columns collapsed to 18px each and a fourth implicit 500px column
   appeared. The ~"" keeps the value verbatim. */
/* `li.` on purpose: the rule above is `.installerModalMontage li`, a class plus a
   type, which outranks a lone class - so the 4:3 crop was winning here and the
   lead was coming out 586x440 instead of its own 3:2. */
.installerModalMontage li.installerModalMontageLead {
  grid-column: 1 / -1;
  /* The lead is 500x334, so it keeps its own shape rather than being cropped. */
  aspect-ratio: 500 / 334;
  /* Narrowed and centred rather than cropped: at full panel width it stood 391px
       tall and pushed the bottom row of the montage out of a 919px-tall window.
       Scaling the frame down keeps the whole shot - cropping it to a shorter ratio
       would have cut the top off the flap. */
  max-width: 55%;
  margin: 0 auto;
}
.installerModalMontage img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 6px;
}
/* Below this the dialog is close to the viewport edges, so the close chip is
   pulled inwards - at -20px it would sit off-screen - and the panel's padding
   comes down with it. */
@media (max-width: 760px) {
  .installerModal .modal-dialog {
    margin: 56px 30px;
  }
  .installerModalClose {
    top: -20px;
    right: -12px;
  }
  /* Same specificity battle as above. */
  .modal.installerModal .modal-dialog .installerModalContent {
    padding: 28px 24px 30px;
  }
  .installerModalTitle {
    font-size: 24px;
    margin-bottom: 18px;
  }
}
/* ----------------------------------------------------------- responsive ---- */
/* The aside is the first thing to go: below this the same content is shown
   full-width under the results by .belowFittersOptions. */
@media (max-width: 900px) {
  .fittersAside {
    display: none;
  }
  .fittersResultsHeading {
    margin-top: 20px;
    text-align: center;
  }
}
@media (max-width: 480px) {
  .fitterCard {
    padding: 15px;
  }
  .fitterCardTop {
    gap: 15px;
  }
}
/* Logos and tiles both step down here, as they did before. */
@media (max-width: 400px) {
  .fitterCardMedia {
    flex: 0 0 70px;
  }
  .fitterLogoImg {
    width: 70px;
  }
  .fitterMonogram {
    width: 70px;
    height: 70px;
    line-height: 70px;
    font-size: 39px;
  }
}
