/* Everything below the hero: service cards, the "Also ask me about" grid,
   the About and most-recent-job photo pairs, the Why choose cards, and the
   parallelogram buttons shared by the CTA band and the Why section.
   Loaded after styles.css, so plain selectors win without !important. */

.pg-row {
  /* Photo shape. 4/3 was 260px tall on a 347px card and read as a letterbox;
     4/5 puts it at 434px. One value to dial: 1/1 gives 347, 3/4 gives 463. */
  --pg-ratio: 4 / 5;
  /* Scaled with the card. The slant is a fixed horizontal offset, so the angle
     it cuts is offset over height: leaving it at 34px on a card that grew from
     388px to 562px would have flattened the edge from 5.0 to 3.5 degrees and
     the parallelogram would have started looking like a rectangle. 49px holds
     the angle the shorter card had. */
  --slant: 49px;
  /* White rather than the section's own #FAF9F7, so the card still reads as a
     card against it. The difference is slight, which is what the drop-shadow
     below is for. */
  --pg-card: #FFFFFF;
  display: grid;
  /* No cap. The cards take whatever the row gives them, and the row is pulled
     out to the full gutter below, so they are as wide as three across can be
     at this window. */
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  /* Sets the space under the blue rule. 28px left it 10px off the cards while
     the rule sat 30px below the lede, so the separator read as belonging to
     the row rather than dividing the two. */
  margin-top: 48px;
  /* The whole gutter, so the row runs edge to edge with no margin left at all.
     This is the width ceiling for three across: at a 1200px window that is
     1200 less the two 8px gaps, or 394.67 a card. The only ways past it are a
     smaller gap, which buys 5px, a wider window, or dropping to two cards a
     row.

     The cost: the row no longer lines up with the heading and lede above it,
     which every other block on the page does. Drop this one line to put it
     back on the shell. */
  margin-inline: calc(-1 * var(--gutter));
}

.pg-card {
  background: var(--pg-card);
  /* A filter, not box-shadow. clip-path clips the shadow away with everything
     else, so a box-shadow on this element would simply not be painted.
     drop-shadow runs after the clip and follows the slanted silhouette. */
  filter: drop-shadow(0 10px 24px rgba(20, 22, 26, .10));
  clip-path: polygon(var(--slant) 0, 100% 0, calc(100% - var(--slant)) 100%, 0 100%);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Keep the service cards square-edged as the tablet layout narrows. */
@media (max-width: 999.98px) {
  .pg-card { clip-path: none; }
}

/* The ratio has to win over the photo. .pg-media is a flex item, so its height
   comes from its content, and a tall source pushed it past 4/3: the three
   source images are 681x721, 1332x1658 and 1332x950, which gave three
   different photo heights and three different yellow bands. Taking the
   picture out of flow leaves nothing to push against, so the ratio is the
   only thing setting the height. */
.pg-media {
  position: relative;
  aspect-ratio: var(--pg-ratio);
  flex: none;
  margin: 0;
}
.pg-media picture {
  position: absolute;
  inset: 0;
}
.pg-driveway-gallery,
.pg-patio-gallery,
.pg-stamped-gallery { display: none; }
.pg-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The bottom edge runs from 0 to (100% - slant), so the right side of this
   block is the short one and needs the slant added to its padding or the last
   letter sits on the cut. The left side is the opposite: the cut leans away
   going down, so the text only has to clear a few pixels there. */
.pg-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 12px;
  /* align-items centres the CTA, which is an inline-flex box and would
     otherwise stretch the full width; text-align centres the lines within the
     title and subtitle. The existing padding is deliberately left asymmetric,
     30px against 71px: the block sits at the bottom of the card where the
     shape has leaned left, so its content box is already offset about 20px
     left of the card's centre, which is where the shape's own centre is at
     that height. Even padding would have centred on the box and looked a
     touch right of centre against the slant. */
  align-items: center;
  text-align: center;
  padding: 18px 22px 22px;
  padding-right: calc(22px + var(--slant));
  padding-left: 30px;
}

.pg-title {
  margin: 0;
  font-size: clamp(18px, 1.5vw, 21px);
  font-weight: 700;
  line-height: 1.2;
  color: var(--ink);
}

.pg-sub {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  color: var(--accent);
}
.pg-sub-mobile-break { display: none; }

/* Only the Driveways card carries one. The three cards are grid items and
   stretch to a common height, so the other two simply gain the whitespace
   rather than going short. Muted and a step down in size, so it reads as a
   note under the category line and not as a second subtitle. */

/* Three across needs the full width. Below the split the row stacks, and the
   slant comes down with it: the same 34px on a full width card is a much
   shallower angle and stops reading as a parallelogram. */
@media (max-width: 899.98px) {
  .pg-row {
    grid-template-columns: 1fr;
    --slant: 22px;
  }
}

/* Section head centred, and the heading held to one line.

   The 62ch cap on .section-head is what was breaking the heading, not the type
   size: at 50px the line measures 1088px, which is exactly the shell's content
   box, while the cap sits at 675px. Removing the cap alone would leave it
   fitting with nothing to spare, so the size comes down to 48px and is tied to
   the viewport as well, which keeps it on one line as the window narrows.

   nowrap only applies from 900px up. A 45 character heading held to one line
   on a phone would have to drop to about 15px to fit, so below that it wraps
   at its normal size instead. */
.services .section-head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}

.services .section-lede {
  max-width: 68ch;
  margin-inline: auto;
}

@media (min-width: 900px) {
  .services .section-head h2 {
    white-space: nowrap;
    font-size: min(48px, 4vw);
  }
}

/* Blue rule between the lede and the cards.

   A pseudo-element on the head rather than a new div, so the markup this
   variant adds stays limited to the card row itself. Centred to match the
   head above it, and short rather than full width: a rule running the whole
   way across would read as the end of the section, which is the job the
   <hr> further down the page already does. */
.services .section-head::after {
  content: "";
  display: block;
  width: 96px;
  height: 3px;
  background: var(--accent);
  margin: 30px auto 0;
}

/* ------------------------- the CTA band and Why section buttons

   Same parallelogram language as the cards, on both button pairs that sit on
   a photograph: the one under "If I don't pick up, I'm pouring" and the one
   under "Why choose Legacy Concrete". One rule rather than two copies, so the
   two pairs cannot drift apart.

   The angle is not the cards' angle. The cards cut 49px over 641px of height,
   which is 4.8 degrees; the same angle on a 51px tall button is a 4px slant,
   invisible. 14px over 51px reads as a slant at this size, at about 15
   degrees. Matching the number or matching the angle are both defensible and
   they are not the same thing here.

   Two things the clip breaks, both fixed below rather than left to look
   accidental:

   1. box-shadow does not survive clip-path. .btn-primary carries one, and it
      simply would not paint. drop-shadow runs after the clip and follows the
      slanted silhouette.
   2. A border does not survive it either, and .btn-ghost is nothing but a
      border: 1px of white at 55% over the photo. Clipped, it would keep its
      top and bottom edges and lose both slanted ones, which reads as a bug.
      So it becomes a solid fill instead, white with blue type, which is the
      same treatment the hero call button already uses. */
.cta-actions .btn,
.why-actions .btn {
  --btn-slant: 14px;
  clip-path: polygon(var(--btn-slant) 0, 100% 0, calc(100% - var(--btn-slant)) 100%, 0 100%);
  /* room for the cuts, so neither end of the label sits on a slanted edge */
  padding-inline: calc(26px + var(--btn-slant));
}

.cta-actions .btn-primary,
.why-actions .btn-primary {
  box-shadow: none;
  filter: drop-shadow(0 8px 18px rgba(20, 22, 26, .28));
}

.cta-actions .btn-ghost,
.why-actions .btn-ghost {
  background: #FFFFFF;
  border-color: #FFFFFF;
  color: var(--accent);
}
.cta-actions .btn-ghost:hover,
.why-actions .btn-ghost:hover {
  background: var(--pale);
  border-color: var(--pale);
  color: var(--accent-hover);
}
.cta-actions .btn-ghost,
.why-actions .btn-ghost {
  position: relative;
  --cta-edge: 1.34px;
}
.cta-actions .btn-ghost::before,
.why-actions .btn-ghost::before {
  content: "";
  position: absolute;
  inset: var(--cta-edge) calc(var(--cta-edge) * 1.344);
  background: #FFFFFF;
  clip-path: polygon(13.36px 0, 100% 0, calc(100% - 13.36px) 100%, 0 100%);
  pointer-events: none;
  transition: background .2s ease;
}
.cta-actions .btn-ghost > span { position: relative; }
.why-actions .btn-ghost > span { position: relative; }
.cta-actions .btn-ghost:hover,
.why-actions .btn-ghost:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent);
}
.cta-actions .btn-ghost:hover::before { background: #FFFFFF; }
.why-actions .btn-ghost:hover::before { background: #FFFFFF; }

/* ------------------------------------- "Also ask me about", 3 across, 2 down

   Six services in small parallelograms. From 740px up only: below that the
   .ask-row list is hidden entirely and the .ask-acc accordion takes over, so
   styling it there would be styling something nobody sees.

   The auto-fit track in styles.css is replaced with a fixed three, so the grid
   is 3 by 2 rather than reflowing to four tracks at wider widths. grid-auto-rows
   1fr keeps the two rows the same height: Concrete Cutting's description is
   four times the length of Fire Pits', and without it the second row would be
   visibly taller than the first.

   border-bottom comes off for the same reason the ghost button lost its
   border: the clip keeps horizontal edges and cuts the slanted ones, so a rule
   underneath would stop short at both ends. */
@media (min-width: 740px) {
  /* Out to the same line as the card row above, so Concrete Extensions starts
     where Concrete Driveways starts. Same pull as .pg-row uses, applied to the
     whole .ask block rather than the grid alone: moving the grid and leaving
     the "Also ask me about" label behind on the shell would read as a mistake,
     not as alignment. */
  .ask {
    /* 10px short of the full pull, which is the room the stagger below needs.
       At the full pull the block already sat on 0 and 1200, so shifting one
       row left and the other right would have run both off the window. Held
       back by the stagger distance, the top row lands on 0 after its shift,
       which is where the Concrete Driveways card starts, and the bottom row
       finishes on 1200. */
    margin-inline: calc(-1 * max(0px, var(--gutter) - 10px));
  }

  /* The two rows offset against each other. .ask-grid holds both the .ask-row
     blocks and the .ask-acc accordions, alternating, so the six .ask-row
     elements are children 1, 3, 5, 7, 9 and 11. The accordions are display
     none at this width but nth-child still counts them, which is why the split
     is at 6 and 7 rather than at 3 and 4. */
  .ask-row:nth-child(-n+6) { transform: translateX(-10px); }
  .ask-row:nth-child(n+7)  { transform: translateX(10px); }

  .ask-grid {
    grid-template-columns: repeat(3, 1fr);
    grid-auto-rows: 1fr;
    /* Row gap 20, column gap 0, which comes out as 20px of visible space in
       both directions.

       The two are not measured the same way. Two parallelograms side by side
       lean identically, so their facing edges are parallel and the space
       between them is column-gap PLUS the slant, at every height. Stacked, one
       sits flat above the other and the gap is just row-gap. With 8px set on
       both, the sides read 28 and the rows read 8.

       So the column gap goes to 0 and lets the 20px slant be the whole space,
       and the row gap is set to that same 20. Tighter than 20 means a smaller
       --ask-slant: the shape's own contribution is the floor here. */
    gap: 20px 0;
    margin-top: 22px;
  }

  /* The card is now a two sided thing: the name on the front, the description
     on the back, flipped on hover around the horizontal axis.

     .ask-row keeps none of the card's own look. It is only the 3D stage now,
     and everything visual moved onto the faces. That is deliberate: filter,
     clip-path and overflow all group an element, and a grouping ancestor
     flattens the 3D rendering context underneath it, so leaving the shadow
     and the clip on .ask-row would have collapsed the flip into a 2D smear.

     The height has to be declared. Both faces are absolutely positioned, so
     neither contributes to layout, and with grid-auto-rows: 1fr the rows would
     have had nothing to size against and collapsed to zero. 170px is set
     against the longest description, Concrete Cutting's. */
  .ask-row {
    --ask-slant: 20px;
    height: 170px;
    padding: 0;
    border-bottom: 0;
    background: none;
    perspective: 900px;
  }

  .ask-flip {
    position: relative;
    height: 100%;
    transform-style: preserve-3d;
    transition: transform .55s cubic-bezier(.2, .7, .3, 1);
  }
  /* focus-within as well as hover: the accordion below 740px is what touch
     gets, but a keyboard user on desktop needs a way in too. */
  .ask-row:hover .ask-flip,
  .ask-row:focus-within .ask-flip { transform: rotateX(180deg); }

  .ask-face {
    position: absolute;
    inset: 0;
    backface-visibility: hidden;
    display: flex;
    align-items: center;
    /* justify-content centres the flex child, text-align centres the lines
       inside it once the description wraps. Both are needed. The text lands on
       the true centre of the shape as well as the box: at the vertical middle
       the parallelogram runs from slant/2 to width minus slant/2, so its
       midpoint is the box midpoint, and the faces are vertically centred. */
    justify-content: center;
    text-align: center;
    clip-path: polygon(var(--ask-slant) 0, 100% 0, calc(100% - var(--ask-slant)) 100%, 0 100%);
    background: #FFFFFF;
    box-shadow: 0 8px 18px rgba(20, 22, 26, .08);
    padding: 18px calc(18px + var(--ask-slant));
  }

  /* The revealed side in the site's own blue tint, so a hovered card reads as
     lit up rather than just turned over. --accent-tint is the token already
     used for blue backgrounds elsewhere, not a new colour. */
  .ask-back {
    transform: rotateX(180deg);
    background: var(--accent-tint);
  }
  .ask-back p {
    margin: 0;
    font-size: 15px;
    color: var(--slate);
    text-wrap: pretty;
  }

  @media (prefers-reduced-motion: reduce) {
    .ask-flip { transition: none; }
  }
}

/* "Also ask me about" in the accent blue, centred over the grid.

   display: block because it is a <span>, and text-align has nothing to act on
   while it is inline and only as wide as its own text. Outside the 740px
   block, so the phone layout gets the same treatment. */
.ask-eyebrow {
  display: block;
  text-align: center;
  color: var(--accent);
}

/* ------------------------------------------------- About, two photos

   A staggered pair: Arturo top left and high, the driveway bottom right and
   low, overlapping him by two grid columns. Both sit on a soft blue
   parallelogram that bridges them.

   The two photos share grid row 1 of a 12 column grid and overlap on columns
   6 and 7. Same row rather than absolute positioning, so the row still sizes
   itself off the taller of the two and the section cannot collapse.

   The blue is a pseudo-element, so it takes no space and neither photo moves
   because of it. It is clipped rather than skewed: transform: skewX(-15deg)
   is the same shape but it spills outside its own box by half the height
   times tan 15, about 80px each way here, which would have run it under the
   body copy on the right. A clip cannot leave its box. The slant is that
   angle expressed as a horizontal offset: height x tan(15deg). */
.about-portrait-wrap {
  position: relative;
  /* 570px of shape x tan(15deg) */
  --about-slant: 153px;
}

.about-portrait-wrap::before {
  content: "";
  position: absolute;
  /* Narrower than the photos rather than wider, and taller. Positive on the
     sides pulls the shape in from the column edge; negative top and bottom
     pushes it past them. */
  inset: -46px 18px;
  /* --accent, the same blue as the buttons and the nav's Contact, rather than
     the --accent-tint wash it started as. */
  background: var(--accent);
  clip-path: polygon(var(--about-slant) 0, 100% 0, calc(100% - var(--about-slant)) 100%, 0 100%);
  z-index: 0;
}

/* Two tracks with a real gap, rather than twelve with an empty column between
   the photos. The empty column was one twelfth of the width, about 49px, and
   it moved with the viewport; the gap is the thing being set here, so it
   should be the thing declared. */
.about-portraits {
  position: relative;
  z-index: 1;          /* both photos cut over the blue */
  /* flow-root rather than grid: the small photo now lies over the big one
     instead of sitting beside it, and flow-root keeps the big one's bottom
     margin inside this box so the small one has somewhere to hang. */
  display: flow-root;
}

/* Tall verticals, not the near square the single portrait used. */
.about-portrait {
  aspect-ratio: 3 / 4;
}

.about-portrait:not(.about-portrait-2) {
  width: 72%;
  margin-bottom: 46px;   /* room for the small one to hang below */
}

/* Over the big photo's bottom right corner, straddling it rather than sitting
   inside it. The mirror of the recent job section, which hangs its small photo
   off the top right instead; that section is untouched.

   The pale edge is the same hard shadow, zero blur, in the page background
   colour, offset only toward the sides that lie over the photo underneath.
   Bottom right means those are the left and the top, so both offsets are
   negative. On the recent job pair the small photo is high, so its lower edge
   is the one over the big and the vertical offset there is positive. */
.about-portrait-2 {
  position: absolute;
  bottom: 0;
  right: 40px;
  width: 40%;
  margin-top: 0;
  z-index: 2;
  box-shadow: -14px -14px 0 0 var(--pale);
}

/* styles.css pulls the portrait crop to 30% across, to keep Arturo clear of
   the edge in the shot it was written for. The sign is centred in its frame
   and wants the middle. */
.about-portrait-2 img {
  object-position: center;
}

/* Below the split the pair follows the reference the owner supplied
   (assets/images/example_mobile_about_section.jpg): big photo left, small
   photo right and BOTTOM ALIGNED with it, a gap between them rather than an
   overlap, and the parallelogram behind both with its top right corner left
   open by the short photo.

   That top right opening is the point of the composition. The small photo is
   short and sits on the floor of the row, so the blue behind it reads as a
   large wedge rather than a sliver, which is what makes the shape read as a
   backdrop at this size.

   This reverses two things from the previous pass, both deliberately, both
   from the reference: the corner overlap is gone, and so is the pale frame on
   the small photo. Desktop keeps both.

   Proportions are measured off the reference, which runs its photos at 54%
   and 36% of the frame with a 3% gutter and a 3% margin each side. */
@media (max-width: 899.98px) {
  .about-portraits {
    /* flow-root, not block: the big photo's bottom margin is the gap the
       small one hangs into, and block lets that margin collapse straight out
       of this box. The small photo then sits flush with the big one's bottom
       instead of straddling it. */
    display: flow-root;
    /* Inside the column, so the blue shows down both sides.

       margin, never padding. The small photo below is absolutely positioned,
       so its percentages resolve against this element's PADDING box while the
       big photo's resolve against its CONTENT box. Padding here would set the
       two measuring boxes 20px apart and they would drift as the column
       changes. A margin moves the whole box and leaves both on 94%. */
    margin-inline: 3%;
  }

  .about-portrait:not(.about-portrait-2) {
    width: 70%;
    /* The gap the small photo hangs into, desktop's 46px in proportion. */
    margin: 0 0 8%;
  }

  /* Straddling the big photo's bottom right corner, the same arrangement
     desktop uses. The pale edge is desktop's hard shadow, zero blur, offset
     only toward the two sides that lie over the photo underneath, which at
     this corner are the left and the top. 10px against desktop's 14, in
     proportion with the smaller photo. */
  .about-portrait-2 {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 42%;
    margin: 0;
    z-index: 2;
    box-shadow: -10px -10px 0 0 var(--pale);
  }

  /* Cut below the split. Free estimates is said in five other places on the
     page, so only the fifteen minutes and the Spanish line are lost with it.
     See CLAUDE.md: "español" appears nowhere else. */
  .about-estimate { display: none; }

  /* The band clears the photos' top by 15px and their floor by 10px, so both
     ends of the parallelogram read. The reference is proportionally the same,
     about 7% of the photo height above and 5% below.

     The slant is a percentage of the band's own width rather than desktop's
     px offset, because everything above is a percentage of the column and the
     column is not the viewport. The geometry: the big photo at 70% of a 94%
     inner box plus its 8% drop puts the block at 0.952W of the column width,
     the band adds 25px, and a 15 degree cut is height x tan(15deg). That
     lands at 27.4% of the band's width, holding within a tenth of a degree
     from 335 to 387.

     Recompute it if the photo widths, the gutter or the two offsets change.

     left and right are zero. The rule this replaced had them negative, which
     pushed the blue 14px past the content column at every width. */
  .about-portrait-wrap::before {
    top: -15px;
    right: 0;
    bottom: -10px;
    left: 0;
    height: auto;
    translate: none;
    clip-path: polygon(27.4% 0, 100% 0, 72.6% 100%, 0 100%);
  }
}

/* The About heading sits above both columns now, centred, on one line.

   It was the .about-head-mobile copy, which styles.css shows only below the
   breakpoint while .about-head-desktop runs inside the body column. One
   heading serves both now and the desktop copy is gone from the markup, so
   there is no second <h2> with the same words for a screen reader to read
   twice.

   Same approach as the services heading: nowrap only from 900px up, and the
   size tied to the viewport so the line keeps fitting as the window narrows.
   Below that it wraps at its normal size, since holding 44 characters on one
   line on a phone would take it under 15px. */
.about-head-top {
  display: block;
  /* Lifted on its own. An offset rather than a negative top margin, which
     would have dragged the photos and the body copy up with it. Nothing
     reflows, so the grid below stays exactly where it was. */
  position: relative;
  top: -42px;
  margin: 0 auto 34px;
  max-width: var(--maxw);
  padding-inline: var(--gutter);
  text-align: center;
  font-size: clamp(31px, 4.2vw, 50px);
}

@media (min-width: 900px) {
  .about-head-top {
    white-space: nowrap;
    font-size: min(46px, 3.9vw);
  }
}

/* Eyebrow over the About copy. Same treatment as "Also ask me about" further
   up the page, so the two read as the same kind of label: 12px, 700, wide
   tracking, uppercase, accent blue. Left aligned, because the copy under it
   is. */
.about-eyebrow {
  display: block;
  margin-bottom: 10px;
  /* 16px, up from the 12px the other eyebrows use. This one no longer matches
     "Also ask me about". */
  font-size: 16px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
    color: var(--accent);
}

/* Only the one that follows copy needs space above it. The first sits at the
   top of the column with the heading's own margin already above it; this one
   was landing hard against the end of the previous paragraph. */
.about-body p + .about-eyebrow {
  margin-top: 26px;
}

/* --------------------------------------- Why choose Legacy Concrete

   Three outlined parallelograms sharing their edges, as one run.

   The outline is a skewed pseudo-element, not a clip. Everything else on this
   page is clipped, but a clip cuts a border off the slanted sides and leaves
   it on the flat ones, and an inner fill does not work here either because
   this section sits on a photograph and the fill would block it.
   skewX on an empty box shears the border itself, which is the one case where
   skew is the right tool. The text is not inside the skewed element, so
   nothing needs counter-skewing.

   gap: 0 so the three touch. Adjacent cards' borders land on exactly the same
   line and read as one shared divider rather than two.

   The light blue is the colour the icons used, kept so removing them does not
   take the section's only accent with it. */
.why-grid {
  grid-template-columns: repeat(4, 1fr);
  /* 44px, not the 14 it looks like on screen. A skew paints outside its own
     box: at 8 degrees on a 210px card the outline runs 14.8px past each edge
     at the top and bottom, so the first 29.5px of any gap is spent just
     pulling the outlines apart. 44 leaves about 14px of daylight where they
     are closest. */
  gap: 44px;
}

/* The heading on the front, the body on the back, flipped on hover. Same
   motion as the "Also ask me about" cards.

   The skewed outline stays put while the content turns. It is the card's own
   ::before, outside the flipping element, so the row of joined parallelograms
   holds its shape and only what is inside each one moves.

   Height has to be declared, as it did on the ask cards: both faces are
   absolutely positioned, so neither contributes to layout and the row would
   collapse. 210px is set against the longest back, card one's. */
.why-card {
  position: relative;
  height: 210px;
  padding: 0;
  perspective: 900px;
}

.why-flip {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform .55s cubic-bezier(.2, .7, .3, 1);
}
.why-card:hover .why-flip,
.why-card:focus-within .why-flip { transform: rotateX(180deg); }

.why-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 30px;
}

.why-back { transform: rotateX(180deg); }

/* styles.css sets these white and near-white for a card that used to be a
   transparent outline on a photograph. On white they have to invert. */
.why-card h3 { color: var(--ink); }
.why-card p { color: var(--slate); }

@media (prefers-reduced-motion: reduce) {
  .why-flip { transition: none; }
}

/* Filled white, like the service cards up the page.

   The fill goes on this skewed pseudo-element, not on .why-card. A background
   on the card itself would paint its rectangular box and the parallelogram
   would vanish behind a plain white block; on the skewed element it takes the
   shape. The outline comes off with the fill in: a blue keyline around a white
   card reads as a second idea, and the service cards carry none. */
.why-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: #FFFFFF;
  transform: skewX(-8deg);
  pointer-events: none;
  /* Ambient rather than one drop: four layers, each roughly double the blur of
     the one before at a low opacity. The tight layer is the contact edge that
     stops the card looking pasted on, the wide ones are the soft falloff. A
     single 30px shadow has one hard-ish boundary; stacking them gives a curve
     instead, which is what reads as soft.

     Tuned up from the usual light-background values, since these sit on a dark
     photograph and a .08 layer would disappear into it. */
  box-shadow:
    0 2px 4px rgba(6, 10, 16, .16),
    0 8px 16px rgba(6, 10, 16, .16),
    0 20px 40px rgba(6, 10, 16, .20),
    0 40px 80px rgba(6, 10, 16, .22);
}

.why-card h3,
.why-card p {
  position: relative;   /* over the outline */
}

/* Mobile cards keep their front face and compact height without interaction. */
@media (max-width: 899.98px) {
  .why-grid {
    grid-template-columns: 1fr 1fr;
    align-items: start;
  }
  .why-card::before { transform: skewX(-4deg); }
  .why-card {
    height: 96px;
    cursor: default;
    transition: none;
  }
  .why-card .why-flip,
  .why-card:hover .why-flip,
  .why-card:focus-within .why-flip {
    transform: none;
    transition: none;
  }
  .why-back { display: none; }
  .why-face { padding: 12px 16px; }
}

/* --------------------------------------------- Most recent job

   Title, one line of copy, the About section's two photo composition, and a
   call.

   The composition is a second copy of the About geometry rather than a shared
   class: making it shared would mean rewriting the About markup too, which is
   a refactor rather than this change. The two will drift if one is tuned and
   the other is not. Worth folding into one class if this stays.

   The figure is held to 590px, the width the About column happens to be, so
   the 153px slant cuts the same 15 degrees it does up there. */
.rj {
  padding-block: clamp(56px, 7vw, 96px);
}

/* Copy on the left, the photo pair on the right. The figure track is fixed at
   the 590px the composition is built around, so the slant keeps cutting the
   same 15 degrees; the copy takes whatever is left. */
.rj-grid {
  display: grid;
  grid-template-columns: 1fr 590px;
  gap: clamp(34px, 5vw, 68px);
  align-items: center;
}

.rj-head {
  margin: 0;
  font-size: clamp(31px, 3.4vw, 44px);
}
.rj-story {
  position: relative;
  margin-top: 24px;
  padding: 4px 0 18px 22px;
  border-left: 4px solid var(--accent);
}
.rj-story::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: -4px;
  width: 64px;
  height: 4px;
  background: var(--accent);
}
.rj-story p {
  margin: 0 0 14px;
  font-size: 17px;
  line-height: 1.65;
  color: var(--slate);
}
.rj-story p:last-child { margin-bottom: 0; }
.rj-story .rj-lede { color: var(--ink); font-weight: 600; }

.rj-review.rv-card {
  width: min(100%, 360px);
  margin: 22px 0 0;
  padding: 0;
}
.rj-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 18px;
  margin-top: 28px;
}
.rj-bottom .rj-actions { margin-top: 0; }
.rj-bottom .rj-review {
  flex: 1 1 220px;
  max-width: 360px;
  margin: 0 0 0 auto;
}
.rj-review .rv-card-link { padding: 16px 18px; }
.rj-review .rv-quote {
  margin: 10px 0 12px;
  font-size: 14px;
  line-height: 1.5;
}
.rj-review .rv-foot { padding-top: 10px; }
.rj-review .rv-name { font-size: 14px; }
.rj-review .rv-src { font-size: 12px; }
.rj-review .rv-stars { font-size: 13px; }

.rj-lede {
  margin: 14px 0 0;
  font-size: 18px;
  color: var(--slate);
}

.rj-figure {
  position: relative;
  margin: 0;
  --rj-slant: 153px;
}

.rj-figure::before {
  content: "";
  position: absolute;
  inset: -46px 18px;
  background: var(--accent);
  clip-path: polygon(var(--rj-slant) 0, 100% 0, calc(100% - var(--rj-slant)) 100%, 0 100%);
  z-index: 0;
}

/* The small photo lies over the big one's top right corner, rather than
   sitting beside it in its own column. Only this section: the About pair keeps
   its two columns and is untouched.

   No longer a grid. Two overlapping boxes want one in flow and one placed
   against the container, and a grid would need them in the same cell fighting
   over alignment. */
.rj-pair {
  position: relative;
  z-index: 1;
  /* flow-root, so the big photo's top margin stays inside this box instead of
     collapsing through it. Without it the margin moved the whole pair down and
     the small photo, positioned against the pair, came with it: both tops
     landed on the same line and nothing stood proud. */
  display: flow-root;
}

/* Placeholder boxes, deliberately plain and labelled so they cannot be
   mistaken for the real thing. Same 3/4 the About photos use. */
.rj-photo {
  position: relative;
  aspect-ratio: 3 / 4;
  overflow: hidden;
}

/* Absolute, the same as the About photos: in flow, a tall source pushes the
   box past its ratio and the stagger collapses. */
/* Same as styles.css does for the About photos: the wrapper must not introduce
   a box of its own, so the img stays the thing being positioned. */
.rj-photo picture { display: contents; }

.rj-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* The big one carries the layout, dropped far enough for the small one to
   stand proud above it. */
.rj-photo:not(.rj-photo-2) {
  width: 72%;
  margin-top: 46px;
  /* Pulled out past the figure's left edge. The copy column ends 68px to the
     left of here, so there is room before the two would meet. */
  margin-left: -20px;
}

/* Over the big photo's top right corner: hung on the container's right edge
   and its top, so it straddles that corner rather than sitting inside it.

   The pale edge is the same trick the old About overlap used, turned round. A
   hard shadow, zero blur, in the page's own background colour, offset only
   towards the sides that touch the photo underneath. There it was the left and
   top; here the small photo is high and right, so the edges over the big one
   are its left and its bottom, and the offset goes -14px across and +14px
   down. Both photos are grey concrete at the seam, so without it they read as
   one picture. */
.rj-photo-2 {
  position: absolute;
  top: 0;
  right: 15px;
  width: 40%;
  margin-top: 0;
  z-index: 2;
  box-shadow: -14px 14px 0 0 var(--pale);
}

/* Under the copy rather than centred below everything. The left column would
   otherwise hold two lines against a 780px figure and read as mostly empty. */
.rj-actions {
  display: flex;
  margin-top: 28px;
}

/* The button takes the CTA band's parallelogram. It sits on the page's own
   background rather than a photo, so unlike those it keeps its shadow off and
   needs no white-fill counterpart. */
.rj-actions .btn {
  --btn-slant: 14px;
  clip-path: polygon(var(--btn-slant) 0, 100% 0, calc(100% - var(--btn-slant)) 100%, 0 100%);
  padding-inline: calc(26px + var(--btn-slant));
  box-shadow: none;
}

/* One column below the figure's own width plus a gutter, or the fixed 590px
   track would overflow. */
@media (max-width: 899.98px) {
  .rj-grid { grid-template-columns: 1fr; }
  .rj-figure { max-width: 590px; }
}

/* Below the split this pair matches the About one, mirrored. Same widths,
   same drop, same band; the small photo just hangs off the top right corner
   instead of the bottom right, so its pale edge is on the left and the bottom
   rather than the left and the top.

   The order changes too. Above the split the copy column holds the heading,
   the story and the button and review together, with the figure beside it.
   On one column the owner wants the photos between the story and the button,
   so the pair backs up the claim before the button asks for the click.
   .rj-copy goes display: contents there, which promotes its three children to
   grid items of .rj-grid and lets order put the figure among them. The
   wrapper carries no styling of its own, so nothing is lost with the box. */
@media (max-width: 899.98px) {
  .rj-copy { display: contents; }
  .rj-head { order: 1; }
  .rj-story { order: 2; }
  .rj-figure { order: 3; }
  .rj-bottom { order: 4; }

  .rj-pair {
    /* margin, never padding: the small photo is absolutely positioned and
       would measure against the padding box while the big one measures
       against the content box. */
    margin-inline: 3%;
  }

  .rj-photo:not(.rj-photo-2) {
    width: 70%;
    margin-left: 0;
    /* The drop the small photo stands proud into, above rather than below. */
    margin-top: 8%;
  }

  .rj-photo-2 {
    position: absolute;
    top: 0;
    right: 0;
    width: 42%;
    margin-top: 0;
    /* Left and bottom, the two sides lying over the photo underneath at this
       corner. 10px against desktop's 14, in proportion with the photo. */
    box-shadow: -10px 10px 0 0 var(--pale);
  }

  /* Clears the pair's top by 15px and its floor by 10px, same as About. The
     slant is a percentage of the band's own width for the same reason it is
     there: the column is not the viewport. Geometry matches About exactly,
     the block at 0.952W of the column, so the figure is the same 27.4%. */
  .rj-figure::before {
    top: -15px;
    right: 0;
    bottom: -10px;
    left: 0;
    clip-path: polygon(27.4% 0, 100% 0, 72.6% 100%, 0 100%);
  }

  /* The review card runs the full column under the photos and the button sits
     beneath it. column-reverse rather than reordering by hand: the card is the
     second child in the markup, so reversing puts it on top and leaves the DOM
     alone for desktop, which still reads button then card.

     Side by side was tried first and the card came out 143px wide, too narrow
     for a name, a chip, a quote and a footer link. Full width is the fix; the
     button never needed the room. */
  .rj-bottom {
    display: flex;
    flex-direction: column-reverse;
    align-items: stretch;
    gap: 14px;
  }
  .rj-bottom .rj-actions { margin-top: 0; }
  /* The flex sizing above is desktop's row; here the column sets the width and
     the auto margin would push the card off it. */
  .rj-bottom .rj-review {
    flex: none;
    max-width: none;
    width: 100%;
    margin: 0;
  }
}

/* Contact section: three matching parallelograms for direct contact. */
.contact-prompts {
  display: grid;
  gap: 30px;
  margin: 0;
  font-size: clamp(29px, 3.3vw, 40px);
}
.contact-note {
  margin-top: 30px;
  font-size: 17px;
  line-height: 1.6;
}
.contact-left .contact-note {
  position: relative;
  padding: 4px 0 18px 22px;
  border-left: 4px solid var(--accent);
  font-size: 22px;
  font-weight: 700;
  line-height: 1.4;
  color: var(--ink);
  text-decoration: none;
}
.contact-left .contact-note::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: -4px;
  width: 64px;
  height: 4px;
  background: var(--accent);
}
@media (min-width: 1100px) {
  .contact-left .contact-note {
    white-space: nowrap;
    font-size: clamp(16px, 1.5vw, 18px);
  }
}
/* Below the split the three questions centre and the line under them stays
   left, keeping its blue rule. The two blue Text and Call cards come off
   entirely: the banner, the floating call bar and the form all offer the same
   two actions within a thumb's reach of here. */
@media (max-width: 899.98px) {
  .contact-prompts { text-align: center; }
  .contact-left .contact-note {
    text-align: left;
    /* The rule is the reason this cannot centre with the questions: a left
       border on centred text reads as a misalignment. */
    white-space: normal;
  }
  .contact-channels.quick-cards { display: none; }
}

.contact-channels.quick-cards {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin-top: 36px;
}
.contact-channels .quick-card {
  min-width: 0;
  min-height: 120px;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 12px 18px;
  background: var(--accent);
  border: 0;
  color: #FFFFFF;
  text-align: center;
  clip-path: polygon(14px 0, 100% 0, calc(100% - 14px) 100%, 0 100%);
  transition: background .2s ease, transform .2s ease;
}
.contact-channels .quick-card:hover {
  background: var(--accent-hover);
  transform: translateY(-3px);
}
.contact-channels .quick-kind,
.contact-channels .quick-num {
  color: #FFFFFF;
  font-size: 16px;
}
.contact-channels .quick-num {
  font-family: Figtree, system-ui, sans-serif;
  font-weight: 600;
  letter-spacing: 0;
  overflow-wrap: anywhere;
}

/* Two-column Google review carousel */
.reviews { padding: clamp(72px, 8vw, 116px) 0; }
.rv-layout {
  position: relative;
  z-index: 1;
  width: min(var(--maxw), calc(100% - 2 * var(--gutter)));
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(350px, 1fr) minmax(0, 1.8fr);
  align-items: center;
  gap: clamp(34px, 6vw, 88px);
}
.rv-head { position: relative; align-self: stretch; display: flex; align-items: center; text-align: left; padding: 0; }
.rv-head { transform: translateX(-5px); }
.rv-head h2 {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 0;
  padding-left: 18px;
  font-size: clamp(48px, calc(3.5vw + 10px), 54px);
  line-height: 1.08;
}
.rv-head::before {
  content: "";
  position: absolute;
  left: 0;
  top: -8px;
  height: 268px;
  border-left: 2.4px solid var(--accent);
}
.rv-head h2 span { display: block; white-space: nowrap; }
.rv-carousel { position: relative; min-width: 0; isolation: isolate; }
.rv-carousel::before {
  --rv-slant: clamp(228px, 21.33vw, 280px);
  content: "";
  position: absolute;
  z-index: 0;
  top: calc(-1 * clamp(72px, 8vw, 116px));
  bottom: calc(-1 * clamp(72px, 8vw, 116px));
  left: 50px;
  right: 50px;
  background: var(--accent);
  clip-path: polygon(var(--rv-slant) 0, 100% 0, calc(100% - var(--rv-slant)) 100%, 0 100%);
}
.rv-lane + .rv-lane { margin-top: 22px; }
.rv-marquee {
  position: relative;
  margin: 0;
  padding: 0;
  overflow: hidden;
  mask-image: none;
  -webkit-mask-image: none;
}
.rv-row {
  position: relative;
  z-index: 1;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - 14px) / 2);
  gap: 14px;
  width: 100%;
  padding: 0;
  animation: none;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.rv-row::-webkit-scrollbar { display: none; }

.rv-card {
  width: auto;
  min-width: 0;
  height: 252px;
  padding: 18px 17px 15px;
  border-radius: 8px;
  scroll-snap-align: start;
}
.rv-card:hover { transform: translateY(-2px); }
.rv-card-link { min-width: 0; }
.rv-top { gap: 8px; }
.rv-stars { font-size: 15px; }
.rv-chip { padding: 5px 8px; font-size: 11px; }
.rv-quote {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  overflow: hidden;
  margin: 12px 0;
  font-size: 14px;
  line-height: 1.5;
}
.rv-foot { padding-top: 11px; }
.rv-controls {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr) 38px;
  align-items: center;
  gap: 12px;
}
.rv-controls[hidden] { display: none; }

/* When every card is already visible there is nothing to page through, so the
   arrows go and the track takes the full width. This replaces hiding
   .rv-controls itself, which is the element wrapping the track: doing that
   took every review off the page with it. */
.rv-lane.is-static .rv-arrow { display: none; }
.rv-lane.is-static .rv-controls { grid-template-columns: minmax(0, 1fr); }
.rv-arrow {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  color: #fff;
  background: transparent;
  border: 1px solid rgba(255,255,255,.7);
  cursor: pointer;
  transition: color .2s ease, background .2s ease, border-color .2s ease;
}
.rv-arrow:hover:not(:disabled) { color: var(--ink); background: #fff; border-color: #fff; }
.rv-arrow:disabled { opacity: .4; cursor: default; }
.rv-arrow svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.g-head-redesign {
  width: calc(100% + 56px);
  max-width: none;
  margin: 0 -28px;
  padding: 44px 28px 28px;
  text-align: center;
  background:
    linear-gradient(var(--accent), var(--accent)) left top / 30px 4px no-repeat,
    linear-gradient(var(--accent), var(--accent)) left top / 4px 30px no-repeat,
    linear-gradient(var(--accent), var(--accent)) right top / 30px 4px no-repeat,
    linear-gradient(var(--accent), var(--accent)) right top / 4px 30px no-repeat;
}
.g-meter { position: relative; padding-bottom: 28px; }
.g-meter::after {
  content: "";
  position: absolute;
  left: -28px;
  right: -28px;
  bottom: -10px;
  height: 28px;
  pointer-events: none;
  background:
    linear-gradient(var(--accent), var(--accent)) left bottom / 30px 4px no-repeat,
    linear-gradient(var(--accent), var(--accent)) left bottom / 4px 28px no-repeat,
    linear-gradient(var(--accent), var(--accent)) right bottom / 30px 4px no-repeat,
    linear-gradient(var(--accent), var(--accent)) right bottom / 4px 28px no-repeat;
}
.g-head-redesign h2 { position: relative; top: -16px; margin: 0; }
.g-head-redesign .g-services {
  position: relative;
  top: -16px;
  width: 100%;
  margin: 0;
  color: var(--ink);
  font-size: 40px;
  font-weight: 700;
  text-align: justify;
  text-align-last: justify;
  text-wrap: wrap;
}
/* Break sets. Each is display:none somewhere, and a hidden <br> joins the
   text nodes either side of it, so every one carries a space before it in the
   markup.

   .ah-break splits the About heading into its two lines below the split.
   .gs-m gives the services line its six rows there; the unclassed break in
   that line is the desktop row change and runs at every width. */
.ah-break,
.gs-m { display: none; }
.gs-under240,
.gs-under260 { display: none; }
@media (max-width: 899.98px) {
  .ah-break,
  .gs-m { display: inline; }
}

/* Centred at every width. The rule above sets justify, which only made sense
   while this was one long wrapping line; with explicit breaks every row would
   be stretched to the full width instead. Both properties have to go:
   text-align-last is what justify uses on the final row.

   nowrap so the rows are the ones in the markup and nothing wraps a second
   time inside them. Same specificity as the rule above, which outranks a bare
   .g-services. */
.g-head-redesign .g-services {
  text-align: center;
  text-align-last: center;
  text-wrap: nowrap;
}
@media (max-width: 899.98px) {
  /* Six rows on a phone, at the same 31px .rj-head uses so the two section
     openers match. The rows were set at about 21px and left a wide empty
     margin either side of every one of them. 31px puts the longest,
     "Driveway Extensions,", within a few pixels of the gutter. */
  .g-head-redesign .g-services {
    font-size: clamp(24px, 7.9vw, 31px);
    line-height: 1.25;
  }
}
.g-project-intro {
  margin-top: clamp(38px, 5vw, 64px);
}
.g-project-intro h3 { margin: 0; font-size: clamp(24px, 2.8vw, 34px); line-height: 1.2; }
.g-head-redesign .g-project-intro p { margin: 10px auto 0; color: var(--accent); font-weight: 600; }
.services .section-head h2 { position: relative; top: -13px; }
.services .section-head .section-lede { font-weight: 700; }
@media (max-width: 739.98px) {
  .services .section-head { position: relative; top: -13px; }
}

/* At tablet widths, keep the project service list to four deliberate rows. */
@media (min-width: 700px) and (max-width: 1100px) {
  .g-head-redesign .g-services br.gs-m { display: none; }
  .g-head-redesign .g-services br.gs-m:nth-of-type(2),
  .g-head-redesign .g-services br.gs-m:nth-of-type(5) { display: inline; }
  .g-head-redesign .g-services br:not(.gs-m) { display: inline; }
  .g-head-redesign .g-services {
    font-size: clamp(21px, 3.05vw, 34px);
    line-height: 1.25;
  }
}

@media (max-width: 739.98px) {
  /* Inset the straight-edged cards on phones and keep each image at its 4:5
     ratio so it scales down with the card width. */
  .services .pg-row {
    margin-inline: calc(-1 * var(--gutter) + 3px);
    margin-top: 32px;
    row-gap: 40px;
  }
  .pg-card {
    clip-path: none;
    position: relative;
    overflow: visible;
    width: 85%;
    justify-self: center;
  }
  .pg-text { padding-inline: 22px; gap: 4px; }
  .pg-sub { color: var(--ink); font-weight: 700; }
  .pg-card:first-child .pg-sub { line-height: 1.55; }
  .pg-sub-mobile-break { display: initial; }
  .pg-media {
    aspect-ratio: 4 / 5;
    height: auto;
  }

  /* The first service photo becomes a native horizontal swipe track only on
     phones. The original single picture remains in use at larger widths. */
  .pg-media > .pg-media-desktop { display: none; }
  .pg-driveway-gallery,
  .pg-patio-gallery,
  .pg-stamped-gallery {
    display: block;
    position: absolute;
    inset: 0;
    overflow: hidden;
  }
  .pg-driveway-track,
  .pg-patio-track,
  .pg-stamped-track {
    display: flex;
    width: 100%;
    height: 100%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .pg-driveway-track::-webkit-scrollbar,
  .pg-patio-track::-webkit-scrollbar,
  .pg-stamped-track::-webkit-scrollbar { display: none; }
  .pg-driveway-slide,
  .pg-patio-slide,
  .pg-stamped-slide {
    flex: 0 0 100%;
    width: 100%;
    height: 100%;
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }
  .pg-driveway-slide img,
  .pg-patio-slide img,
  .pg-stamped-slide img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  .pg-driveway-arrow,
  .pg-patio-arrow,
  .pg-stamped-arrow {
    position: absolute;
    top: 50%;
    z-index: 2;
    display: grid;
    place-items: center;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1px solid rgba(255,255,255,.55);
    border-radius: 50%;
    background: rgba(20,22,26,.34);
    color: #FFFFFF;
    opacity: .76;
    transform: translateY(-50%);
    -webkit-tap-highlight-color: transparent;
  }
  .pg-driveway-arrow:active,
  .pg-patio-arrow:active,
  .pg-stamped-arrow:active { opacity: 1; }
  .pg-driveway-arrow svg,
  .pg-patio-arrow svg,
  .pg-stamped-arrow svg { display: block; width: 17px; height: 17px; }
  .pg-driveway-prev,
  .pg-patio-prev,
  .pg-stamped-prev { left: 8px; }
  .pg-driveway-next,
  .pg-patio-next,
  .pg-stamped-next { right: 8px; }
  @media (prefers-reduced-motion: reduce) {
    .pg-driveway-track,
    .pg-patio-track,
    .pg-stamped-track { scroll-behavior: auto; }
  }
}

/* Stacked cards place blue service titles between the photo and subtitle. */
@media (max-width: 899.98px) {
  #services .pg-row { margin-top: 32px; row-gap: 40px; }
  #services .pg-card { position: relative; overflow: visible; }
  #services .pg-card .pg-text { gap: 4px; padding-top: 18px; }
  #services .pg-card .pg-title {
    position: static;
    margin: 0 0 8px;
    color: var(--accent);
    font-size: 23px;
    font-weight: 700;
    line-height: 1.2;
    text-align: center;
  }
}

@media (max-width: 899.98px) {
  .rv-layout { grid-template-columns: minmax(300px, .9fr) minmax(0, 1.6fr); gap: 28px; }
  .rv-head h2 { font-size: 46px; }
  .rv-row { grid-auto-columns: calc((100% - 14px) / 2); }
}
@media (max-width: 640px) {
  .g-head-redesign { width: calc(100% + 32px); margin: 0 -16px; padding: 32px 16px 16px; }
  .g-head-redesign .g-services { width: 100%; margin: 0; }
  .g-meter::after { left: -16px; right: -16px; }

  .rv-layout { grid-template-columns: 1fr; gap: 26px; }
  .rv-head, .rv-carousel { order: initial; }
  .rv-carousel::before {
    --rv-slant: 28px;
    top: calc(-1 * clamp(72px, 8vw, 116px) - 133px);
    left: 0;
    right: 0;
  }
  .rv-head { align-self: start; display: block; }
  .rv-head::before { display: none; }
  .rv-head h2 { position: relative; }
  .rv-head h2::before {
    content: "";
    position: absolute;
    left: 0;
    top: -10%;
    height: 120%;
    border-left: 2.4px solid var(--accent);
  }
  .rv-head h2 { max-width: none; font-size: clamp(36px, calc(7vw + 10px), 44px); }
  .rv-controls { grid-template-columns: 34px minmax(0, 1fr) 34px; gap: 8px; }
  .rv-row { grid-auto-columns: 100%; }
  .rv-card { height: 250px; }
}

/* Reviews below the split: heading over the cards and centred, no blue shape,
   two cards to a screen with arrows for paging.

   The parallelogram goes because it was sized for a wide two column layout
   and, stacked, it reads as a slab behind the cards rather than a shape.

   The arrows stay in a narrow column at each side, leaving two cards readable
   in the center track. */
@media (max-width: 899.98px) {
  .rv-layout {
    grid-template-columns: 1fr;
    gap: 20px;
  }
  .rv-carousel::before { display: none; }

  .rv-head {
    align-self: start;
    display: block;
    text-align: center;
    transform: none;
  }
  .rv-head::before { display: none; }
  .rv-head h2 {
    align-items: center;
    gap: 2px;
    padding-left: 0;
    font-size: clamp(30px, 8.6vw, 38px);
  }
  .rv-head h2::before { display: none; }

  .rv-arrow { display: grid; }
  .rv-controls { grid-template-columns: 34px minmax(0, 1fr) 34px; gap: 8px; }

  /* One scroll container, with exactly two cards filling its center track. */
  .rv-marquee { overflow: hidden; scroll-snap-type: none; }
  .rv-row { grid-auto-columns: calc((100% - 12px) / 2); gap: 12px; }
  .rv-card { height: auto; min-height: 230px; padding: 14px 13px 12px; }
  .rv-card .rv-quote { -webkit-line-clamp: 5; font-size: 13px; margin: 9px 0; }
  .rv-card .rv-top { gap: 6px; }
  .rv-card .rv-chip { padding: 3px 6px; font-size: 10px; }
  .rv-card .rv-stars { font-size: 13px; }
  .rv-card .rv-name { font-size: 13px; }
  .rv-card .rv-src { font-size: 11px; }
}

@media (max-width: 299.98px) {
  .rv-controls { grid-template-columns: 28px minmax(0, 1fr) 28px; gap: 5px; }
  .rv-arrow { width: 28px; height: 28px; }
  .rv-arrow svg { width: 16px; height: 16px; }
}

@media (max-width: 304.98px) {
  .why-grid { grid-template-columns: 1fr; }
}

/* .rj-actions belongs here too: its nowrap label plus the parallelogram's
   40px side padding held a 192px floor that pushed the whole page into
   horizontal scroll below about 212px. Same treatment as the other two
   button groups rather than a second narrow-width pattern. */
@media (max-width: 269.98px) {
  .cta-actions,
  .why-actions,
  .rj-actions {
    width: 100%;
    flex-direction: column;
    align-items: stretch;
  }
  .cta-actions .btn,
  .why-actions .btn,
  .rj-actions .btn {
    width: 100%;
    max-width: none;
    clip-path: none;
    font-size: 12px;
    line-height: 1.15;
    padding-inline: 8px;
    white-space: normal;
    overflow-wrap: anywhere;
  }
}

@media (max-width: 999.98px) and (min-width: 740px) {
  /* The secondary service cards should use the same straight-edged shape as
     the primary service cards in the tablet layout. */
  .ask-face { clip-path: none; padding-inline: 18px; }

  /* Leave the shell gutters in place when the tablet cards become rectangular
     so the outer cards do not touch the viewport edges. */
  .services .pg-row,
  .ask { margin-inline: 0; }
}

@media (max-width: 899.98px) {
  .about-grid {
    grid-template-columns: 1fr;
    align-items: start;
  }
}

@media (max-width: 449.98px) {
  .rv-top .rv-chip { display: none; }
}

@media (max-width: 384.98px) {
  .rv-row { grid-auto-columns: 100%; }
}

@media (max-width: 234.98px) {
  .reviews .rv-row {
    width: 100%;
    grid-auto-columns: calc(100% - 20px);
    gap: 10px;
  }
  .reviews .rv-card { min-height: 205px; padding: 10px; }
  .reviews .rv-card .rv-quote { -webkit-line-clamp: 4; font-size: 12px; }
}

@media (max-width: 259.98px) {
  .g-head-redesign .g-services br.gs-under260 { display: inline; }
}

@media (max-width: 239.98px) {
  .g-head-redesign .g-services br.gs-under240 { display: inline; }
}

.services-heading-compact { display: none; }
@media (max-width: 169.98px) {
  .services-heading-full { display: none; }
  .services-heading-compact { display: inline; }
}

@media (max-width: 159.98px) {
  .why-card:nth-child(-n+2) { display: none; }
}

@media (min-width: 900px) and (max-width: 999.98px) {
  /* Match the three primary service columns and their 8px gutters. */
  .ask-grid { grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .ask-row:nth-child(n) { transform: none; }
}

@media (min-width: 740px) and (max-width: 899.98px) {
  /* The primary cards stack at this width, so stack the secondary services
     on the same track with the same card-to-card spacing. */
  .ask-grid { grid-template-columns: 1fr; gap: 8px; }
  .ask-row:nth-child(n) { transform: none; }
}

/* Review cards share their width again once the tablet review layout stacks. */
@media (min-width: 900px) and (max-width: 999.98px) {
  .reviews .rv-top .rv-chip { display: none; }
}

/* Main service titles and their supporting copy keep the same colors on every
   card at every viewport size. */
#services .pg-title { color: var(--accent); }
#services .pg-sub{ color: var(--ink); }
