/* ---------- REVIEWS ----------
   The Google reviews band, shared by every page that shows it: the homepage, the
   /areas/ hub and all forty area pages. It lived inline in index.html when the
   homepage was the only page with reviews on it; it is a file now for the same
   reason chrome.css and theme.css are files -- one copy of the rules, so a card
   that is tidied here is tidied on forty-two pages rather than one.

   Loaded after theme.css and before area.css, so it can lean on the tokens
   (--ice-soft, --gold, --line) and still be overridden by a page type's own
   layout. The markup it dresses is written by assets/reviews.js. */

/* The card vocabulary here is older than the section that now uses it: these
   were hand-typed testimonials once, and the quote-and-attribution shape was
   the right one, so the reviews band inherits it rather than inventing a second
   card. `.testi` also earns the seasonal transition in assets/theme.css by
   being named there, which a new class would have had to be added to.
   Everything below the grid is new, because a Google review carries three
   things a typed testimonial did not: a score, a reviewer, and a date. */
.testi-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;}
.testi{
  background:var(--ice-soft);border-radius:var(--radius);padding:28px 26px;
  border-left:4px solid var(--gold);
}
.testi p.quote{font-size:1.02rem;color:var(--ink);margin:0 0 16px;}
.testi p.who{font-family:'JetBrains Mono',monospace;font-size:0.82rem;color:var(--sky-deep);margin:0;}

.reviews[hidden]{display:none;}
/* The score sits beside the section heading rather than under it: a 4.9 is the
   single most persuasive thing in the band, and it should be readable without
   anybody having to get as far as the first quote. */
.reviews-head{
  display:flex;align-items:flex-end;justify-content:space-between;gap:32px;
  flex-wrap:wrap;margin-bottom:40px;
}
.reviews-head .section-head{margin-bottom:0;}
.reviews-score{
  display:flex;align-items:center;gap:16px;flex-shrink:0;
  background:var(--white);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px 22px;
}
.reviews-score .num{
  font-family:'JetBrains Mono',monospace;font-size:2.2rem;font-weight:600;
  line-height:1;color:var(--ink);
}
.reviews-score .count{
  display:block;font-size:0.84rem;color:var(--ink-soft);margin-top:7px;
}
.reviews-score .count a{color:var(--sky-deep);font-weight:600;}
/* Part stars are a gold row clipped over a grey one -- a 4.8 wants four fifths
   of the fifth star, which a half-star glyph cannot draw. The width comes from
   --pct, which is the only thing the script sets. */
.stars{position:relative;display:inline-block;line-height:0;font-size:1.05rem;}
.stars-row{display:flex;gap:3px;}
.stars-row svg{width:1em;height:1em;flex:0 0 auto;fill:currentColor;}
.stars .under{color:var(--line);}
.stars .over{
  position:absolute;top:0;left:0;overflow:hidden;
  width:calc(var(--pct,100) * 1%);color:var(--gold);
}
.testi-grid .testi{display:flex;flex-direction:column;gap:14px;padding:26px 24px;}
/* Google's terms do not allow a review to be shown without the reviewer
   attached to it, so the attribution is part of the card rather than a
   nicety: photo where they have one, initial where they have not. */
.review-who{display:flex;align-items:center;gap:12px;}
.review-avatar{
  width:38px;height:38px;border-radius:50%;flex-shrink:0;object-fit:cover;
  background:var(--white);border:1px solid var(--line);
}
.review-avatar-fallback{
  display:flex;align-items:center;justify-content:center;
  font-family:'JetBrains Mono',monospace;font-size:1rem;font-weight:600;
  color:var(--sky-deep);
}
.review-name{font-weight:700;font-size:0.96rem;margin:0;line-height:1.25;}
.review-name a{color:inherit;text-decoration:none;}
.review-name a:hover{text-decoration:underline;text-decoration-color:var(--gold);text-underline-offset:3px;}
.review-when{
  font-family:'JetBrains Mono',monospace;font-size:0.68rem;letter-spacing:0.06em;
  text-transform:uppercase;color:var(--stone);margin:3px 0 0;
}
/* The date doubles as the way through to the review itself on Google, so it is
   underlined faintly rather than left looking like plain metadata -- a link
   nobody can see is not offering anything. */
/* The way through to the review on Google, at the foot of the card and pushed
   there even when the quote is short, so a row of cards lines their links up.
   Stretched over the whole card: the card is the target and the words say where
   it goes. The reviewer's name and a linked job are lifted above it so they
   keep their own. */
.testi-grid .testi{position:relative;}
.review-google{
  margin-top:auto;align-self:flex-start;
  font-family:'JetBrains Mono',monospace;font-size:0.72rem;letter-spacing:0.06em;
  text-transform:uppercase;font-weight:700;color:var(--sky-deep);text-decoration:none;
}
.review-google::after{content:'';position:absolute;inset:0;z-index:1;border-radius:inherit;}
.review-google:focus-visible{outline:none;}
.testi:has(.review-google:focus-visible){outline:3px solid var(--gold);outline-offset:2px;}
.testi:hover .review-google{text-decoration:underline;text-decoration-color:var(--gold);text-underline-offset:3px;}
.review-name a,.review-job{position:relative;z-index:2;}
.review-body{flex:1 1 auto;}
.testi-grid .testi p.quote{font-size:0.97rem;line-height:1.55;margin:0;}
/* The mark and the link out, which together are the point of the band: every
   word above can be checked against the profile it came from. */
.reviews-foot{
  display:flex;align-items:center;gap:18px;flex-wrap:wrap;
  margin:28px 0 0;font-size:0.9rem;color:var(--ink-soft);
}
.reviews-foot a{color:var(--sky-deep);font-weight:700;}
.reviews-attrib{display:inline-flex;align-items:center;gap:7px;color:var(--stone);}
.reviews-attrib .g-ico{width:1.05em;height:1.05em;flex-shrink:0;vertical-align:-0.16em;}
.reviews-score[hidden]{display:none;}

/* The words of a review, kept together in one element. Every card has one, and
   it carries the column that used to be the card's own job (see .testi-grid
   .testi above) -- the card itself has to be free to become two columns when
   there is a job to show beside the quote. */
.review-body{display:flex;flex-direction:column;gap:14px;min-width:0;}

/* The job a review is about, where the owner has linked the two together: a few
   of that job's photographs and the way through to it on /our-work/.

   Down the right-hand side of the card, not along the bottom of it. Underneath,
   the photographs had to share one wide row, which meant cropping each to a 56px
   band -- a sliver of a picture, and rarely the part of it worth seeing. A narrow
   column gives each one a box close to the shape it already is, so what shows is
   the whole photograph at a small size.

   The column is a share of the card rather than a fixed width, clamped at both
   ends: three cards across a desktop are narrow enough that the quote needs
   nearly all of the room, and one card across a tablet is wide enough to give
   the photographs more without the quote noticing. One link around the lot, so
   the pictures and the line under them are one target rather than four. */
.testi-grid .testi-linked{
  display:grid;
  grid-template-columns:minmax(0,1fr) clamp(78px, 22%, 118px);
  column-gap:15px;
  align-items:start;
}
.review-job{
  display:flex;flex-direction:column;gap:8px;
  text-decoration:none;color:var(--sky-deep);
}
.review-job-shots{display:flex;flex-direction:column;gap:6px;}
/* contain rather than cover, which is the whole point of the change: the box is
   a tidy 4:3 and the photograph is fitted inside it entire, so a portrait shot
   sits in the middle of its box instead of having its top and bottom taken off.
   The box keeps its own background for whatever is left either side. */
.review-job-shots img{
  display:block;width:100%;aspect-ratio:4 / 3;object-fit:contain;
  border-radius:7px;background:var(--white);border:1px solid var(--line);
  transition:transform .18s ease, box-shadow .18s ease;
}
.review-job:hover .review-job-shots img{
  transform:translateY(-2px);box-shadow:0 6px 14px rgba(11,42,74,0.14);
}
/* Small, and allowed to break mid-word: the label names the town, and a
   Newmillerdam is longer than the column is wide. */
.review-job-go{
  font-family:'JetBrains Mono',monospace;font-size:0.62rem;
  letter-spacing:0.04em;text-transform:uppercase;font-weight:600;
  line-height:1.4;overflow-wrap:anywhere;
}
.review-job:hover .review-job-go{
  text-decoration:underline;text-decoration-color:var(--gold);text-underline-offset:3px;
}
.review-job:focus-visible{
  outline:2px solid var(--sky-deep);outline-offset:4px;border-radius:4px;
}
/* The same lift as a job card (.work-card in assets/work.css), so the reviews in
   the homepage timeline answer the mouse the way the jobs beside them do. On
   the timeline the card takes the job card's hairline border as well, gold down
   its left edge as ever, so the two turn blue together on hover. The seasonal
   6s colour glide from assets/theme.css is kept; the lift and shadow are quick. */
.testi-grid .testi{
  transition:transform .18s ease, box-shadow .18s ease, border-color .18s ease,
    background-color 6s ease, color 6s ease;
}
.testi-grid .testi:hover{transform:translateY(-3px);box-shadow:0 12px 30px rgba(11,42,74,0.10);}
.proof-timeline .testi{border:1px solid var(--line);border-left:4px solid var(--gold);}
.proof-timeline .testi:hover{border-color:var(--sky);border-left-color:var(--gold);}
@media (prefers-reduced-motion: reduce){
  .testi-grid .testi{transition:none;}
  .testi-grid .testi:hover{transform:none;}
}
@media (max-width: 1024px){ .testi-grid{grid-template-columns:repeat(2,1fr);} }
/* A young profile with one or two quotes to its name gets a grid that fits them
   rather than three columns with holes in it. Scoped to the wide layouts on
   purpose: below 880px everything is one column anyway, and an attribute
   selector would outrank that rule from anywhere in the file. */
@media (min-width: 881px){
  .testi-grid[data-cards="1"]{grid-template-columns:minmax(0,440px);}
  .testi-grid[data-cards="2"]{grid-template-columns:repeat(2,1fr);}
}
@media (max-width: 880px){
  .testi-grid{grid-template-columns:1fr;}
  .reviews-head{align-items:flex-start;gap:24px;}
}
/* On a phone the card is about as wide as the quote needs on its own: a column
   of photographs beside it would leave the words some twenty characters across.
   So the job goes back underneath here -- but as a row of the same whole 4:3
   photographs, side by side, rather than the cropped band it was before. */
@media (max-width: 620px){
  .testi-grid .testi-linked{grid-template-columns:minmax(0,1fr);row-gap:15px;}
  /* Back under the words, so it wants the faint rule that tells the two apart
     again -- beside them, the column edge does that job on its own. */
  .review-job{padding-top:15px;border-top:1px dashed var(--line);}
  .review-job-shots{
    display:grid;grid-auto-flow:column;grid-auto-columns:minmax(0,1fr);gap:8px;
  }
  .review-job-go{font-size:0.68rem;letter-spacing:0.06em;}
}
