/* ============================================================================
   REVISION 2 — homepage additions (loaded after css/styles.css)

   Promoted from lab variant R ("Faithful") on 2026-09-29, with the owners'
   two follow-ups: no dividers in the banner, and the before/after sliders
   flipped to BEFORE on the left / AFTER on the right. How It Works carries
   the once-only motion from variant T.

   The Minted-Midnight look is untouched — same 18px radii, same BenchNine /
   Public Sans / Archivo split, same pill controls, same tile treatment — and
   the new pieces are written in that voice:

     assurance banner  -> a navy strip (7-day rain touch-up guarantee, locally
                          owned & operated, exterior cleans include glass,
                          frames & sills)
     services grid     -> the existing tile, 3 large over 4 small
     why it matters    -> the navy band
     how it works      -> open columns on white, BenchNine numerals in teal discs
     reviews           -> the existing carousel, moved onto the gray wash

   No new colours: every value below is one of the four brand colours or a
   tint / shade of them. Motion is confined to How It Works (js/rev2.js).
   ========================================================================= */

:root {
  /* navy lifted ~8% toward sky, so the banner separates from the video hero's
     deep-navy scrim without becoming a different colour */
  --navy-lift: #131b2c;
  --sky-line: rgba(101, 141, 192, .62);
  --ink-quiet: rgba(12, 17, 31, .2);
}

/* ======================= HERO STICKER (rev-live) ========================== */
/* The score arrives at runtime, so the live wrapper is a flex row of its own.
   [hidden] is display:none !important in the base, which still wins while the
   attribute is present. */
.gsticker { white-space: nowrap; }
.gsticker .gs-live { display: inline-flex; align-items: center; gap: .6em; }
@media (max-width: 380px) {
  .gsticker { font-size: .85rem; gap: .45em; padding-inline: .95em; }
  .gsticker .gs-live { gap: .4em; }
  .gsticker .gstars { letter-spacing: .04em; }
}

/* ========================= ASSURANCE BANNER (#why) ======================== */
.assure {
  background: var(--navy-lift);
  border-top: 1px solid rgba(101, 141, 192, .3);
  color: #fff;
}
.assure-list {
  list-style: none;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  max-width: 1180px; margin-inline: auto;
  padding-inline: clamp(1.1rem, 4vw, 2.5rem);
}
.assure-item {
  display: flex; align-items: center; justify-content: center;
  gap: 1rem; padding: 1.55rem 1.2rem;
  min-width: 0;
}
/* no dividers between the three items (owner, 2026-09-29) */
.assure-ic { flex: none; width: 46px; height: 46px; color: var(--teal); }
.assure-txt {
  font-family: 'BenchNine', 'Public Sans', sans-serif; font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em; line-height: 1.15;
  font-size: clamp(1.1rem, 1.5vw, 1.3rem);
  color: #fff; max-width: 17em; text-wrap: balance;
  overflow-wrap: anywhere;
}
/* keep "7-Day" and "Touch-Up" whole: a line break at the hyphen reads as a typo */
.assure-txt .nb { white-space: nowrap; }
/* Below 760px the three become compact rows, separated by spacing alone. */
@media (max-width: 760px) {
  .assure-list { grid-template-columns: 1fr; }
  .assure-item { justify-content: flex-start; gap: .95rem; padding: .95rem 0; }
  .assure-ic { width: 38px; height: 38px; }
  .assure-txt { font-size: 1.15rem; max-width: none; }
}
/* the middle band: three columns still fit, icon gives way a little */
@media (min-width: 761px) and (max-width: 1020px) {
  .assure-item { gap: .7rem; padding-inline: .8rem; }
  .assure-ic { width: 38px; height: 38px; }
  .assure-txt { font-size: 1.08rem; letter-spacing: .08em; }
}

/* ============================ WHAT WE CLEAN =============================== */
/* Mobile first: one column. Every tile is the site's own 4:3 pane. */
.tile-grid { grid-template-columns: minmax(0, 1fr); gap: 1rem; }
.tile { aspect-ratio: 4 / 3; }
.tile-face p { max-height: 0; }
.tile-face h3 { font-size: 1.3rem; }

/* Keyboard and tap parity with hover: the description is in the DOM, and it
   opens on hover, keyboard focus, or focus anywhere inside the tile. */
.tile:hover .tile-face p,
.tile:focus-visible .tile-face p,
.tile:focus-within .tile-face p { max-height: 8em; opacity: 1; }
.tile:focus-visible { outline: 3px solid var(--sky-text); outline-offset: 3px; }

/* Solar is a wide 1000x524 photo shown in near-square panes: keep the brush
   head (about 52% across, 62% down) inside the crop at every card size. */
.tile img[src$="svc-solar.webp"] { object-position: 52% 62%; }

/* Where hover is unavailable, and on anything narrower than the desktop grid,
   the description is simply shown. Nothing lives only behind a mouse. */
@media (hover: none), (max-width: 999.98px) {
  .tile-face p { max-height: none; opacity: 1; }
}

/* Tablet: first card full width, then two columns — 1 + 6, no orphan. */
@media (min-width: 640px) and (max-width: 999.98px) {
  .tile-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tile--lg:first-child { grid-column: 1 / -1; aspect-ratio: 16 / 9; }
  .tile--lg:first-child .tile-face h3 { font-size: 1.6rem; }
  .tile--lg:first-child .tile-face p { font-size: .98rem; max-width: 34rem; }
}

/* Desktop: 12-column grid, three large (span 4) over four small (span 3).
   Same gutter on both rows; both rows meet the container edges exactly. */
@media (min-width: 1000px) {
  .tile-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 1rem; }
  .tile--lg { grid-column: span 4; aspect-ratio: 4 / 3; }
  .tile--sm { grid-column: span 3; aspect-ratio: 5 / 4; }
  .tile--lg .tile-face { padding: 3rem 1.4rem 1.3rem; }
  .tile--lg .tile-face h3 { font-size: 1.62rem; }
  .tile--lg .tile-face p { font-size: .95rem; }
  .tile--sm .tile-face { padding: 2rem 1.1rem 1rem; }
  .tile--sm .tile-face h3 { font-size: 1.2rem; }
  .tile--sm .tile-face p { font-size: .82rem; line-height: 1.5; }
}

/* ============================== WHY IT MATTERS ============================ */
/* The navy band, compact. Left: eyebrow + headline. Right: the paragraph
   behind the same 4px teal rule the old "Why" columns carried. No button, no
   image — a single quiet glow keeps it from being a flat slab. */
.matters {
  background:
    radial-gradient(70% 140% at 100% 0%, rgba(101, 141, 192, .16), transparent 62%),
    var(--navy);
  padding-block: clamp(3rem, 6vw, 4.4rem) clamp(2.8rem, 5vw, 3.6rem);
}
.matters .wrap {
  display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  column-gap: clamp(2rem, 5vw, 4rem); align-items: center;
}
.matters .eyebrow { grid-column: 1; grid-row: 1; align-self: end; }
.matters h2 {
  grid-column: 1; grid-row: 2;
  font-size: clamp(2rem, 4vw, 3rem);
  text-wrap: balance;
}
.matters-copy {
  grid-column: 2; grid-row: 1 / span 2;
  border-left: 4px solid var(--teal);
  padding-left: clamp(1.2rem, 2.4vw, 1.9rem);
  font-size: 1.08rem; line-height: 1.7; font-weight: 300;
  color: #cfd6e2;
}
@media (max-width: 900px) {
  .matters .wrap { grid-template-columns: minmax(0, 1fr); }
  .matters .eyebrow { grid-row: 1; }
  .matters h2 { grid-row: 2; }
  .matters-copy {
    grid-column: 1; grid-row: 3; margin-top: 1.6rem;
    border-left: 0; padding-left: 0;
    border-top: 4px solid var(--teal); padding-top: 1.15rem;
    font-size: 1.02rem; max-width: 46rem;
  }
}

/* Results sits tight beneath the navy band, so the sliders read as proof of
   the problem just described rather than as a new topic. */
#proof { padding-top: clamp(2rem, 3.6vw, 2.8rem); }
#proof .sec-head { margin-bottom: clamp(1.3rem, 3vw, 2rem); }

/* ================================ HOW IT WORKS ============================ */
.how-steps {
  list-style: none;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  max-width: 1040px; margin-inline: auto;
}
.how-step {
  position: relative; text-align: center;
  padding-inline: clamp(.9rem, 3vw, 2.2rem);
}
.how-num {
  position: relative; z-index: 1;
  display: grid; place-items: center;
  width: 56px; height: 56px; margin: 0 auto 1.15rem;
  border-radius: 50%; background: var(--teal); color: var(--navy);
  font-family: 'BenchNine', 'Public Sans', sans-serif; font-weight: 700;
  font-size: 1.95rem; line-height: 1;
}
/* the connecting rule, drawn from one disc to the next */
.how-step:not(:last-child)::before {
  content: ""; position: absolute; top: 27px; height: 2px;
  left: calc(50% + 40px); width: calc(100% - 80px);
  background: rgba(101, 141, 192, .42);
}
.how-step h3 {
  font-family: 'BenchNine', 'Public Sans', sans-serif; font-weight: 700;
  font-size: 1.6rem; letter-spacing: .06em; text-transform: uppercase;
  line-height: 1.1; color: var(--navy); margin-bottom: .55rem;
  text-wrap: balance;
}
.how-step p {
  max-width: 21rem; margin-inline: auto;
  font-size: 1rem; line-height: 1.6; color: var(--body-ink);
}
.how-cta { text-align: center; margin-top: clamp(2rem, 4.5vw, 3rem); }
.how-cta .btn { box-shadow: 0 10px 24px -8px rgba(12, 17, 31, .28); }

@media (max-width: 760px) {
  .how-steps { grid-template-columns: minmax(0, 1fr); max-width: 30rem; }
  .how-step {
    text-align: left; padding: 0 0 1.7rem;
    display: grid; grid-template-columns: 48px minmax(0, 1fr); column-gap: 1rem;
    align-items: start;
  }
  .how-step:last-child { padding-bottom: 0; }
  .how-num {
    grid-row: 1 / span 2; margin: 0;
    width: 48px; height: 48px; font-size: 1.7rem;
  }
  .how-step h3 { grid-column: 2; font-size: 1.45rem; margin: .4rem 0 .3rem; }
  .how-step p { grid-column: 2; margin-inline: 0; max-width: none; }
  /* vertical rule from the bottom of one disc to the top of the next */
  .how-step:not(:last-child)::before {
    top: 54px; bottom: 6px; height: auto;
    left: 23px; width: 2px;
  }
}

/* ================================= REVIEWS ================================ */
/* On the gray wash: white cards, and the two controls that were gray-on-gray
   get a visible shape. */
#reviews { background: var(--gray); }
/* The carousel track clips its own overflow, so the base card shadow (0 10px
   30px) is cut off in a hard rectangle on the gray wash. A contained shadow
   keeps the card edges clean. */
#reviews .rev-card { background: #fff; box-shadow: 0 1px 3px rgba(12, 17, 31, .07); }
#reviews .rev-dot::before { background: var(--ink-quiet); }
#reviews .rev-dot.is-on::before { background: var(--blue-ink); }
#reviews .btn--ghost {
  background: #fff; box-shadow: inset 0 0 0 1px var(--line-strong);
}
#reviews .btn--ghost:hover { background: var(--navy); color: #fff; box-shadow: none; }

/* .rev-head has two states: the live rating row, and the plain fallback line
   that shows when the summary cannot be read. */
.rev-head[data-rev-fallback] {
  font-size: 1rem; font-weight: 400; color: var(--grey);
}
.rev-head[data-rev-live] { margin-top: .9rem; }
/* On a phone the row cannot hold stars + score + count on one line, and the
   bare "·" separator was left dangling after the score. The separator is a
   bare text node, so the row's own text colour goes transparent (hiding it)
   and every real child carries its own colour. Result: stars + score, then
   the count beneath. */
@media (max-width: 560px) {
  .rev-head[data-rev-live] { color: transparent; gap: .35rem 1rem; }
  .rev-head[data-rev-live] .rev-score { color: var(--ink); }
  .rev-head[data-rev-live] .rev-count { flex-basis: 100%; text-align: center; color: var(--grey-dim); }
}

/* ============================== REDUCED MOTION ============================ */
@media (prefers-reduced-motion: reduce) {
  .tile-face p { transition: none; }
  .btn:hover { transform: none; }
}

/* ======================= SLIDERS: BEFORE LEFT, AFTER RIGHT ====================
   (owner, 2026-09-29 — reverses the revision PDF). styles.css clips the AFTER
   layer to the left --pos% of the frame. Here the BEFORE layer takes the clip
   and sits on top, so it fills the left and the AFTER image (unclipped, beneath)
   shows on the right. The JS, the handle and the 50/50 start are untouched. */
.slider .s-before { z-index: 1; clip-path: inset(0 calc(100% - var(--pos)) 0 0); }
.slider .s-after  { clip-path: none; }
.s-tag--b { left: .8rem; right: auto; }
.s-tag--a { right: .8rem; left: auto; }

/* ===================== HOW IT WORKS — MOTION (from lab variant T) ================
   Owner liked T's sequence, so it is ported here without changing R's look:
   number 1 pops, a glowing line draws to number 2, which pops, the line draws
   on to number 3, which lands with one ring of light; each title and sentence
   rises in with its number. R's existing connector stays as the faint track
   (::before); the drawn line is a second layer on top of it (::after).
   Once only. Everything hidden-until-triggered is scoped to html.r-anim, which
   js/rev2.js sets only when motion is allowed — with reduced motion or no
   IntersectionObserver the section simply renders complete. */
.how-step:not(:last-child)::after {
  content: ""; position: absolute; top: 26.5px; height: 3px; border-radius: 3px;
  left: calc(50% + 40px); width: calc(100% - 80px);
  background: linear-gradient(90deg, var(--sky), var(--teal));
  box-shadow: 0 0 12px rgba(150, 206, 198, .85);
  transform-origin: left center;
  pointer-events: none;
}
/* the last number lands with a ring of light */
.how-step:last-child .how-num::after {
  content: ""; position: absolute; inset: -8px; border-radius: 50%;
  border: 2px solid var(--teal); opacity: 0; pointer-events: none;
}

@keyframes r-line  { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes r-lineV { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes r-pop {
  0%   { transform: scale(.2); opacity: 0; }
  60%  { transform: scale(1.2); opacity: 1; }
  80%  { transform: scale(.94); }
  100% { transform: none; opacity: 1; }
}
@keyframes r-rise { from { transform: translateY(12px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes r-ping { 0% { transform: scale(1); opacity: .9; } 100% { transform: scale(1.75); opacity: 0; } }

/* before the section scrolls in */
html.r-anim .how:not(.r-in) .how-step::after { transform: scaleX(0); }
html.r-anim .how:not(.r-in) .how-num { opacity: 0; transform: scale(.2); }
html.r-anim .how:not(.r-in) .how-step h3,
html.r-anim .how:not(.r-in) .how-step p { opacity: 0; }

/* the sequence */
html.r-anim .how.r-in .how-num { animation: r-pop .75s cubic-bezier(.3, 1.3, .5, 1) both; }
html.r-anim .how.r-in .how-step:nth-child(1) .how-num { animation-delay: .05s; }
html.r-anim .how.r-in .how-step:nth-child(2) .how-num { animation-delay: .85s; }
html.r-anim .how.r-in .how-step:nth-child(3) .how-num { animation-delay: 1.65s; }
html.r-anim .how.r-in .how-step:nth-child(1)::after { animation: r-line .7s cubic-bezier(.5, .1, .3, 1) .25s both; }
html.r-anim .how.r-in .how-step:nth-child(2)::after { animation: r-line .7s cubic-bezier(.5, .1, .3, 1) 1.05s both; }
html.r-anim .how.r-in .how-step h3,
html.r-anim .how.r-in .how-step p { animation: r-rise .65s var(--ease) both; }
html.r-anim .how.r-in .how-step:nth-child(1) h3 { animation-delay: .25s; }
html.r-anim .how.r-in .how-step:nth-child(1) p  { animation-delay: .35s; }
html.r-anim .how.r-in .how-step:nth-child(2) h3 { animation-delay: 1.05s; }
html.r-anim .how.r-in .how-step:nth-child(2) p  { animation-delay: 1.15s; }
html.r-anim .how.r-in .how-step:nth-child(3) h3 { animation-delay: 1.85s; }
html.r-anim .how.r-in .how-step:nth-child(3) p  { animation-delay: 1.95s; }
html.r-anim .how.r-in .how-step:last-child .how-num::after { animation: r-ping 1.1s ease-out 2.25s 1 forwards; }  /* forwards, not both: `both` paints the 0% frame (.9 opacity) through the 2.25s delay */

/* phones: the connector runs down, drawn one step at a time */
@media (max-width: 760px) {
  .how-step:not(:last-child)::after {
    top: 54px; bottom: 6px; height: auto;
    left: 22.5px; width: 3px; right: auto;
    background: linear-gradient(180deg, var(--sky), var(--teal));
    transform-origin: top center;
  }
  html.r-anim .how:not(.r-in) .how-step::after { transform: scaleY(0); }
  html.r-anim .how.r-in .how-step:nth-child(1)::after { animation-name: r-lineV; }
  html.r-anim .how.r-in .how-step:nth-child(2)::after { animation-name: r-lineV; }
}
