/* =========================================================
   RIDGELINE AIR & HEAT
   Example site. The business is fictional - see CONTEXT.md.

   >> THIS IS MOCK A AT FULL SIZE, NOT A NEW DESIGN.
   Every colour, font, gradient and glass recipe below is carried
   over from the approved mock in the studio site's _lab/lab.css
   (`.rl`, `.rl-a`). That mock is the last-known-good for this
   look and it is what the studio site's hero animation resolves
   into. Copy it, do not restyle it.

   The one real difference: the mock is a MINIATURE, so its sizes
   are all `em` relative to the frame it was drawn in. Here they
   are real page sizes. The proportions are kept, the units are not.
   ========================================================= */

:root{
  /* Ridgeline's palette - harvested from the mock, do not invent new values */
  --blue:        #1173d4;   /* the brand blue - buttons, links, the flake, icons  */
  --blue-lite:   #6fb3ee;   /* the sun half of the mark                           */
  --blue-deep:   #0d63ba;   /* bottom of the button gradient                      */
  --blue-top:    #3a90e4;   /* top of the button gradient                         */
  --gold:        #ffc23c;   /* the star rating, and nothing else                  */

  --ink:         #101418;   /* body text                                          */
  --ink-head:    #0d2233;   /* headings                                           */
  --ink-soft:    #5b6773;   /* secondary body text                                */
  --ink-nav:     #26323d;   /* nav links - darker than body on purpose, see below */

  --line:        #e6eaee;
  --tint:        #f7f9fb;   /* the pale band background                           */

  --wrap:        1180px;
  --radius:      14px;
  --band-pad:    clamp(3.5rem,7vw,6rem);  /* top and bottom air on a .band */

  /* >> HOW MUCH ROOM THE PINNED TOP BAR TAKES, and this value is a FALLBACK ONLY.
     `assets/js/nav.js` measures the real bar and overwrites it on load and on every
     resize. It has to be measured rather than written down because the bar's height
     is not one number: it becomes two rows below 760px, and it grows again once the
     webfont lands. These figures are what the page falls back to if the script does
     not run - close enough that nothing ends up hidden underneath the bar. */
  --bar-h:       5.3rem;
}

*{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;}
body{
  margin:0;
  font-family:'Barlow',system-ui,sans-serif;
  font-size:17px;
  line-height:1.6;
  color:var(--ink);
  background:#fff;
}
img{max-width:100%;display:block;}
a{color:inherit;text-decoration:none;}

h1,h2{
  font-family:'Barlow Condensed',system-ui,sans-serif;
  font-weight:800;
  line-height:.98;
  letter-spacing:.005em;
  margin:0;
  color:var(--ink-head);
}
h2{font-size:clamp(2rem,4vw,3.15rem);}

/* Side padding scales with the window instead of sitting at a fixed 24px.
   On a laptop the 1180 cap leaves almost no margin of its own, so content was
   ending up ~74px from the edge on both sides; this brings it in. Above ~1400
   the cap already supplies the margin and the clamp stops growing, so wide
   screens are unchanged. Phones keep the original 1.5rem. */
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 clamp(1.5rem,4vw,3rem);}
.wrap.narrow{max-width:760px;}

/* Narrow sections sit at the page's left edge, not centred in their own column.
   Before this, a narrow block was centred inside the wrap, so a heading started
   ~200px further in than the cards directly beneath it and the page had two
   different left edges. The container now spans the full content width and its
   children keep the readable 760px measure, which puts every left edge on the
   same line without making the paragraphs too wide to read.
   >> .closing is deliberately NOT included - it is text-align:center by design. */
.page-head .wrap.narrow,
.band .wrap.narrow{max-width:var(--wrap);}
.page-head .wrap.narrow > *,
.band .wrap.narrow > *{max-width:760px;}

/* Opt back out, per page. The service pages keep the original centred column
   (owner, wd-s6) - they are a single narrow run of text with no cards beside
   it, so there is no second left edge for the heading to line up with, and
   left-aligning it just leaves a wide empty right-hand side. */
body.centred-narrow .page-head .wrap.narrow,
body.centred-narrow .band .wrap.narrow{max-width:760px;}
body.centred-narrow .page-head .wrap.narrow > *,
body.centred-narrow .band .wrap.narrow > *{max-width:none;}
.center{text-align:center;}

.skip{
  position:absolute;left:-9999px;top:0;background:#fff;color:var(--blue);
  padding:.75rem 1.25rem;z-index:99;font-weight:600;
}
.skip:focus{left:.5rem;top:.5rem;}

:focus-visible{outline:3px solid var(--blue);outline-offset:3px;}


/* =========================================================
   THE FIRST SCREEN
   Nav, hero copy and the four service cards all sit over ONE
   full-bleed photo. This composition is locked - it is what the
   studio site's animation resolves into.
   ========================================================= */

/* >> THE PHOTO IS ON THIS ELEMENT SO THE FROSTED BARS HAVE SOMETHING TO BLUR.
   This is not decoration, it is the whole reason the glass exists:
   `backdrop-filter` blurs what is BEHIND an element, and over a flat white
   background that is nothing at all - a frosted bar on white renders as white.
   If the photo ever comes off here, the nav and the card band stop reading as
   glass and turn into flat tinted strips.

   >> THE SCRIM IS AN ELLIPSE ANCHORED ON THE HERO COPY, NOT A FLAT WASH.
   A uniform full-cover version was tried in the mock and it broke both bars -
   the dark navy nav ink fell to about 3:1 against a 4.5 minimum, because the
   glass is only ~18% opaque and was suddenly sitting on a dark base. The
   radial form is strongest behind the white hero copy and reaches full
   transparency before the top and bottom edges, so the bars sit back over
   bright photo where dark ink reads. Measured, not guessed. */
.hero{
  position:relative;
  min-height:100svh;
  /* >> THIS PADDING REPLACES THE BAR, IT DOES NOT ADD TO THE HERO (wd-s22).
     Pinning the bar takes it out of the flow, so without this the eyebrow line and
     everything under it slide up by the bar's height. `box-sizing:border-box` at the
     top of this file means the padding sits INSIDE the 100svh, so the hero is exactly
     the height it was and its contents sit exactly where they did. */
  padding-top:var(--bar-h);
  display:flex;
  flex-direction:column;
  background:
    radial-gradient(125% 88% at 6% 50%,
                    rgba(6,18,30,.82) 0%, rgba(6,18,30,.58) 34%,
                    rgba(6,18,30,.22) 66%, rgba(6,18,30,0) 100%),
    /* >> `cover`, NOT `104% auto` - THIS IS THE GREY-BAR FIX (owner, wd-s5).
       `104% auto` sets the WIDTH and lets the height follow, so on a tall box the photo
       runs out before the box does and the pale fallback colour shows through as a grey
       band above the nav and below the card band. `cover` scales to fill whichever
       direction is short, so there is never any uncovered area.
       The 104% value came from the mock, where the frame is a wide 3:1 band - there
       `cover` is width-driven and leaves no horizontal slack to shift the framing with,
       which is the problem 104% was solving. A full-height hero is the opposite shape:
       `cover` is height-driven here and leaves plenty of horizontal slack, so the
       position below still does its job. Same intent, right value for this geometry. */
    url("https://media.7starwebstudio.com/example/ridgeline/images/demo-home.jpg") 25% 50%/cover no-repeat #eef4fa;
}

/* ---- nav ---- */
/* Geometry and blur copied from the live 7staragency.com nav (read-only
   reference): an inset floating rectangle rather than a bar running edge to
   edge. The ALPHA is the one honest deviation - 0.06 works there because it is
   a white film over a dark page; here it is a light tint over a bright photo,
   and at 0.06 the panel vanishes and the dark text sits straight on the sky. */
/* >> THE BAR IS PINNED TO THE TOP OF THE SCREEN ON EVERY PAGE (wd-s22).
   `top/left/right:0` puts it against the edges and the margin below insets it, so the
   floating rectangle sits exactly where it used to. On the home page it starts as glass
   over the house photo and `nav.js` adds `.is-solid` once the photo has scrolled past -
   glass has nothing to blur over the white sections below, which is the same reasoning
   that made every inner page solid in the first place.
   z-index 50 keeps it over the page and under the skip link, which is 99. */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:50;
  display:flex;align-items:center;gap:clamp(1rem,3vw,2.5rem);
  margin:1.25rem 1.5rem 0;
  padding:.7rem 1.25rem;
  border-radius:var(--radius);
  transition:background-color .25s ease, border-color .25s ease,
             box-shadow .25s ease, margin .25s ease,
             border-radius .25s ease, padding .25s ease;
  background:rgba(226,239,252,.18);
  -webkit-backdrop-filter:blur(12px) saturate(130%);
  backdrop-filter:blur(12px) saturate(130%);
  border:1px solid rgba(255,255,255,.42);
  box-shadow:0 8px 26px rgba(14,34,51,.30),
             inset 0 1px 0 rgba(255,255,255,.55),
             inset 0 -1px 0 rgba(0,0,0,.06);
}

/* the wrapper exists so the gap between mark and words is its own value and
   not the nav's much larger gap, which would fling the mark away from them */
.brand{display:inline-flex;align-items:center;gap:.5rem;flex-shrink:0;}
.mark{width:2.1rem;height:2.1rem;flex-shrink:0;display:block;
  filter:drop-shadow(0 1px 3px rgba(255,255,255,.9));}
.mark-sun-disc{fill:var(--blue-lite);}
.mark-sun{stroke:var(--blue-lite);}
.mark-flake{stroke:var(--blue);}
.logo{
  font-family:'Barlow Condensed',sans-serif;font-weight:800;
  font-size:1.5rem;letter-spacing:.06em;white-space:nowrap;color:var(--ink-head);
}
.logo em{font-style:normal;color:var(--blue);}

.nav nav{display:flex;gap:1.6rem;flex:1;}
/* >> THE NAV INK IS DARKER THAN THE BODY GREY AND THAT IS A LEGIBILITY FIX, NOT
   A STYLE CHOICE. Measured on the frosted panel, the softer grey came out at
   4.13:1 over the sky and 2.08:1 where the dark roof sits behind the bar. The
   right lever was darkening the ink; raising the panel's opacity would have
   given back exactly the transparency that was asked for. */
.nav nav a{color:var(--ink-nav);font-weight:700;font-size:.95rem;}
.nav nav a:hover{color:var(--blue);}

/* >> THE LIGHT HALO IS WHAT MAKES THE TRANSPARENCY POSSIBLE - it does the
   legibility work so the glass does not have to. Note the direction is
   INVERTED from the usual: the standard shadow is dark because that text is
   white on dark imagery. This text is dark navy on a light panel, so a dark
   shadow would just read as smudge. It needs a light halo. */
.brand,.nav nav a{
  text-shadow:0 1px 4px rgba(255,255,255,.95), 0 2px 10px rgba(255,255,255,.65);
}

.phone-btn{
  display:inline-flex;align-items:center;justify-content:center;
  font-family:'Barlow Condensed',sans-serif;font-weight:700;letter-spacing:.04em;
  font-size:1.15rem;padding:.5rem 1.1rem;border-radius:9px;white-space:nowrap;
  color:#fff;
  background:linear-gradient(180deg,var(--blue-top) 0%,var(--blue) 52%,var(--blue-deep) 100%);
  box-shadow:0 4px 12px rgba(17,115,212,.42),
             inset 0 1px 0 rgba(255,255,255,.34),
             inset 0 -2px 0 rgba(0,0,0,.17);
  transition:transform .15s, box-shadow .15s;
}
.phone-btn:hover{transform:translateY(-2px);
  box-shadow:0 8px 20px rgba(17,115,212,.5),
             inset 0 1px 0 rgba(255,255,255,.34),
             inset 0 -2px 0 rgba(0,0,0,.17);}

/* ---- hero copy ----
   `flex:1` in a full-height column, so this band absorbs whatever the nav and
   the card band give up. Because it is centred, every pixel it gains becomes
   symmetric clearance around the copy. */
.hero-body{flex:1 1 auto;display:flex;align-items:center;padding:3rem 3rem;}
.hero-copy{color:#fff;max-width:46rem;}

.eyebrow{
  font-size:.78rem;letter-spacing:.2em;text-transform:uppercase;font-weight:600;
  color:#8fc4f5;margin:0;
}
.hero-copy h1{
  color:#fff;font-size:clamp(2.9rem,6.6vw,5.4rem);margin:.28em 0 .3em;
  line-height:.96;
}
.sub{font-size:clamp(1.05rem,1.4vw,1.25rem);line-height:1.5;max-width:34ch;
  color:#d6dee6;margin:0;}

.cta-row{display:flex;align-items:center;gap:.9rem;margin-top:1.8rem;flex-wrap:wrap;}
.cta-row.center{justify-content:center;}

/* the hero buttons use the same recipe as the nav phone button so the page
   reads as one system rather than a set of unrelated controls */
.btn{
  display:inline-block;color:#fff;font-weight:600;font-size:1.05rem;
  padding:.75rem 1.7rem;border-radius:9px;
  background:linear-gradient(180deg,var(--blue-top) 0%,var(--blue) 52%,var(--blue-deep) 100%);
  box-shadow:0 4px 12px rgba(17,115,212,.40),
             inset 0 1px 0 rgba(255,255,255,.32),
             inset 0 -2px 0 rgba(0,0,0,.18);
  transition:transform .15s, box-shadow .15s;
}
.btn:hover{transform:translateY(-2px);
  box-shadow:0 8px 22px rgba(17,115,212,.5),
             inset 0 1px 0 rgba(255,255,255,.32),
             inset 0 -2px 0 rgba(0,0,0,.18);}

.btn-ghost{
  display:inline-block;border:1.5px solid rgba(255,255,255,.62);color:#fff;
  font-weight:600;font-size:1.05rem;padding:.72rem 1.55rem;border-radius:9px;
  background:linear-gradient(180deg,rgba(255,255,255,.20),rgba(255,255,255,.05));
  box-shadow:0 3px 10px rgba(0,0,0,.26),
             inset 0 1px 0 rgba(255,255,255,.34),
             inset 0 -2px 0 rgba(0,0,0,.12);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
  transition:transform .15s, background .15s;
}
.btn-ghost:hover{transform:translateY(-2px);
  background:linear-gradient(180deg,rgba(255,255,255,.30),rgba(255,255,255,.10));}

.trust{
  display:flex;gap:1.8rem;margin:1.9rem 0 0;padding:0;list-style:none;flex-wrap:wrap;
  font-size:.9rem;color:#c3ced8;
}
.trust b{color:#fff;}
.stars{color:var(--gold);letter-spacing:.06em;}

/* ---- the service card band ----
   The "footer" bar of the first screen. Deliberately shorter than the hero. */
.svc{
  display:grid;grid-template-columns:repeat(4,1fr);gap:1rem;
  margin:0 1.5rem 1.25rem;padding:1.1rem;
  border-radius:var(--radius);
  background:rgba(226,239,252,.20);
  /* >> A SOFTER BLUR THAN THE NAV ON PURPOSE (8 vs 12). What sits behind this
     band is the paver driveway - bright and almost uniform - and at a heavy
     blur it averages out to flat near-white and stops reading as glass at all.
     The nav can afford more because the sky behind it has a strong gradient
     that survives blurring. Match the blur to what is BEHIND the panel, never
     to the other panel. */
  -webkit-backdrop-filter:blur(8px) saturate(130%);
  backdrop-filter:blur(8px) saturate(130%);
  border:1px solid rgba(255,255,255,.42);
  box-shadow:0 8px 26px rgba(14,34,51,.28),
             inset 0 1px 0 rgba(255,255,255,.55),
             inset 0 -1px 0 rgba(0,0,0,.06);
}
/* >> THE CARDS ARE THE OPAQUE PART, THE BAND IS THE TRANSPARENT PART.
   The cards carry dark body text and the photo behind them is dark lawn and
   driveway, so a very transparent card leaves the text washed out. Keeping the
   BAND light-transparent preserves the frosted read while the cards sit more
   opaque because they are content surfaces. Push this down and the text stops
   passing contrast. */
.card{
  background:rgba(255,255,255,.74);
  -webkit-backdrop-filter:blur(10px) saturate(130%);
  backdrop-filter:blur(10px) saturate(130%);
  border:1px solid rgba(255,255,255,.75);
  border-radius:10px;
  padding:1.15rem 1.3rem;
  box-shadow:0 6px 16px rgba(14,34,51,.18),
             inset 0 1px 0 rgba(255,255,255,.95),
             inset 0 -2px 0 rgba(17,115,212,.08);
}
.card b{
  display:block;font-family:'Barlow Condensed',sans-serif;font-size:1.25rem;
  letter-spacing:.03em;margin:.55rem 0 .2rem;color:var(--ink-head);
  text-shadow:0 1px 0 rgba(255,255,255,.85);
}
.card p{margin:0;font-size:.92rem;color:#3f5567;line-height:1.4;
  text-shadow:0 1px 0 rgba(255,255,255,.65);}

.ic{
  display:flex;align-items:center;justify-content:center;
  width:2.3rem;height:2.3rem;border-radius:7px;
  background:rgba(255,255,255,.72);border:1px solid rgba(17,115,212,.28);
  box-shadow:0 2px 5px rgba(14,34,51,.14), inset 0 1px 0 rgba(255,255,255,.95);
}
/* stroke-width stays 2 on a 24 box to match the brand mark, so the icon set
   and the logo read as one family */
.ic svg{width:72%;height:72%;display:block;
  fill:none;stroke:var(--blue);stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
.ic svg .fl{fill:var(--blue);stroke:none;}


/* =========================================================
   INNER PAGES
   Everything behind the home page. Same components, but the
   top bar cannot be frosted here - see the note on .nav-solid.
   ========================================================= */

/* >> SOLID, NOT FROSTED, AND THAT IS NOT A STYLE PREFERENCE.
   Frosted glass blurs whatever sits BEHIND it. On the home page that is the house
   photo, which is the whole reason the bar reads as glass. An inner page has no
   photo behind the bar, so the same treatment would render as a flat tinted strip -
   the exact failure documented in DESIGN.md decision 2, in the other direction. */
/* >> `.is-solid` IS THE SAME BAR, NOT A SECOND ONE (wd-s22). The home page's glass bar
   turns into this the moment the house photo has scrolled past, because from there down
   the page is white and there is nothing behind the glass to blur. Every rule below is
   shared rather than copied, so the two can never drift apart. */
.nav-solid,.nav.is-solid{
  margin:0;border-radius:0;border:0;border-bottom:1px solid var(--line);
  background:#fff;
  -webkit-backdrop-filter:none;backdrop-filter:none;
  box-shadow:0 1px 3px rgba(16,20,24,.06);
  padding:.85rem 1.75rem;
}
/* the halo exists to lift dark ink off a bright photo - there is no photo here */
.nav-solid .brand,.nav-solid nav a,
.nav.is-solid .brand,.nav.is-solid nav a{text-shadow:none;}
.nav-solid .mark,.nav.is-solid .mark{filter:none;}
.nav-solid nav a.here,.nav.is-solid nav a.here{color:var(--blue);}

/* >> THE INNER PAGES NEED THE SAME SPACER THE HERO GETS. The bar is pinned there too,
   so the page content below it has to be pushed down by the height it no longer
   occupies. Every inner page is the bar followed immediately by `<main>`. */
.nav-solid + main{padding-top:var(--bar-h);}

/* >> ANCHOR LANDINGS CLEAR THE BAR. Without this, jumping to `#about` or `#services`
   parks the heading underneath the pinned bar. The extra 1rem is breathing room so the
   heading is not touching it. */
[id]{scroll-margin-top:calc(var(--bar-h) + 1rem);}

/* THE INNER-PAGE BANNER (wd-s6). Same house photo as the home hero, cropped to
   the front of the house.

   >> THE CROP. The band is far wider than it is tall, so `cover` is width-driven
   and the whole width of the photo shows - the only real choice is which
   horizontal slice. The house front sits between roughly 11% and 76% of the
   photo's height, centred near 44%, so that is the vertical anchor. Anything
   lower fills the band with driveway; anything higher fills it with sky.

   >> THE SCRIM IS A LEFT-TO-RIGHT RAMP, NOT THE HERO'S ELLIPSE. The hero copy sits
   in the left half of a full-height frame, so an ellipse anchored left suits it.
   A banner is a wide shallow strip - an ellipse in that shape either misses the
   text or covers everything. The ramp keeps the left dark enough for white type
   and lets the right stay bright, which is where the van sits on three pages. */
.page-head{
  padding:clamp(3rem,6vw,5rem) 0 clamp(2rem,4vw,3rem);
  background:var(--tint);border-bottom:1px solid var(--line);
}
/* Type goes light, because the band is now a photograph. The shadow is the
   house standard for text over imagery - see the shared component standards. */

/* THE PHOTO BANNER - ONLY on the two pages that carry no photograph of their
   own (owner, wd-s6). Plans is pricing cards and Reviews is a wall of quotes;
   every other page already has imagery, so a photo banner there would be a
   second picture competing with the first. Opt in with `banner-photo` on body.

   >> THE CROP. The band is far wider than it is tall, so `cover` is width-driven
   and the whole width of the photo shows - the only real choice is which
   horizontal slice. The house front sits between roughly 11% and 76% of the
   photo's height, centred near 44%, so that is the vertical anchor. Lower fills
   the band with driveway, higher fills it with sky.

   >> THE SCRIM IS A LEFT-TO-RIGHT RAMP, NOT THE HERO'S ELLIPSE. The hero copy sits
   in the left half of a full-height frame, which suits an ellipse. A banner is a
   wide shallow strip, where an ellipse either misses the text or covers the lot. */
body.banner-photo .page-head{
  background:
    linear-gradient(100deg,
      rgba(6,18,30,.88) 0%, rgba(6,18,30,.74) 34%,
      rgba(6,18,30,.42) 62%, rgba(6,18,30,.24) 100%),
    url("https://media.7starwebstudio.com/example/ridgeline/images/demo-home.jpg") center 44%/cover no-repeat #0f2233;
  border-bottom:1px solid rgba(255,255,255,.14);
}
body.banner-photo .page-head h1{color:#fff;}
body.banner-photo .page-head .lead{color:#dbe6f0;}
body.banner-photo .page-head .eyebrow-dark{color:var(--blue-lite);}
/* Reviews puts its score block inside the banner. The big number is dark navy by
   default and disappeared completely against the photo. */
body.banner-photo .page-head .score-num{color:#fff;}
body.banner-photo .page-head .score-sub{color:#dbe6f0;}
body.banner-photo .page-head h1,body.banner-photo .page-head .lead,
body.banner-photo .page-head .eyebrow-dark{
  text-shadow:0 2px 12px rgba(0,0,0,.85),0 1px 4px rgba(0,0,0,.6);
}
.page-head h1{font-size:clamp(2.4rem,5vw,3.8rem);margin:.35rem 0 0;}
.eyebrow-dark{color:var(--blue);}

/* page head with the van sitting in the empty half beside the heading.
   The van faces LEFT, into the words - a subject facing off the page
   walks the eye out of it. */
/* minmax(0,1fr) on the text column, not plain 1fr: a grid column defaults to
   its content's minimum width, so a long heading would refuse to shrink and
   push the van out of the row instead of wrapping. The 0 lets it wrap. */
.head-van{display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,50%);
  gap:clamp(1.25rem,3vw,3rem);align-items:center;}
.head-van img{width:100%;height:auto;display:block;}

/* the four people */
.team{display:grid;grid-template-columns:repeat(4,1fr);gap:1.75rem;}
.person b{
  display:block;font-family:'Barlow Condensed',sans-serif;font-size:1.45rem;
  letter-spacing:.03em;color:var(--ink-head);margin:.9rem 0 0;
}
.person .role{
  display:block;font-size:.8rem;letter-spacing:.14em;text-transform:uppercase;
  font-weight:600;color:var(--blue);margin:.15rem 0 .5rem;
}
.person p{margin:0;font-size:.97rem;color:var(--ink-soft);line-height:1.5;}

/* The four staff photos (wd-s6). Square, because the locked Leonardo headshot
   recipe generates square. The pale gradient stays as the background so a slow
   or failed image still shows the frame rather than a collapsed gap. */
.photo{
  display:block;width:100%;height:auto;aspect-ratio:1/1;object-fit:cover;
  border-radius:12px;
  background:linear-gradient(160deg,#e3f0fd 0%,#d3e4f5 100%);
  border:1px solid #c9e2fb;
}

/* A photo band between the page head and the first content section. Top padding
   only - the band beneath brings its own, and doubling them opens a gap that
   reads as a missing section. */
.page-shot{margin:0;padding:var(--band-pad) 0 0;}
/* Height is capped and the image crops rather than scaling. At full content
   width a 16:9 photo runs about 600px tall and takes over the page; the cap
   keeps it a band. The crop is safe because these shots are centre-weighted. */
.page-shot img{
  display:block;width:100%;height:auto;border-radius:var(--radius);
  max-height:clamp(240px,32vw,440px);object-fit:cover;object-position:center;
}

/* ---- service pages ---- */
.ticks{list-style:none;margin:1.3rem 0 0;padding:0;}
.ticks li{
  position:relative;padding-left:1.8rem;margin:0 0 .65rem;
  font-size:1.02rem;color:var(--ink-soft);line-height:1.5;
}
.ticks li::before{
  content:"";position:absolute;left:0;top:.45em;
  width:.62rem;height:.32rem;border-left:2px solid var(--blue);
  border-bottom:2px solid var(--blue);transform:rotate(-45deg);
}
/* the gas / carbon monoxide warning on the furnace page - the one place on this site
   where a line has to stop somebody rather than sell to them */
.warn{
  margin:0 0 2rem;padding:1.1rem 1.3rem;border-radius:12px;
  background:#fff4e5;border:1px solid #f0d3a4;color:#5a3d0c;line-height:1.5;
}

/* the services index */
.svc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1.5rem;}
.svc-card{
  display:block;background:#fff;border:1px solid var(--line);border-radius:14px;
  padding:1.7rem 1.6rem;box-shadow:0 2px 12px rgba(16,20,24,.06);
  transition:transform .15s, box-shadow .15s;
}
.svc-card:hover{transform:translateY(-3px);box-shadow:0 10px 24px rgba(16,20,24,.10);}
.svc-card b{
  display:block;font-family:'Barlow Condensed',sans-serif;font-size:1.5rem;
  letter-spacing:.03em;color:var(--ink-head);
}
.svc-card p{margin:.45rem 0 0;color:var(--ink-soft);font-size:.98rem;line-height:1.5;}
.svc-more{display:inline-block;margin-top:1rem;color:var(--blue);font-weight:600;
  font-size:.95rem;}

/* ---- reviews page ---- */
.score{display:flex;align-items:baseline;gap:.7rem;flex-wrap:wrap;margin:1.1rem 0 0;}
.score-num{font-family:'Barlow Condensed',sans-serif;font-weight:800;font-size:3.2rem;
  line-height:1;color:var(--ink-head);}
.score-sub{color:var(--ink-soft);font-size:1rem;}

.reviews{display:grid;grid-template-columns:repeat(3,1fr);gap:1.5rem;}
.review{
  margin:0;background:#fff;border:1px solid var(--line);border-radius:14px;
  padding:1.7rem 1.6rem;box-shadow:0 2px 12px rgba(16,20,24,.06);
  display:flex;flex-direction:column;
}
.review > p:not(.stars){margin:0;color:var(--ink);line-height:1.55;flex:1 1 auto;}
.review .stars{margin:0 0 .8rem;font-size:1.05rem;letter-spacing:.08em;}
.review footer{display:flex;align-items:center;gap:.8rem;margin-top:1.4rem;}
/* an INITIAL, not a face - see the note in reviews.html */
.who{
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
  width:2.6rem;height:2.6rem;border-radius:50%;
  background:#e3f0fd;border:1px solid #c9e2fb;color:var(--blue);
  font-family:'Barlow Condensed',sans-serif;font-weight:800;font-size:1.3rem;
}
.review cite{font-style:normal;font-weight:700;color:var(--ink-head);font-size:.98rem;
  display:flex;flex-direction:column;line-height:1.3;}
.review cite span{font-weight:400;color:var(--ink-soft);font-size:.88rem;}

/* ---- contact: form on the left, contact information beside it ----
   Layout donor named in components/unsection-about-reviews-contact.md.
   The information panel is SOURCE-ORDERED SECOND but shows FIRST on a phone -
   see the mobile block. The phone number outranks the form on a trade site. */
.contact-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(2rem,5vw,4rem);
  align-items:start;}
.contact-form-col h2{font-size:clamp(1.6rem,2.6vw,2.1rem);margin:0 0 1.4rem;}

.info-panel{
  background:var(--tint);border:1px solid var(--line);border-radius:14px;
  padding:clamp(1.5rem,3vw,2.1rem);
}
.info-label{
  font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;font-weight:600;
  color:var(--blue);margin:0;
}
.info-row{margin-top:1.6rem;}
.info-row p:last-child{margin:.3rem 0 0;color:var(--ink-soft);font-size:1rem;line-height:1.5;}

/* the phone is the point of the page, so it is the biggest thing on it */
.big-phone{
  display:inline-block;font-family:'Barlow Condensed',sans-serif;font-weight:800;
  font-size:clamp(2.1rem,4.4vw,3rem);color:var(--blue);letter-spacing:.02em;
  margin:.35rem 0 0;line-height:1;
}
.big-phone:hover{color:var(--blue-deep);}

.form{max-width:520px;}
.field{margin:0 0 1.15rem;}
.field label{display:block;font-weight:600;font-size:.95rem;color:var(--ink-head);
  margin:0 0 .35rem;}
.opt{font-weight:400;color:var(--ink-soft);}
.field input,.field select,.field textarea{
  width:100%;font-family:inherit;font-size:1rem;color:var(--ink);
  padding:.7rem .85rem;border:1px solid #cfd8e0;border-radius:9px;background:#fff;
}
.field textarea{resize:vertical;}
.field input:focus,.field select:focus,.field textarea:focus{
  border-color:var(--blue);outline:none;box-shadow:0 0 0 3px rgba(17,115,212,.16);
}
.form .btn{border:0;cursor:pointer;font-family:inherit;}
.form-note{font-size:.95rem;color:var(--ink-soft);margin:1.1rem 0 0;}
.form-done{
  font-size:1.1rem;color:var(--ink-head);background:#e8f4ff;border:1px solid #c9e2fb;
  border-radius:12px;padding:1.4rem 1.5rem;max-width:520px;
}
.form-done a{color:var(--blue);font-weight:700;}

/* the three maintenance plans */
.plans{display:grid;grid-template-columns:repeat(3,1fr);gap:1.5rem;align-items:start;}
.plan{
  background:#fff;border:1px solid var(--line);border-radius:14px;
  padding:1.9rem 1.7rem;box-shadow:0 2px 12px rgba(16,20,24,.06);
  display:flex;flex-direction:column;height:100%;
}
.plan b{
  display:block;font-family:'Barlow Condensed',sans-serif;font-size:1.5rem;
  letter-spacing:.05em;text-transform:uppercase;color:var(--blue);
}
.plan-price{
  font-family:'Barlow Condensed',sans-serif;font-weight:800;font-size:3.1rem;
  color:var(--ink-head);margin:.35rem 0 1.1rem;line-height:1;
}
.plan-price span{font-size:1.05rem;font-weight:600;color:var(--ink-soft);
  font-family:'Barlow',sans-serif;letter-spacing:0;}
.plan-list{list-style:none;margin:0 0 1.6rem;padding:0;flex:1 1 auto;}
.plan-list li{
  position:relative;padding-left:1.7rem;margin:0 0 .6rem;
  font-size:.98rem;color:var(--ink-soft);line-height:1.45;
}
.plan-list li::before{
  content:"";position:absolute;left:0;top:.42em;
  width:.62rem;height:.32rem;border-left:2px solid var(--blue);
  border-bottom:2px solid var(--blue);transform:rotate(-45deg);
}
.plan-btn{align-self:flex-start;}

/* a second heading inside a band that already has one - same size as the first,
   because these are two equal ideas and shrinking one invented a hierarchy that
   is not in the copy. Only the top margin separates them. */
.h2-second{margin-top:2.9rem;}

/* =========================================================
   THE PAGE BELOW THE FIRST SCREEN
   ========================================================= */

.band{padding:var(--band-pad) 0;}

/* The safety callout opens its band, so the band's full top padding lands above
   the box while the box's own margin sits below it - two different numbers, and
   the box reads as floating (caught on furnace repair, wd-s6). Both gaps are now
   half the band padding, so they stay equal at every screen width. */
.band .warn:first-child{
  margin-top:calc(var(--band-pad) / -2);
  margin-bottom:calc(var(--band-pad) / 2);
}
.band-tint{background:var(--tint);border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);}
.band-blue{
  background:linear-gradient(180deg,#0f2a44 0%,#0b2137 100%);
  color:#dbe6f0;
}
.band-blue h2{color:#fff;}
.band-blue .lead{color:#c3d2e0;}
.hl{color:#7cc0ff;}

.lead{font-size:clamp(1.05rem,1.5vw,1.2rem);color:var(--ink-soft);
  max-width:60ch;margin:1.1rem 0 0;}
.band-blue .lead{margin-bottom:1.9rem;}

.link{color:var(--blue);font-weight:600;display:inline-block;margin-top:1.3rem;}
.link:hover{text-decoration:underline;}

/* the four numbered promises */
.steps{list-style:none;counter-reset:s;margin:2.6rem 0 0;padding:0;
  display:grid;grid-template-columns:repeat(2,1fr);gap:1.6rem 2.5rem;}
.steps li{counter-increment:s;position:relative;padding-left:3.4rem;
  font-size:1.02rem;color:var(--ink-soft);}
.steps li::before{
  content:counter(s);position:absolute;left:0;top:-.15rem;
  width:2.4rem;height:2.4rem;border-radius:8px;
  display:flex;align-items:center;justify-content:center;
  font-family:'Barlow Condensed',sans-serif;font-weight:800;font-size:1.3rem;
  color:var(--blue);background:#e3f0fd;border:1px solid #c9e2fb;
}
.steps b{color:var(--ink-head);display:block;}

/* reviews */
.rating{font-size:1.05rem;color:var(--ink-soft);margin:.9rem 0 0;}
.stars-big{color:var(--gold);font-size:1.6rem;letter-spacing:.12em;margin:.35rem 0 0;}
.quotes{display:grid;grid-template-columns:repeat(3,1fr);gap:1.5rem;margin:2.6rem 0 0;}
blockquote{
  margin:0;padding:1.6rem 1.5rem;background:#fff;
  border:1px solid var(--line);border-radius:12px;
  box-shadow:0 2px 10px rgba(16,20,24,.05);
}
blockquote p{margin:0;font-size:1rem;color:var(--ink);line-height:1.55;}
cite{display:block;margin-top:1rem;font-style:normal;font-weight:700;
  font-size:.9rem;color:var(--ink-soft);}

/* the closing block - headline and two buttons, nothing else */
.closing{
  padding:clamp(3.5rem,7vw,6rem) 0;text-align:center;
  background:var(--tint);border-top:1px solid var(--line);
}
.btn-outline{
  display:inline-block;font-weight:600;font-size:1.05rem;
  padding:.72rem 1.65rem;border-radius:9px;
  color:var(--blue);border:1.5px solid #cfe3f8;
  background:linear-gradient(180deg,#ffffff 0%,#eef6ff 100%);
  box-shadow:0 2px 6px rgba(16,20,24,.10),
             inset 0 1px 0 rgba(255,255,255,.95),
             inset 0 -2px 0 rgba(17,115,212,.10);
  transition:transform .15s;
}
.btn-outline:hover{transform:translateY(-2px);}

.foot{background:#0d1a26;color:#93a4b4;padding:3rem 0;font-size:.95rem;}
.foot p{margin:.3rem 0;}
.foot a{color:#cfe0ef;}
.foot a:hover{color:#fff;}
.foot-name{
  font-family:'Barlow Condensed',sans-serif;font-weight:800;font-size:1.5rem;
  letter-spacing:.05em;color:#fff;margin:0 0 .5rem;
}

/* >> THE BASE ROW (wd-s18) - a rule, then one line left and the copyright right.
   Structure copied from the GCH example's `.foot-base`, which is the only other footer
   we have built and already solved this: a divider, a flex row that splits, and a stack
   on a phone.

   >> THE COLOURS ARE NOT COPIED, AND THAT IS THE POINT. GCH's row is #6B563E on a warm
   cream footer; this one sits on #0d1a26. Taking its values across would have put brown
   text on navy. Same shape, this site's palette - the geometry travels, the colours do not.

   >> #7d90a2 IS MEASURED, NOT PICKED BY EYE. The row has to read as secondary to the
   footer's own #93a4b4 body text while still being legible at .8rem. Against #0d1a26:
   #93a4b4 = 6.88:1, #7d90a2 = 5.35:1, and the dimmer #6f8296 that was tried first =
   4.45:1, which is UNDER the 4.5:1 floor for small text. Dimmer than this is not an
   option here. */
.foot-base{
  /* >> 1.6 -> 2.8rem, wd-s18 (owner, "slightly lower"). Same change and same reasoning as
     the GCH footer, kept in step so the two example sites do not drift: the gap ABOVE the
     rule is what moves the group down, and it is NOT done by cutting the footer's bottom
     padding, which would push the row against the end of the page. */
  margin-top:2.8rem;padding-top:1.1rem;
  border-top:1px solid rgba(255,255,255,.10);
  font-size:.8rem;color:#7d90a2;
  display:flex;justify-content:space-between;align-items:baseline;gap:1rem;flex-wrap:wrap;
}
/* the two halves of the row are `p` inside `.foot`, which carries a .3rem margin - it
   would push them off the baseline they are being aligned on */
.foot-base p{margin:0;}


/* =========================================================
   SMALLER SCREENS
   Most visitors arrive here on a phone, in a hot house, in a
   hurry - so the phone button and the headline come first and
   nothing is allowed to need a horizontal scroll.
   ========================================================= */

@media (max-width:1000px){
  .svc{grid-template-columns:repeat(2,1fr);}
  .quotes{grid-template-columns:1fr;}
  .team{grid-template-columns:repeat(2,1fr);gap:1.5rem;}
  .plans{grid-template-columns:1fr;}
  .reviews{grid-template-columns:1fr;}
  .svc-grid{grid-template-columns:repeat(2,1fr);}
  .contact-grid{grid-template-columns:1fr;gap:2.25rem;}
  .info-panel{order:-1;}
}

@media (max-width:760px){
  /* the van drops under the heading and stops being full-bleed wide */
  .head-van{grid-template-columns:1fr;gap:1.25rem;}
  .head-van img{max-width:460px;}

  /* the first screen stops being one screenful and simply flows */
  /* >> THE DARK WASH HAS TO BE REDRAWN FOR A TALL NARROW SCREEN, NOT JUST INHERITED.
     The desktop version is an ellipse anchored at the LEFT, behind hero copy that sits
     in the left half of a wide photo. Stack that same shape into a phone and the copy
     is no longer where the dark part is - caught in review, the "Licensed TACLB#" line
     was sitting on bright pavers and had effectively vanished.
     The phone version is a vertical wash instead, and it is deliberately shaped in three
     parts for the same reason the desktop one is elliptical: CLEAR at the top so the dark
     nav text still reads on its frosted panel, DARK through the middle where the white
     headline and the trust line sit, and CLEAR again at the bottom so the service cards
     keep a bright base. Darkening the whole thing evenly breaks the two glass panels,
     which is exactly the mistake the desktop scrim already documents.
     Photo also switches to `cover` here: at a fixed height it ran out before the cards
     did, leaving them on flat colour with nothing behind them to frost. */
  /* >> AND THE PHOTO GETS A BAND, IT DOES NOT FILL THE HERO.
     `cover` was tried first and is wrong here: the photo is a wide landscape shot and a
     phone hero is a tall narrow box, so filling it crops away everything except a vertical
     strip of roof - the house stops being recognisable, which is the one job the photo has.
     Instead it runs as a band across the top at its own proportions and fades into solid
     navy, so the house reads properly and the copy below still has a dark base. */
  .hero{
    min-height:auto;
    background:
      linear-gradient(180deg,
        rgba(6,18,30,.10) 0%,  rgba(6,18,30,.34) 22%,
        rgba(6,18,30,.72) 52%, rgba(15,34,51,.97) 76%,
        #0f2233 88%),
      /* top-aligned on purpose: the nav has to sit over bright sky, because its ink is
         dark navy on a light frosted panel and it goes unreadable over anything dark. */
      url("https://media.7starwebstudio.com/example/ridgeline/images/demo-home.jpg") 38% 0/auto 74vh no-repeat #0f2233;
  }
  /* the frosted card band needs a photo behind it to work, and down here there is none,
     so on a phone the cards become ordinary solid cards on a pale strip */
  .svc{
    background:var(--tint);border:0;border-radius:0;box-shadow:none;
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }
  .card{
    background:#fff;border:1px solid var(--line);
    -webkit-backdrop-filter:none;backdrop-filter:none;
    box-shadow:0 2px 10px rgba(16,20,24,.06);
  }
  .card b,.card p{text-shadow:none;}
  .ic{background:#e3f0fd;border:1px solid #c9e2fb;box-shadow:none;}
  /* the bar becomes two rows here, so the fallback spacer has to grow with it -
     see the note on --bar-h at the top. nav.js overwrites this with the real figure. */
  :root{--bar-h:7.6rem;}
  .nav{flex-wrap:wrap;justify-content:space-between;gap:.75rem;
    margin:.75rem .75rem 0;padding:.6rem .9rem;}
  /* >> AND THE SOLID BAR HAS TO TAKE THAT MARGIN BACK OFF. The line above is a plain
     `.nav` rule and it sits LATER in the file than `.nav-solid`, so on a phone it was
     winning and giving the solid bar a 12px gap above it and down both sides. In the
     flow that only ever showed white page behind it. Pinned, the page scrolls through
     those gutters, which reads as a slab floating over the content. */
  .nav-solid,.nav.is-solid{margin:0;}
  .nav nav{order:3;flex-basis:100%;justify-content:space-between;gap:.5rem;}
  .nav nav a{font-size:.9rem;}
  .logo{font-size:1.25rem;}
  .mark{width:1.8rem;height:1.8rem;}

  /* >> THE PHONE BUTTON SITS ON THE SAME ROW AS THE LOGO (owner, wd-s6 - phone only).
     Brand plus button was a few pixels wider than a phone, so the button wrapped to a
     row of its own, which made the frosted bar a whole row taller and ate that much of
     the hero behind it. Both are shrunk just enough to fit on one line and the brand is
     allowed to give up space first, so the row holds instead of wrapping.
     `min-width:0` on the brand is the part that actually does it - a flex item refuses
     to shrink below its content width without it, and the button gets pushed down. */
  .brand{flex:0 1 auto;min-width:0;}
  .phone-btn{font-size:.95rem;padding:.44rem .85rem;letter-spacing:.02em;}
}

@media (max-width:760px){

  .hero-body{padding:3.5rem 1.25rem 3rem;}
  .hero-copy h1{font-size:clamp(2.5rem,11vw,3.4rem);}
  .sub{max-width:none;}
  .cta-row .btn,.cta-row .btn-ghost{flex:1 1 auto;text-align:center;}
  .trust{gap:.5rem 1.2rem;font-size:.85rem;}

  .svc{grid-template-columns:1fr;margin:0 .75rem 1rem;padding:.85rem;gap:.75rem;}

  .steps{grid-template-columns:1fr;gap:1.3rem;}

  .nav-solid{padding:.6rem .9rem;}
  .plan{padding:1.5rem 1.35rem;}
  .svc-grid{grid-template-columns:1fr;}

  /* >> THE CONTACT PANEL JUMPS ABOVE THE FORM ON A PHONE. Somebody whose AC just died
     should reach a tappable number immediately, not after four form fields. The markup
     keeps the form first because that is the reading order on a wide screen. */
  .contact-grid{grid-template-columns:1fr;gap:2rem;}
  .info-panel{order:-1;}
  .page-head{padding:2.5rem 0 2rem;}

  /* >> THE BASE ROW STACKS RATHER THAN SPLITS. Left-and-right needs width; on a phone the
     sentence wraps to two or three lines and the copyright ends up floated beside its last
     word instead of under the whole thing. */
  .foot-base{flex-direction:column;gap:.45rem;}
}

/* One more step down for small phones, where even the trimmed pair does not fit.
   >> KEEP THIS AFTER THE 760 BLOCK. Equal specificity means file order decides,
   so sitting above it would let any later .logo or .phone-btn rule win. */
@media (max-width:400px){
  .logo{font-size:1.12rem;letter-spacing:.04em;}
  .mark{width:1.6rem;height:1.6rem;}
  .phone-btn{font-size:.88rem;padding:.4rem .7rem;}
}

@media (prefers-reduced-motion:reduce){
  *{transition:none !important;animation:none !important;}
}
