/* ==========================================================================
   Single Service
   Loaded by uq_service_assets() (inc/service.php) in TWO places: a single
   Service, and a Page whose shared page builder carries a `related_services`
   row (the last block in this file). Every selector here is scoped to a
   .uq-service-* or .uq-related-services class, so the Page case cannot be
   reached by anything but that block.
   ==========================================================================

   THIS FILE IS SMALL ON PURPOSE, AND THAT IS THE HEADLINE.

   The Single Service page is the Single Project page with a different header --
   the client's own words -- so almost all of it is drawn by rules that ALREADY
   EXIST in style.css, which is loaded site-wide:

     content + contact row   .uq-project-details   (grid, 380px aside, sticky
                             offset, long-form prose, every breakpoint)
     FAQ                     .uq-faq               (same component, sized into a
                             column by three CSS variables the module sets)
     Related Services        .uq-multi-services    (same card, same 3-col grid)
     Pricing                 .uq-pricing
     CTA Footer              .uq-footer-cta
     breadcrumbs             .uq-project-breadcrumbs

   Not one of those is duplicated here. What IS here is only the two things the
   brief actually asked to change or add:

     1. the Service Header's composition, re-proportioned to the Quo reference;
     2. the Trust Bar, which is a new module because nothing existing has its
        shape (see the note at the head of template-parts/service/trust-bar.php);
     3. two margin resets on the Related Services rail's WYSIWYG description,
        and nothing else. That module's composition, CARD and GRID are all
        .uq-multi-services in style.css -- not one of those values is restated
        here -- and a Flexible Page renders the very same module, so these two
        lines serve both.

   STYLE.CSS IS NOT EDITED. It is 397KB, loaded on every page, and the live site
   layers a Customizer CSS block over it -- so keeping the Service work in its
   own sheet is the strongest guarantee that Projects, Blog, Pages and Locations
   are byte-for-byte unchanged, and it makes the whole thing reversible by
   deleting one file.

   NO NEW COLOUR, NO NEW TYPE SCALE, NO NEW SPACING SYSTEM. Every value below is
   an existing theme token or a proportion measured off the client's reference.
*/

/* ==========================================
   Service Header -- the Quo composition
   Adapts .uq-service-gallery-hero, which already existed
   ==========================================
   THE MARKUP WAS NOT REBUILT. The three-image header the client asked us to
   reuse is template-parts/flexible-content/service-hero-gallery.php, and it
   already emits exactly the right pieces: one main figure and a __thumbnails
   box holding up to two more. Only the ARRANGEMENT changes, and it changes
   here.

   What style.css does today:            What the reference does:

     +----------------------------+        +---------+  +----------+
     |          main              |        |         |  |  thumb 1 |
     +----------------------------+        |  main   |  +----------+
     +-------------+ +------------+        |  tall   |  +----------+
     |   thumb 1   | |  thumb 2   |        |         |  |  thumb 2 |
     +-------------+ +------------+        +---------+  +----------+

   i.e. a wide landscape image with two below it, versus ONE TALL PORTRAIT image
   beside two stacked smaller ones. The second is the reference's, so the
   gallery becomes a two-column grid and the thumbnails box becomes two rows.

   ONLY COMPOSITION AND PROPORTION ARE TAKEN FROM THE REFERENCE -- the brief is
   explicit. No colour, typeface, button shape or brand mark from it is used;
   the type below resolves to the site's own --uq-site-font-* tokens and the
   brand palette, and the container is the site's 1200px. */

.uq-service-gallery-hero {
    /* The site's body face, via the token, instead of the hard-coded
       `var(--font-main, Inter, ...)` fallback chain in style.css. */
    font-family: var(--uq-site-font-body, Arial, sans-serif);
}

/* The reference splits the row close to evenly, with the copy holding a little
   less than half. style.css has .72fr / 1.28fr -- a narrow column of text
   beside a very wide image band -- which is the old landscape arrangement's
   proportion, not this one. */
.uq-service-gallery-hero__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr);
    align-items: center;
    gap: clamp(40px, 5vw, 96px);
}

/* Title and tagline width, which the client called out specifically. The
   reference sets its headline on three lines and its tagline a touch narrower;
   540 / 470 reproduces that at this type scale without inventing a new one. */
.uq-service-gallery-hero__content {
    max-width: 540px;
}

.uq-service-gallery-hero .uq-service-gallery-hero__title {
    max-width: 540px;
    /* THE SITE'S STANDARD HEADING BLUE, not this header's private black.
       style.css sets `color: #000` on .uq-service-gallery-hero__title, which was
       the reference site's treatment rather than Roofer On Demand's -- so the
       Service H1 was the only major page title on the site that was not brand
       blue. The exact same token the other three use:

           .uq-project-details__title   color: var(--uq-theme-primary, #104E8B)
           .uq-blog-header__title       --uq-blog-primary -> the same token
           .uq-hub__title               --uq-hub-primary  -> the same token

       Not a hex of its own, so a brand change in one place still reaches all
       four. (0,2,0) here beats style.css's (0,1,0), and this sheet loads after
       it -- no !important needed. */
    color: var(--uq-theme-primary, #104E8B);
    /* The site's heading face -- Roobert through the token, rather than the
       hard-coded "Roobert", Inter stack in style.css, so a font change in one
       place still reaches this header. */
    font-family: var(--uq-site-font-heading, Arial, sans-serif);
}

.uq-service-gallery-hero__description {
    max-width: 470px;
    /* The shared module description colour rather than this header's private
       #000000b3. */
    color: var(--uq-module-card-description-color, rgba(0, 0, 0, 0.7));
    font-size: var(--uq-module-description-size, 16px);
}

/* ---------- The button's third style ----------
   `button_type` offers Primary | Secondary | Normal. style.css already draws
   --primary (filled) and --secondary (white on a hairline); Normal is the third
   and it did not exist, because the old layout only had two buttons.

   NORMAL IS THE OUTLINED BUTTON, AND THE REFERENCE IS HERO CENTERED'S.
   --------------------------------------------------------------------
   The client pointed at the home page's Hero Centered pair -- a filled yellow
   "Book an assessment" beside a white, hairline-bordered "Call Us Now" -- and
   asked for Normal to be that second, outlined button.

   In the markup that outlined button is .uq-home-hero__button--secondary:
   template-parts/flexible-content/location-page-header.php emits only --primary
   and --secondary, it has no button_type field, and style.css declares no
   .uq-home-hero__button--normal at all. So "Hero Centered's Normal" is that
   module's secondary, and this is it.

   IT IS EXPRESSED THROUGH THIS MODULE'S OWN --uq-shg-secondary-* VARIABLES
   rather than by restating white / #e5e5e5 / black. Those three are set in
   template-parts/service/header.php from the same theme tokens Hero Centered's
   PHP defaults resolve to, so the two buttons cannot drift: change the token and
   both follow. The geometry needs nothing -- min-height, padding, border width,
   radius and type all come from .uq-service-gallery-hero__button, which was
   already Hero Centered's button declaration for declaration.

   The previous treatment was a bare text link -- no border, no box, brand blue
   with an underline on hover. It is gone, not overridden.

   NORMAL IS NOW INDEPENDENT OF SECONDARY (client item #8). It used to read the
   --uq-shg-secondary-* trio directly, which meant the two could never be told
   apart. It now reads its own --uq-shg-normal-* trio, which
   template-parts/service/header.php prints from three Theme Settings fields of
   its own. Their fallbacks are Secondary's current values, so the two still
   render identically until somebody sets them apart -- the behaviour described
   above is preserved, it is just no longer forced.

   THE SECOND ARGUMENT IS NOT DECORATION. `services_hero_gallery`
   (template-parts/flexible-content/service-hero-gallery.php) draws these same
   classes on a Page and sets --uq-shg-primary-* / --uq-shg-secondary-* from its
   own per-row fields -- but no --normal ones, because that layout only ever
   emits primary and secondary buttons. Chaining to the secondary variable means
   any markup that does not set the normal trio still paints exactly what it
   painted before, so that layout cannot regress even if it grows a Normal
   button later.

   PRIMARY AND SECONDARY ARE NOT TOUCHED. Only the --normal selectors changed. */
.uq-service-gallery-hero__button--normal,
.uq-service-gallery-hero__button--normal:hover {
    border-color: var(--uq-shg-normal-border, var(--uq-shg-secondary-border));
    background: var(--uq-shg-normal-bg, var(--uq-shg-secondary-bg));
    color: var(--uq-shg-normal-text, var(--uq-shg-secondary-text));
}

/* ---------- The gallery: one tall image beside two stacked ---------- */
.uq-service-gallery-hero__gallery {
    display: grid;
    /* Very slightly wider for the tall image, as the reference has it. */
    grid-template-columns: minmax(0, 1.04fr) minmax(0, 1fr);
    gap: 16px;
    /* stretch, so the thumbnails column resolves to the main image's height and
       the two columns end level. */
    align-items: stretch;
}

/* THE TALL ONE, and its proportion is measured rather than guessed.
 *
 * On the reference the main image is 264 x 451 -- an aspect ratio of 0.585, so
 * distinctly TALLER than a 3/4 portrait (0.75). 3/4 was the first pass and it
 * still read as a slightly-tall landscape rather than the narrow vertical panel
 * the reference uses, so this is 3/5 (0.6), which lands within a couple of
 * percent of the real thing.
 *
 * It also sets the row height the stacked column fills, so it drives the whole
 * composition: at 3/5 the two stacked images resolve to roughly 1.2:1 each,
 * which is what the reference has (267 x 205 and 267 x 223). At 3/4 they came
 * out at 1.5:1 -- visibly wider and flatter than the reference's. */
.uq-service-gallery-hero__image--main {
    aspect-ratio: 3 / 5;
    height: 100%;
}

/* Two rows now, not two columns. margin-top is cleared because the box no
   longer sits UNDER the main image. */
.uq-service-gallery-hero__thumbnails {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: repeat(2, minmax(0, 1fr));
    gap: 16px;
    margin-top: 0;
}

/* Two images in the row rather than three: one stacked card, full height, so
   there is no half-empty column. */
.uq-service-gallery-hero__thumbnails--single {
    grid-template-rows: minmax(0, 1fr);
}

/* The stacked images take their height from the grid row instead of a ratio of
   their own -- that is what keeps them level with the tall image at every width.
 *
 * position: relative + an absolutely positioned image is what makes that TRUE
 * rather than merely intended, and it is load-bearing for the portrait ratio
 * above.
 *
 * A grid row is as tall as its tallest item. With the image in normal flow, each
 * stacked figure contributed its own PHOTO'S natural height to that calculation,
 * so the row was sized by whatever the editor happened to upload -- and the main
 * image, which carries height: 100%, then stretched to match it. Measured: with
 * square source photos the main image rendered at 0.505 instead of the 0.6 it
 * asks for, i.e. the aspect-ratio was being overridden by the thumbnails.
 *
 * Taking the images out of flow leaves the stacked column with no intrinsic
 * height, so the row is sized by the main image alone and the composition is the
 * same on every Service whatever shape the three photos are. */
.uq-service-gallery-hero__image--thumbnail {
    position: relative;
    aspect-ratio: auto;
    height: 100%;
    min-height: 0;
}

.uq-service-gallery-hero__image--thumbnail img {
    position: absolute;
    top: 0;
    left: 0;
}

/* ONE IMAGE ONLY: no thumbnails box, so the two-column grid would leave a hole
   beside the image. The modifier is set in PHP rather than inferred with :has(),
   so it works in every browser and needs no @supports. */
.uq-service-gallery-hero__gallery--solo {
    grid-template-columns: minmax(0, 1fr);
}

.uq-service-gallery-hero__gallery--solo .uq-service-gallery-hero__image--main {
    /* Alone in the row it reads better landscape, which is also the proportion
       this header shipped with. */
    aspect-ratio: 16 / 9;
}

/* ---------- Responsive ----------
   The site's own breakpoints -- 991 / 767 / 479 -- so the header changes shape
   at the same widths every other page does. style.css stacks this header at
   860px, which is not one of them; 991 is where .uq-project-details stacks, and
   matching it is what keeps the two pages feeling like one site. */
@media screen and (max-width: 991px) {
    .uq-service-gallery-hero__inner {
        grid-template-columns: minmax(0, 1fr);
        gap: 40px;
    }

    .uq-service-gallery-hero__content,
    .uq-service-gallery-hero .uq-service-gallery-hero__title,
    .uq-service-gallery-hero__description {
        max-width: 672px;
    }

    .uq-service-gallery-hero__gallery {
        max-width: 736px;
        margin: 0 auto;
    }
}

@media screen and (max-width: 767px) {
    .uq-service-gallery-hero__gallery {
        gap: 12px;
    }

    .uq-service-gallery-hero__thumbnails {
        gap: 12px;
    }

    /* Below the stacking point the tall portrait becomes very tall indeed on a
       narrow screen, so it relaxes towards square. */
    .uq-service-gallery-hero__image--main {
        aspect-ratio: 4 / 4.4;
    }
}

@media screen and (max-width: 479px) {
    .uq-service-gallery-hero__image--main {
        aspect-ratio: 1 / 1;
    }
}

/* ==========================================
   Trust Bar
   Layout: service_trust_bar
   Rendered by template-parts/service/trust-bar.php
   ==========================================
   THE QUO COMPOSITION, built as a Service-page sibling of the Brands Logos
   module rather than as a component of its own.

   Reference: https://www.quo.com/solutions/home-services, the band directly
   under the hero. Measured on that page at desktop width rather than eyeballed,
   because the collapsed-viewport values are a different (smaller) step:

     ONE CENTRED LINE   [mark] 4.7 stars | 3,400+ reviews   <statement>
                        rating 16px/600, a hairline divider, reviews 16px/400 at
                        70% black, statement 16px/500. All three on the body
                        face -- Quo sets no display face anywhere in this band.

     A LOGO ROW BELOW   five greyscale logos about 32px tall, centred, roughly
                        30px under the line. IT IS STATIC. Quo's row runs no
                        animation, holds no duplicated set, and its two fade
                        masks compute to display:none. Ours is static for the
                        same reason: five logos fit, so there is nothing to
                        scroll and a moving strip directly under the H1 would
                        pull the eye off the header.

   WHAT WAS HERE BEFORE. A four-column strip of icon + title + subtext proof
   points ("Licensed & Insured", "25-Year Warranty"...) separated by vertical
   rules. That was built against a misreading of which section the client meant
   and is retired whole: the icon grid, its column-count bookkeeping
   (--cols-N and the :nth-child divider rules), the PNG mask tinting, and the
   .uq-service-trust__label type rule that briefly moved to the heading face all
   go with it. Nothing from that pass survives in this file.

   BRANDING IS OURS, COMPOSITION IS QUO'S. Every value below is an existing
   theme token: --uq-theme-border for the hairlines, --uq-theme-text for the
   muted line, --uq-theme-border for the hairlines,
   --uq-site-font-body for all of it, and the shared 1200px container with 5vw
   gutters. No new colour, no new face, no new type step.

   THE LOGO ROW REUSES BRANDS LOGOS RATHER THAN RESTATING IT. The markup carries
   that module's own .uq-logo-marquee__group / __item / __link / __logo classes,
   so the logo sizing, the object-fit contain, the greyscale-plus-opacity
   treatment, the hover restore and the focus ring are ITS rules, applied here
   unchanged. style.css is not touched. What this file does is (a) declare that
   module's three sizing tokens at a Service-page scale, which is all the tokens
   are for, and (b) undo the two declarations that only make sense on a moving
   track. That is the whole coupling. */
.uq-service-trust {
    --uq-stb-border: var(--uq-theme-border, #e5e5e5);
    --uq-stb-rule: #e8ebef;
    --uq-stb-label: #111111;
    --uq-stb-muted: var(--uq-theme-text, #3F4B58);
    /* The site's own yellow, the same token the accent uses everywhere else. */
    /* The uploaded mark's height. Quo's badge measures 19x20 on the line. */
    --uq-stb-mark-size: 20px;
    /* MEASURED OFF THE REFERENCE, not chosen. Quo's band runs 23px from the
       hairline to the top of the line's ink, 28px from that ink to the top of
       the logo ink, and 22px from the logo ink to the band's end -- 121px total.
       These three values are those gaps MINUS this module's own leading (about
       6px above the line's ink and 4px below its baseline), which is what lands
       the RENDERED gaps on Quo's numbers rather than 10px past them. Set the gap
       you want to SEE; the leading adds itself. */
    --uq-stb-row-gap: 25px;
    /* CLIENT CHANGE: 21px -> 12px. "Less space between tabs and border line,
       similar to other cards such as warranty cards." 12px sits just above the
       10px inner inset the Warranty cards use between their own border and
       their content (.uq-filterable-cards__visual's 10px margin), which is the
       card language being pointed at; the band keeps 2px more than a card
       because its rules are hairlines on a white ground rather than the edge of
       a filled surface, and at 10px the line starts to touch them.

       Desktop band height goes 68px -> 50px (1 + 12 + 24 + 12 + 1).

       THE DEFAULT IS ALSO IN PHP. trust-bar.php writes --uq-stb-space-top /
       -bottom INLINE on every render, from spacing_top / spacing_bottom, so
       this declaration is only the fallback for markup without that style
       attribute. The two defaults must be changed together or the inline 21px
       simply wins -- which is why the PHP default moved to 12 in the same pass.
       A row where an editor typed an explicit spacing still keeps it. */
    --uq-stb-space-top: 12px;
    --uq-stb-space-bottom: 12px;

    width: 100%;
    /* The site's 5vw gutters, the same as every other module. */
    padding: 0 5vw;
    background: #ffffff;
    font-family: var(--uq-site-font-body, Arial, sans-serif);
}

.uq-service-trust,
.uq-service-trust *,
.uq-service-trust *::before,
.uq-service-trust *::after {
    box-sizing: border-box;
}

/* The site's 1200px container. It carries the vertical padding and holds the
   trust line and the logos on the site's own measure -- the hairlines do NOT
   live here, see below. */
.uq-service-trust__container {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: var(--uq-stb-space-top) 0 var(--uq-stb-space-bottom);
}

/* CONTAINED HAIRLINES -- the rules stop where the content stops.

   CLIENT CHANGE, and this is the "border styling" half of the item. The colour
   and the weight were already the card language: this hairline is
   1px solid var(--uq-theme-border) and a Warranty card's filter tab is
   1px solid var(--uq-fc-border), which resolves to the SAME --uq-theme-border
   token (#e5e5e5). Nothing about the paint needed touching.

   What differed was the MEASURE. The rules used to run edge to edge while every
   card on the site -- Warranty cards included -- draws its border on the 1200px
   content measure, so the bar read as a full-width divider rather than as a
   component in the same family. Moving the border from the <section> to
   .uq-service-trust__container lands it on exactly that measure: the container
   is `width:100%; max-width:1200px; margin:0 auto`, so the line now starts and
   stops with the text above and below it.

   WHY THE SELECTOR IS `--border-top > __container` AND NOT JUST `__container`.
   The two toggles are ACF-driven modifiers on the SECTION (show_border_top /
   show_border_bottom), and the container is the element that has to carry the
   paint, so the rule has to reach from one to the other. The child combinator
   keeps it to the module's own container and not to anything nested.

   This also means the border and the vertical padding now sit on the SAME
   element, so the 12px above is measured from the rule to the content with no
   box in between -- which is what makes the gap actually read as 12px.

   Nothing else moves: no negative margins, no 100vw trick, no horizontal
   scrollbar, and the section keeps its 5vw gutters and white ground.

   (What this replaces: the rules previously sat on the SECTION precisely
   BECAUSE its 5vw gutters are padding and a border draws outside the padding
   box, which reached the viewport edge for free. That was deliberate -- it
   mirrored the Quo reference band this module was built from -- and it is what
   the client has now asked to change.)

   TOP AND BOTTOM ARE SEPARATE RULES on separate modifiers, driven by
   `show_border_top` and `show_border_bottom`. The single --bordered modifier
   that drew both is gone, along with the `show_border` field behind it: two
   stacked bands would otherwise double the hairline between them, and the
   client wanted each edge switchable on its own. */
.uq-service-trust--border-top > .uq-service-trust__container {
    border-top: 1px solid var(--uq-stb-border);
}

.uq-service-trust--border-bottom > .uq-service-trust__container {
    border-bottom: 1px solid var(--uq-stb-border);
}

/* ---------- The trust line ----------
   TWO flex children, not four. The rating, the divider and the reviews count
   are wrapped in one nowrap group so that when the line is too narrow the
   STATEMENT drops to its own line and the proof group stays intact. Four loose
   children would let the divider wrap to the start of a line on its own, which
   reads as a stray mark. */
.uq-service-trust__bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    /* Quo's line runs 7px from the rating group to the review count and 9px on
       to the statement. The column gap is that second step; the proof group
       below owns the first. */
    gap: 6px 9px;
    margin: 0;
    text-align: center;
}

.uq-service-trust__proof {
    display: inline-flex;
    flex: none;
    align-items: center;
    /* Measured on Quo: mark to score 5px, score to divider 6px, divider to the
       review count 11px. 7px is the one value that sits inside all three. */
    gap: 7px;
    white-space: nowrap;
}

/* ---------- The rating mark ----------
   ONLY what was uploaded. There is no drawn-star fallback and no substitute
   glyph: an empty `rating_icon` renders no element at all and the rating is its
   number alone. The previous pass drew a five-star row here; the client asked
   for it gone.

   Sized to Quo's badge, which measures 19x20 on the line -- a square mark lands
   on 20x20, a wide one scales down inside that cap. */
.uq-service-trust__mark {
    display: block;
    width: auto;
    max-width: 96px;
    height: var(--uq-stb-mark-size);
    flex: none;
    object-fit: contain;
}

.uq-service-trust__score {
    color: var(--uq-stb-label);
    font-size: 16px;
    font-weight: 600;
    line-height: 1.5;
}

/* The divider. A 1px rule rather than a pipe character, so it cannot pick up the
   font's own weight or sit off-centre on the line box. */
.uq-service-trust__sep {
    display: block;
    width: 1px;
    height: 14px;
    flex: none;
    background: var(--uq-stb-rule);
}

.uq-service-trust__reviews {
    color: var(--uq-stb-muted);
    font-size: 16px;
    font-weight: 400;
    line-height: 1.5;
}

/* The reviews count as a link. The theme underlines links inside a lot of
   contexts; this one is a quiet proof point, so the underline only appears on
   hover and focus. */
a.uq-service-trust__reviews {
    color: var(--uq-stb-muted);
    text-decoration: none;
    transition: color 0.2s ease;
}

a.uq-service-trust__reviews:hover,
a.uq-service-trust__reviews:focus-visible {
    color: var(--uq-stb-label);
    text-decoration: underline;
}

/* The statement -- the row's `heading` field, and the only title in this bar.
   HEADING FACE, on client instruction ("Sticky bar title font needs to be
   changed"). It now takes --uq-site-font-heading, the token every other title on
   this site resolves to, so the trust statement reads as a title in the same
   voice as a module heading rather than as a heavier line of body copy.

   THE FAMILY IS NOT DECLARED HERE, AND IT CANNOT BE. This element is a <p>, and
   style.css carries a global
       body, p, a, li, label, input, ... { font-family: var(--uq-site-font-body)
       !important }
   so no plain declaration in this file can set its face -- not at any
   specificity, not at any load order. The override lives in style.css beside
   .uq-footer-cta__card-title and .uq-multi-services__tab, the two elements that
   already needed the identical exception. Look for
   `.uq-service-trust__statement` there.

   ONLY THE FAMILY MOVES. The weight was ALREADY the site's standard title
   weight: 500 is what the shared .uq-heading-* scale, --uq-module-card-title-
   weight and every module title use, and it is the exact weight
   "UQ Site Roobert" ships as a real cut (Roobert-Medium.woff2; the face's other
   @font-face covers 600-900). So 500 renders as true Roobert Medium with no
   synthesis, and the size, colour, line-height, margins and the 16px step are
   deliberately untouched -- the bar's height, wrapping behaviour and spacing are
   unchanged.

   WHY THE PROOF GROUP STAYS ON THE BODY FACE. .uq-service-trust__score (600) and
   __reviews (400) are data, not a title, and the client asked about the title.
   The weights matter too: "UQ Site Roobert" starts at 500, so the 400 review
   count has no real cut and would be synthesised. They keep inheriting
   --uq-site-font-body from the section, which is left exactly as it was.

   (What this replaces: the body face at 16/500, chosen to mirror the Brands
   Logos trust line .uq-logo-marquee__title, 15px/500, which states no family of
   its own and inherits the body face from its section. That was a deliberate
   "same voice one step up" decision and it is what the client has asked to
   change -- so the precedent now diverges on the Service page only.) */
.uq-service-trust__statement {
    margin: 0;
    padding: 0;
    color: var(--uq-stb-label);
    font-size: 16px;
    font-weight: 500;
    line-height: 1.5;
}

/* ---------- The logo row ----------
   Brands Logos' own tokens, declared here at a Service-page scale.

   32px AND A 6px GAP, BOTH REVERSE-ENGINEERED FROM THE REFERENCE. Quo's logo
   row looks like it is spaced 38px apart -- that is what the ink measures -- but
   its CSS column-gap is literally ZERO. The whole rhythm comes from transparent
   padding baked into the logo files. Solving it back:

       asset            file       box w at 32px    ink w on Quo
       CURRENT HOME     300x50         192              154      (19px pad/side)
       Pink's           291x96          97               59
       1-800-GOT-JUNK   300x65         148              110
       maidpro          300x72         133               95
       Mosquito Joe     212x96          71               30      (20px pad/side)
                                       ---              ---
                                       641              601

   641px of boxes butted together, minus the outer padding of the first and last
   marks, is 601px -- exactly the row width measured on the page. So the box
   height is 32px and the gap is 0, and the client is uploading those same files.

   THAT MODEL IS REPLACED BELOW, AND THIS IS WHY.
   ----------------------------------------------
   The measurements above hold only while every uploaded file is cropped the same
   way. The global rule sizes a logo as `height: <fixed>; width: auto`, so the
   rendered WIDTH is whatever the file's own aspect ratio makes it -- the art is
   never measured, only the canvas. Feed that a set of files with different
   shapes and the row falls apart:

       a WIDE file (10:1)   320px at 32px tall, then clipped by max-width to
                            220px -> 22px tall. Short.
       a TALL file (1:2)     16px wide. Extremely small, and the reported bug.
       a SQUARE file          32px wide. Also very small.
       a PADDED canvas       the art is a fraction of the box: measured across
                             the five live logos the ink came back at a median of
                             11.9px tall inside a 32px box, and 242px of ink
                             across a 320px row.

   THE NEW MODEL: A FIXED SLOT, AND A CAP ON THE ART INSIDE IT.
   Every logo is drawn into a box of one width and one height -- --uq-stb-logo-slot
   by --uq-stb-logo-cap -- and the image is told `max-width: 100%;
   max-height: <cap>; width: auto; height: auto`. Because only MAXIMA are set and
   both axes stay auto, the browser scales the file down to fit and stops:

     - the aspect ratio is preserved on every shape, so nothing is distorted;
     - nothing is ever cropped -- a max is a limit, not a window;
     - a tall or square logo now fills the CAP instead of collapsing to a sliver;
     - a wide logo fills the SLOT, as it should;
     - every slot is the same size, so the row reads as one rhythm whatever the
       files are.

   object-fit: contain is kept as well. With both axes auto it is belt-and-braces
   rather than the active constraint, and it is what keeps the fit correct if a
   future rule ever pins both dimensions.

   THE GAP GOES FROM 0 TO 8px. At 0 the spacing WAS the files' transparent
   padding, which is exactly the assumption this change removes: a tight-cropped
   logo that fills its slot would otherwise sit hard against its neighbour. 8px
   is a floor, not the visible gap -- a slot wider than its art still contributes
   its own empty space on top.

   THE SLOT IS 160 WIDE; THE CAP IS 60 AT THE CLIENT'S REQUEST. The cap was 40
   when this model was first tuned -- that value evened the row out, because the
   slot's ratio decides which shapes are width-limited and which are
   height-limited. Modelled against the five shapes on the reference row (6.0,
   4.6, 4.2, 3.0 and 2.2 : 1):

       slot     heights                    spread   row of 5
       160x40   27, 35, 38, 40, 40           13px      832px
       160x60   27, 35, 38, 53, 60           33px      832px   <- this

   So raising the cap alone makes the row LESS uniform, not more: a wide wordmark
   is pinned by the 160px slot and cannot grow, while a squarer mark climbs all
   the way to the cap. The client chose this size directly in DevTools and asked
   for it, so it is what is set -- the trade-off is recorded here rather than
   quietly re-tuned around.

   EVENING IT OUT AGAIN WOULD MEAN A WIDER SLOT, and that is the thing to reach
   for if the row ever looks lopsided: the ratio that produced the 13px spread is
   4:1, so a 60px cap wants a 240px slot -- but 5 x 240 + 4 x 8 = 1232px, which
   overflows the 1200px container and wraps. 190x60 is the compromise (spread
   28px, row 982px, still five per line). Neither is applied; both are one number
   away.

   Row width is unchanged by the cap: 5 x 160 + 4 x 8 = 832px inside a 1200px
   container, seven slots before it wraps. .uq-service-trust__logos-row already
   centres and wraps, so an eighth logo simply starts a second line on the
   existing 16px row-gap.

   The RESPONSIVE ladder is scaled with it, 40/36/32/26 -> 60/54/48/39, so the
   step-down keeps the same proportion at every breakpoint.

   Everything else about a logo -- the grayscale(1), the hover restore, the focus
   ring -- is the Brands Logos module's rule, untouched, reached simply by using
   its class names. The hover changes a filter only, so it can never reflow the
   row. */
.uq-service-trust__logos {
    /* The fixed container, and the cap on the art inside it. Two numbers per
       breakpoint and nothing else to keep in step. */
    --uq-stb-logo-slot: 160px;
    --uq-stb-logo-cap: 60px;

    --uq-logo-marquee-gap: 8px;

    margin-top: var(--uq-stb-row-gap);
}

/* THE FIXED CONTAINER. .uq-logo-marquee__item is already
   `display: flex; flex: none; align-items: center; justify-content: center` in
   style.css, so it is already a centring box and already refuses to shrink --
   all it needed was a size. That is what keeps every logo both vertically and
   horizontally centred in an identical slot.

   --uq-logo-marquee-logo-height and --uq-logo-marquee-logo-max-width are no
   longer declared above: they fed the global rule's `height` / `max-width`,
   which the rule below replaces outright, so leaving them set would have been
   two dead numbers reading as live configuration. */
.uq-service-trust__logos .uq-logo-marquee__item {
    width: var(--uq-stb-logo-slot);
    height: var(--uq-stb-logo-cap);
}

/* The link is optional in the markup -- a logo row without a Link field puts the
   <img> straight into the item -- so it is stretched to the slot rather than
   relied upon. When it is absent the item centres the image itself. */
.uq-service-trust__logos .uq-logo-marquee__link {
    width: 100%;
    height: 100%;
}

/* THE ART. Maxima only, both axes auto: scaled down to fit, never up, never
   distorted, never cropped. */
.uq-service-trust__logos .uq-logo-marquee__logo {
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: var(--uq-stb-logo-cap);
    object-fit: contain;
}

/* THE LOGOS' WEIGHT, matched to the reference by measurement. The global module
   draws every logo at grayscale(1) and opacity 0.68, which suits a standalone
   band of full-colour brand art. These files are ALREADY grey, so 0.68 on top
   washes them out: sampled across the rendered row, our ink came back at a
   median of 185 against Quo's 156, and our darkest pixel at 141 against their
   87. Solving 255 - a(255 - src) for their 87 gives a = 1.0 -- Quo runs these
   same files at full opacity with no filter at all, which the computed style on
   their page confirms.

   So opacity goes to 1 here. grayscale(1) STAYS: it costs nothing on grey art
   and keeps a future full-colour logo in the same register as the rest. Hover
   then has no opacity left to restore, so it lifts the greyscale instead --
   still subtle, and a filter cannot reflow anything. */
.uq-service-trust__logos .uq-logo-marquee__logo {
    opacity: 1;
}

.uq-service-trust__logos .uq-logo-marquee__link:hover .uq-logo-marquee__logo {
    filter: grayscale(0);
    opacity: 1;
}

/* .uq-logo-marquee__group is built for a moving track: it never wraps, and it
   carries a trailing padding-right that hides the seam where the duplicated set
   begins. Both are wrong for a static centred row -- the padding would push the
   row off centre by half the gap -- so both are undone here, and only here. */
.uq-service-trust__logos-row {
    flex-wrap: wrap;
    justify-content: center;
    padding-right: 0;
    /* Quo's own row-gap for the wrapped case. */
    row-gap: 16px;
}

/* ---------- Responsive ----------
   The site's own breakpoints. The line wraps before anything shrinks: the proof
   group and the statement simply stack, which is what Quo's own narrow layout
   does. Only the logos step down. */
@media screen and (max-width: 991px) {
    .uq-service-trust {
        --uq-stb-row-gap: 16px;
    }

    .uq-service-trust__logos {
        --uq-stb-logo-slot: 132px;
        --uq-stb-logo-cap: 54px;
    }
}

@media screen and (max-width: 767px) {
    .uq-service-trust__logos {
        --uq-stb-logo-slot: 112px;
        --uq-stb-logo-cap: 48px;
    }

    .uq-service-trust__logos-row {
        row-gap: 12px;
    }
}

@media screen and (max-width: 479px) {
    .uq-service-trust {
        --uq-stb-mark-size: 18px;
        --uq-stb-row-gap: 20px;
    }

    .uq-service-trust__score,
    .uq-service-trust__reviews,
    .uq-service-trust__statement {
        font-size: 15px;
    }

    .uq-service-trust__logos {
        /* 78, not 80: the section is `padding: 0 5vw`, so at 479px the row has
           431px to work with and 5 slots of 80 plus four 8px gaps is 432 -- one
           pixel over, which would wrap a lone fifth logo onto its own line right
           at the breakpoint. 5 x 78 + 4 x 8 = 422 fits. Narrower than that the
           row wraps and centres on the existing row-gap, which is the intended
           phone behaviour. */
        --uq-stb-logo-slot: 78px;
        --uq-stb-logo-cap: 39px;
    }
}

/* ==========================================
   Service Details -- the sticky contact sidebar
   ==========================================
   The section already renders .uq-project-details--sticky when the row's
   `sticky_sidebar` toggle is on, and style.css already answers that with

       @media (min-width: 992px) {
         .uq-project-details--sticky .uq-project-details__aside-inner {
           position: sticky; top: var(--uq-pd-sticky-top);
         }
       }

   ...which computed correctly and did absolutely nothing. `position: sticky`
   only moves inside its CONTAINING BLOCK -- here .uq-project-details__aside, the
   grid item it sits in -- and .uq-project-details__layout carries
   `align-items: start`, which sizes every grid item to its OWN content rather
   than to the row. Measured on the live markup:

       .uq-project-details__aside        1331px
       .uq-project-details__aside-inner  1331px   <- identical to its parent
       travel                               0px

   The sticky element exactly filled its containing block, so there was no
   distance to stick over and the sidebar simply scrolled away with the page.
   Nothing else was wrong: no transform, filter, contain or non-visible overflow
   anywhere in the ancestor chain.

   align-self: stretch puts the aside track back to the row's full height -- the
   article column's height -- which is what creates the travel. Set on the ASIDE
   only, so `align-items: start` still governs the rest of the grid and the
   content column is untouched.

   THIS IS THE FIX css/blog.css ALREADY USES for .uq-blog-main--sticky, applied
   here rather than invented. It is scoped to .uq-service-details, so the
   Project page is deliberately NOT changed: Project Details carries the same
   latent issue, but fixing it there would alter every Project with the toggle
   on, which is not what was asked for. Worth raising separately.

   Scoped to the --sticky modifier and to >=992px, so a row with the toggle off,
   and every width below the stacking breakpoint, keep a plain static column.
   No position: fixed anywhere. */
@media screen and (min-width: 992px) {
    .uq-service-details.uq-project-details--sticky .uq-project-details__aside {
        align-self: stretch;
    }

    /* NO SCROLL VALVE. An earlier pass capped this column to the viewport height
       and let it scroll internally, so a tall contact card could not hang its
       own submit button below the fold. The client's call is that the internal
       scrollbar is worse than the thing it prevented -- a second scrollbar
       inside the page reads as a broken frame -- so the card is its natural
       height and the page scrolls normally.

       What that means in practice: on a viewport shorter than the card, the
       card sticks at top:148 and its lower part stays below the fold until the
       reader scrolls past the whole article. That is the accepted trade.

       position and top are style.css's; this block now adds only the
       align-self: stretch above, which is what gives sticky its travel. */
}

/* ==========================================
   Related Services
   Layout: related_services
   ==========================================
   THE SERVICE CARDS MODULE, NOT A COPY OF IT -- AND NOW NOT A VARIANT OF IT
   EITHER.

   The module renders .uq-multi-services, the Service Cards component, and BOTH
   the card AND the section composition are left entirely to style.css. Every
   value that makes a Service Cards section look the way it does is inherited,
   not restated:

       composition      .uq-multi-services__layout -- a two-column grid,
                        minmax(224px, 264px) rail | minmax(0, 1fr) cards,
                        gap clamp(35px, 3vw, 51px), align-items: start
       rail (LEFT)      title  max-width 240px, margin 0 0 32px, 400 / 0.98 /
                        -0.045em in the heading font
                        intro  max-width 264px, margin -12px 0 28px,
                        15 / 1.45 on #000000b3
       cards (RIGHT)    the grid, in .uq-multi-services__body
       card             1px solid rgba(0, 0, 0, 0.13) on #ffffff, radius 10px
                        (var(--uq-ms-card-radius)), padding 24px,
                        min-height 170px
       grid             repeat(3, minmax(0, 1fr)), gap 16px
       card title       18 / 500 / 1.35 / -0.015em  (--uq-module-card-title-*)
       card description 14 / 400 / 1.5 on --uq-module-card-description-color
       arrow link       24px square, #f7f5f2, inverting to black on hover
       band spacing     --uq-ms-space-top / --uq-ms-space-bottom, 5vw sides,
                        1200px container, capped at each breakpoint
       responsive       cards 3 up / 2 up at 991 / 1 up at 767; the layout
                        collapses to one column with a 32px gap below 992, so
                        title and description come first and the cards follow

   NONE OF THOSE IS RE-DECLARED BELOW, and that is the point: restyling Service
   Cards restyles this module with it.

   THE CLIENT'S FINAL CALL -- "title and description on the left", "just like
   service cards" -- IS THE UNMODIFIED COMPONENT, so this block declares NO
   layout whatsoever. The section paints in DOM order at every width: rail left,
   cards right above 992px, stacked below it.

   TWO EARLIER PASSES ARE GONE, and neither leaves a residue:

     1. The Related Articles card language -- tinted #f5f8fc panel, square
        corners, 20/600 title, 15/1.55 three-line summary, whole-card click --
        which made the two card grids drift apart the moment either was touched.

     2. THE MIRROR. A min-width 992px block that flipped the composition to
        `grid-template-columns: minmax(0, 1fr) minmax(224px, 264px)` and set
        `order: 1` on .uq-multi-services__body and `order: 2` on
        .uq-multi-services__sidebar -- cards on the left, title and description
        on the right. That answered an earlier reading of the brief; the client
        has since confirmed the opposite, so it is deleted rather than
        overridden. Deleting it is what restores the composition, because the
        base rule it was fighting is the one the client asked for.

   Removing the `order` pair matters beyond this breakpoint: with no order set,
   nothing has to be unwound when the layout goes single-column, so the stacked
   state is Service Cards' stacked state exactly.

   WHAT IS LEFT HERE IS SPACING PARITY FOR THE WYSIWYG DESCRIPTION, AND NOTHING
   ELSE. */

/* The section description is the one real difference in KIND between the two
   modules: Service Cards' is a single <p class="uq-multi-services__intro">, so
   its margin is the class's, while this one is a WYSIWYG <div> whose <p>
   children carry the global `p { margin: 0 0 20px }`. Without these two the
   rail's copy would sit 20px lower than Service Cards' and the gap to the cards
   would be 20px deeper. Type, colour and width are untouched -- they come from
   .uq-multi-services__intro. */
.uq-related-services .uq-multi-services__intro > :first-child { margin-top: 0; }
.uq-related-services .uq-multi-services__intro > :last-child { margin-bottom: 0; }

/* The Flexible Page's Related Services rows render THIS module, through
   template-parts/service/related-services.php -- see the map in
   template-parts/flexible-content/render.php. So the two margin resets above
   are the whole of the CSS for both, and the composition on a Page is the
   composition here, to the value.

   A .uq-related-services--stacked block used to sit at this point: a full-width
   header with the title and description above the cards, for the Page version
   when that was a separate partial. The client asked for one design, the rail,
   so the block is deleted rather than left to be matched by nothing. Reinstating
   it would mean that partial back plus these rules; neither is referenced now. */

/* ---------- The Theme Settings card colours are NOT declared here any more ----
   A `.uq-related-services .uq-multi-services__card` rule used to sit at this
   point, reading --uq-services-card-bg / --uq-services-card-border. It was
   scoped under .uq-related-services on purpose, back when the brief was the
   Related Services card specifically -- which meant the `service_cards` and
   `service_categories` rows on ordinary Pages, drawing the very same card, could
   not be reached by those settings at all.

   The brief is now the opposite: ONE set of Theme Settings controls painting all
   three Service card modules. So the variables moved onto the shared component
   rule itself, `.uq-multi-services__card` in style.css, together with the arrow
   pair on `.uq-multi-services__card-link`. This scoped override would now only
   re-declare the same two properties with the same two values one level deeper,
   so it is deleted rather than left as a second place to maintain.

   Nothing about Related Services' appearance changes: it reads the identical
   variables with the identical fallbacks, one rule further up. */

/* ==========================================
   Service Header -- the button pair
   ==========================================
   THE BUTTON ITSELF IS NOT TOUCHED. Measured against Hero Centered
   (.uq-home-hero__button, template-parts/flexible-content/location-page-header.php)
   the two are already the same object, declaration for declaration:

       inline-flex, min-height 42px, padding 10px 24px, 1px solid border,
       font-size var(--uq-button-font-size, 16px),
       font-weight var(--uq-button-font-weight, 500), line-height 1.2,
       hover translateY(-1px) + opacity 0.88

   So "match the Hero Centered button styling" needs no new button rule, and
   .uq-service-gallery-hero__button keeps its own --uq-shg-* brand blue / white
   pair rather than borrowing Hero Centered's editor-driven --uq-lph-* colours.
   Swapping the classes would have repainted the existing first button.

   WHAT ACTUALLY DIFFERED WAS THE ROW, and it is three values:

                            Hero Centered      Service Header (was)
       gap                  16px               14px
       align-items          center             (unset -> stretch)
       :focus-visible       2px / offset 3px   none

   All three are corrected below. The gap and align-items are invisible until a
   SECOND button exists -- a one-button row has no gap, and a lone flex item
   stretched to its own row height is its own height -- so a Service that has not
   filled in the second button renders exactly what it rendered before.

   The responsive behaviour needed nothing: style.css already takes this row to
   flex-direction: column with 100%-wide buttons at 479px, which is what Hero
   Centered does at the same breakpoint. Only the 767px gap step and the 479px
   stretch are added, so the two rows now narrow and stack identically.

   Scoped to .uq-service-header, the class this module's <section> carries and
   the old page-builder `services_hero_gallery` layout does not -- so a Page
   still using that layout is untouched even where this sheet happens to load. */
.uq-service-header .uq-service-gallery-hero__actions {
    align-items: center;
    gap: 16px;
}

/* The fourth and last difference, and the only one on the button itself:
   Hero Centered declares text-align: center, this button declared nothing and
   inherited `start`. It changes NOTHING for a single-line label -- the button is
   a flex container with justify-content: center, so the label is already centred
   -- and it only shows on a label long enough to wrap to two lines, which is
   exactly where the two would otherwise have diverged. */
.uq-service-header .uq-service-gallery-hero__button {
    text-align: center;
}

.uq-service-header .uq-service-gallery-hero__button:focus-visible {
    outline: 2px solid var(--uq-theme-primary, #104E8B);
    outline-offset: 3px;
}

@media screen and (max-width: 767px) {
    .uq-service-header .uq-service-gallery-hero__actions {
        gap: 12px;
    }
}

@media screen and (max-width: 479px) {
    /* style.css turns the row into a column here and gives every button
       width: 100%. align-items: stretch is Hero Centered's own value for the
       stacked state, and it stops the centre alignment above from applying to a
       column. */
    .uq-service-header .uq-service-gallery-hero__actions {
        align-items: stretch;
    }
}

/* ==========================================
   Service Header -- Photo Layout: stacked
   photo_layout = "stacked"
   ==========================================
   The client's reference is quo.com/solutions/law-firms: two small visuals
   across the top, one wide image beneath them.

       +----------+ +----------+
       |  image 2 | |  image 3 |
       +----------+ +----------+
       +-----------------------+
       |    image 1  (wide)    |
       +-----------------------+

   SAME MARKUP, SAME THREE IMAGES, SAME ORDER IN THE DOM. The partial still
   emits the main <figure> first and the __thumbnails box second; `order` below
   puts the pair on top. Nothing here is a second gallery -- it is the existing
   one re-laid-out, which is why the module needed no new ACF image field.

   EVERY RULE IS UNDER .uq-service-gallery-hero--photos-stacked, a class the
   partial adds ONLY for the stacked choice. The `side` default therefore emits
   no extra class, matches none of this, and renders exactly as it did before the
   field existed.

   PROPORTIONS ARE MEASURED OFF THE REFERENCE, not guessed. Its two top cards
   render 265 x 215 (1.23:1) and its bottom image 556 x 240 (2.32:1), on a 16px
   grid. 5/4 (1.25) and 7/3 (2.33) reproduce that to within a couple of percent,
   and in this module's 736px gallery column they resolve to 360 x 288 each on
   top and 736 x 315 beneath -- the same composition at this page's scale.

   NO DISTORTION, NO OVERFLOW: the <img> keeps the module's own
   `width/height: 100%; object-fit: cover` and the <figure> keeps its
   `overflow: hidden`, so an image of any shape fills its frame on the short axis
   and is clipped on the long one, exactly as in the side layout. Only the frame
   changes shape here; the fitting behaviour is untouched. */
.uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__gallery {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
}

/* The pair on top, the main image beneath. Presentation only -- see the note in
   template-parts/service/header.php on why the DOM order is left alone. */
.uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__thumbnails {
    order: 1;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-rows: minmax(0, 1fr);
    margin-top: 0;
}

.uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__image--main {
    order: 2;
    aspect-ratio: 7 / 3;
    height: auto;
}

/* The side layout takes the thumbnails box OUT OF FLOW so the row is sized by
   the tall main image alone (see the note on __image--thumbnail above). Here
   there is no tall image to take height from, so the pair is put back in flow
   and given a real ratio of its own. */
.uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__image--thumbnail {
    position: static;
    height: auto;
    aspect-ratio: 5 / 4;
}

.uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__image--thumbnail img {
    position: static;
}

/* TWO IMAGES: one small visual on top rather than two. It spans the full width
   and takes the wide ratio, so the result is two wide images stacked rather than
   a half-width card with a hole beside it. */
.uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__thumbnails--single {
    grid-template-columns: minmax(0, 1fr);
}

.uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__thumbnails--single .uq-service-gallery-hero__image--thumbnail {
    aspect-ratio: 7 / 3;
}

/* ONE IMAGE: there is no pair and no arrangement to make, so the solo rule
   above stands. Restated at (0,3,0) only because the stacked main rule is later
   in the file and would otherwise win on source order. */
.uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__gallery--solo .uq-service-gallery-hero__image--main {
    aspect-ratio: 16 / 9;
}

/* ---------- Responsive ----------
   The gallery is already capped at 736px and centred below 991px, so the
   composition simply narrows. What has to be answered is the SIDE layout's own
   narrow-width rules: they relax the tall portrait towards square (4/4.4, then
   1/1), which would turn this layout's wide bottom image into a portrait one.
   Both rules below are (0,2,0) against those (0,1,0) declarations, so the
   stacked ratios hold at every width -- the media queries here only relax them,
   they are not what makes them apply. */
@media screen and (max-width: 767px) {
    /* 7/3 across a ~340px column is a 145px letterbox. 16/9 keeps the image
       readable while still reading as the wide one of the three.
       The two-image case's single top frame follows it, so those two wide
       images stay the same shape as each other at every width. */
    .uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__image--main,
    .uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__thumbnails--single .uq-service-gallery-hero__image--thumbnail {
        aspect-ratio: 16 / 9;
    }
}

@media screen and (max-width: 479px) {
    /* The pair stays two-up on a phone -- that is the composition -- but each
       card is now ~150px wide, where 5/4 is wider than it is useful. */
    .uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__image--thumbnail {
        aspect-ratio: 1 / 1;
    }

    /* Declared AFTER the square pair above, because the two-image case's single
       frame matches both selectors and must stay wide rather than go square. */
    .uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__image--main,
    .uq-service-gallery-hero--photos-stacked .uq-service-gallery-hero__thumbnails--single .uq-service-gallery-hero__image--thumbnail {
        aspect-ratio: 3 / 2;
    }
}
