
        /* A LONG UNBROKEN STRING MUST NEVER PUSH THE PAGE SIDEWAYS. Shops type
           web addresses, email addresses and run-together names into these
           bands. Without this, one such string sets the minimum width of its
           band, and seven bands were measured laying the whole page out 224px
           wider than the window, which gives every visitor a horizontal
           scrollbar.

           CHANGED TWICE on 2026-09-07, and this is the settled answer. It went
           to "break-word" for a few hours because "anywhere" was breaking real
           words, and then back, because "break-word" let the editor lay out
           1311px wide in a 1280px window again. Both symptoms were real; the
           word breaking was the fixable one, so the narrow boxes causing it were
           fixed instead and "anywhere" was restored. The old note follows.

           WHY "anywhere" AND NOT "break-word". "anywhere"
           also lowers the minimum width a box reports, which is what made it
           attractive, but that cuts both ways: it lets a box become far narrower
           than its own words and then breaks those words to fit. On a phone that
           produced a Google rating reading "4." above "9" in a 26px box, and a
           heading reading "GUARANTE" above "ED" in a 167px card. Both boxes were
           too narrow because of separate layout bugs, and "anywhere" turned those
           bugs into visibly broken words instead of leaving them visible as
           overflow. Those layout causes are now fixed directly (grid columns and
           items allowed to shrink, a width cap at phone size), so the gentler
           rule is enough: it still breaks a genuinely unbreakable string like a
           web address, and it never breaks an ordinary word. */
        .site-root { overflow-wrap: anywhere; }
        .site-root h1,
        .site-root h2,
        .site-root h3,
        .site-root h4,
        .site-root h5,
        .site-root h6 {
          font-family: var(--site-font-head);
        }
        /* Signature texture: global film grain, non-interactive, fixed to the
           viewport, sits above the page but below interactive chrome. */
        .site-root::before {
          content: "";
          position: fixed;
          inset: 0;
          z-index: 40;
          pointer-events: none;
          opacity: 0.05;
          mix-blend-mode: overlay;
          background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
        }
        /* Shared angular buttons (Grit look). */
        .site-btn {
          display: inline-flex;
          align-items: center;
          gap: 10px;
          font-family: var(--site-font-head);
          font-weight: 600;
          text-transform: uppercase;
          letter-spacing: 0.06em;
          font-size: 14px;
          line-height: 1;
          padding: 14px 26px;
          /* A BUTTON NEVER WRAPS. Kept from the first pass at the bigger hero
             size, which split "Book Now" in the nav across two lines. A label
             too long for its space should push its own width, not fold. */
          white-space: nowrap;
          border: 2px solid transparent;
          cursor: pointer;
          text-decoration: none;
          transition: background .2s ease, box-shadow .2s ease, border-color .2s ease, transform .2s ease;
          clip-path: polygon(0 0, 100% 0, 100% 100%, 10px 100%, 0 calc(100% - 10px));
        }

        /* HALF AGAIN AS BIG, BUT ONLY IN A HERO. Joey's call 2026-09-01, and the
           correction to a first pass that grew every button on the site: a card
           CTA and a nav CTA were never the problem. What read as an afterthought
           was the one button under a hero headline three times its size.

           Scoped to the four hero button rows rather than given its own class,
           so no hero component has to be edited and nothing else can pick it up
           by accident. The measurements are the shared ones with half added, so
           the shape is unchanged. */
        .site-hero-btns .site-btn,
        .site-phero-btns .site-btn,
        .site-shero-btns .site-btn,
        .ax-hero-btns .site-btn {
          gap: 15px;
          font-size: 21px;
          padding: 21px 39px;
          clip-path: polygon(0 0, 100% 0, 100% 100%, 15px 100%, 0 calc(100% - 15px));
        }
        .site-btn-primary {
          background: var(--site-accent);
          color: var(--site-btn-fg, #fff);
        }
        .site-btn-primary:hover {
          background: var(--site-accent-2);
          box-shadow: 0 12px 34px var(--site-accent-glow);
        }
        .site-btn-ghost {
          background: rgba(255,255,255,0.04);
          color: var(--site-fg);
          border-color: var(--site-border);
        }
        .site-btn-ghost:hover {
          border-color: var(--site-fg);
        }
        /* A hero is painted black whatever mode the site is in, so a ghost
           button inside one must follow the HERO's text colour, not the page's.
           On a light site the page colour is near black, which put a black
           "Call Us" on a black hero and made it impossible to read. */
        .site-hero .site-btn-ghost,
        .site-phero .site-btn-ghost {
          color: var(--site-hero-fg, var(--site-fg));
          border-color: var(--site-hero-border, var(--site-border));
        }
        .site-hero .site-btn-ghost:hover,
        .site-phero .site-btn-ghost:hover {
          border-color: var(--site-hero-fg, var(--site-fg));
        }
        /* NOTHING MAY BE WIDER THAN THE SCREEN IT IS DRAWN ON. The words block
           in a band carries a width from somewhere further up that survives
           every other guard: its own min-width computes 0, its grid column is
           350px, and it still measured 377.86px on a 390px phone, hanging 8px
           off the right edge with the last letter of every line clipped. A cap
           of 100% is the honest floor for a phone. It can only ever shrink
           something already too wide, so nothing that fitted moves, and it is
           deliberately not applied above phone width where wider blocks are the
           design. */
        @media (max-width: 600px) {
          .site-root .site-sec-body { max-width: 100%; }
        }

        /* THE SPECS A BUYER ACTUALLY READS, big enough to read. The service and
           film cards carry their labels at 0.6 to 0.72rem, which is 9.6 to
           11.5px. On a desktop card that is a fine small caption. On a phone the
           IR, HEAT, UV and WARRANTY figures on a film card, and the installation
           time on a PPF card, are the numbers somebody is deciding on, and they
           were the smallest type on the whole site.

           Scoped to .site-root on purpose. The same card is used by the booking
           pages, which are not inside .site-root and are somebody else's surface,
           so they are deliberately untouched. Raises only, never shrinks. */
        @media (max-width: 600px) {
          .site-root .usc-eyebrow,
          .site-root .usc-brand,
          .site-root .usc-stat-label,
          .site-root .usc-orig,
          .site-root .usc-save,
          .site-root .usc-corner-badge { font-size: 12px; }
        }

        /* ---- BIG ENOUGH TO HIT WITH A THUMB ----
           Measured on a real 390px phone: 22 of the 38 tappable things on the
           home page are under 44px tall, which is the size a finger actually
           needs. The footer is the bulk of it, twelve links 15px tall with 17px
           of gap between one line of text and the next, so a miss lands on the
           link above or below. The phone number in the top bar is a 14px tall
           tap target, and it is a call button.

           Phone only. On a desktop a 15px link is fine because a mouse is
           precise, and growing these there would change every shop's footer for
           no reason. Height only: no colour, no size, no weight changes. */
        @media (max-width: 600px) {
          .site-root footer a,
          .site-root [data-announcement-strip] a {
            min-height: 44px;
            display: inline-flex;
            align-items: center;
          }

          /* Every button on the site, same floor. The hero's "Call Us" measured
             233 x 32 on four pages, and it is a call button, which is the single
             thing a customer on a phone is most likely to press. The "Learn More"
             buttons were 34, "Book Online" and "Contact Us" 29. Raises only: a
             button already 44 or taller is not touched, and the horizontal
             padding, the type and the colours are all left alone. */
          /* The class is doubled on purpose. Several bands style their own
             button in their own stylesheet, which is injected after this one, so
             at equal specificity theirs won and the floor did nothing: the
             services page CTA stayed 34px tall. Doubling the class costs
             nothing and puts the floor back in front. */
          .site-root .site-btn.site-btn { min-height: 44px; }

          /* The "Read more" on a review is a real control, not decoration. */
          .site-root .ax-rev-more { min-height: 44px; }

          /* A reviewer's name and the date under it were 14 to 17px tall links.
             They sit inside a card that is already tappable, so they only need
             enough room not to be a mis-tap. */
          .site-root [class*="rev-"] a,
          .site-root [class*="review"] a { min-height: 32px; display: inline-flex; align-items: center; }
        }

        /* ---- A LONG STRING MUST NOT WIDEN THE PAGE ----
           A grid or flex child's default minimum width is "auto", which is its
           own min-content. So one unbreakable string, a web address or an email
           or a run-together name, sets the minimum width of its column, the
           column sets the minimum width of the band, and the band sets the
           minimum width of the page. Measured: seven bands laid the page out
           224px wider than the window from a single long word.

           A "min-width: 0" on the children of the site's own layout containers is
           the standard fix and is only ever permissive: it lowers a floor, so
           nothing that already fitted can move. Deliberately scoped to the
           site's own wrappers rather than every element on the page. */
        .site-root .site-wrap > *,
        .site-root .site-sec-body > *,
        .site-root [class*="-grid"] > * { min-width: 0; }

        .site-btn-arrow { transition: transform .2s ease; }
        .site-btn:hover .site-btn-arrow { transform: translateX(4px); }

        /* Section rhythm. Desktop keeps the tall Grit spacing; smaller widths
           step it down so phones/tablets don't scroll through huge empty gaps
           (desktop >= 901px is untouched). */
        /* Unified content container + side gutter for the whole site. Every
           content container uses .site-wrap: a CENTERED column capped at 1560px
           with a responsive side gutter, so content is a comfortable bounded
           width (never crushed on laptops, never ballooning on wide monitors) and
           every section's content edge lines up. Full-bleed section BACKGROUNDS
           (color bands, the hero image) still span edge-to-edge; only the CONTENT
           column is capped and centered by .site-wrap. Inner reading-width caps
           (headings, paragraph blocks) stay as max-widths inside the column. */
        .site-root { --site-gutter: clamp(24px, 5vw, 72px); }
        .site-sec { position: relative; padding: 104px 0; }
        /* One number for the content column, so a template can move every
           content edge together. Classic's value is the 1760px fallback, so
           this is a no-op for classic; Apex sets --site-content-max to its own
           tighter width. The few section components that used to hardcode 1760
           read the same variable with the same fallback. */
        .site-wrap { max-width: var(--site-content-max, 1760px); margin: 0 auto; padding: 0 var(--site-gutter); }
        /* THE DASHBOARD'S PHONE RULE WAS LANDING ON THE PUBLIC SITE. globals.css
           carries "@media (max-width: 768px) { main { margin-left: 0 !important;
           padding-top: 72px !important } }", written for a mobile dashboard
           header (.mobile-header) that no longer exists anywhere in the code. It
           matches every <main> in the app, so every page of every shop's website
           opened on a phone began with 72px of empty background above the hero.
           Overridden here rather than deleted there, because that block also
           reaches the dashboard and the booking flow and neither was checked in
           this pass. Deleting the dead block is the real fix. */
        @media (max-width: 768px) {
          .site-root main { padding-top: 0 !important; margin-left: 0 !important; }
        }
        @media (max-width: 900px) { .site-sec { padding: 76px 0; } }
        @media (max-width: 600px) {
          .site-sec { padding: 56px 0; }
          .site-root { --site-gutter: 20px; }
        }

        /* Per-section "Spacing" and "Where the content sits" settings (Section
           Settings popover) AND the Site Style sitewide defaults, which stamp the
           same attributes. SectionList wraps each section in a display:contents
           element carrying data-sec-spacing / data-sec-align; these rules turn
           that into padding / alignment on the section's own site-sec root.
           A descendant selector is used here rather than a child combinator.
           CORRECTED 2026-09-07: an earlier note claimed a child combinator
           "does not match reliably" through the display:contents wrapper. That
           is wrong, and it sent at least one session looking in the wrong place.
           display:contents removes the element's BOX, not the element, so
           selectors still match it and its children normally. Measured on the
           real page: [data-sec-spacing] > * matched every wrapper and painted.
           The descendant form is kept because it is what shipped and works;
           the reason it sometimes appears to fail is nothing to do with the
           combinator, it is that several bands write their padding as an INLINE
           style, which beats any stylesheet rule whatever its specificity. Those
           bands read the setting in their own component instead.
           Each wrapper holds exactly one section (.site-sec never nests), so the
           descendant match still targets only that section. When a section has
           no setting the wrapper carries no attribute, so nothing here applies
           and the section renders exactly as before. */
        [data-sec-spacing="compact"] .site-sec { padding-top: 64px; padding-bottom: 64px; }
        [data-sec-spacing="normal"] .site-sec { padding-top: 104px; padding-bottom: 104px; }
        [data-sec-spacing="roomy"] .site-sec { padding-top: 148px; padding-bottom: 148px; }

        /* ── WHERE THE CONTENT SITS ──────────────────────────────────────────
           The one place a shop's alignment choice is implemented.

           text-align on its own only rags glyphs INSIDE a box. Every band puts
           its heading in a box narrower than the band (Apex caps it at 21ch), so
           text-align alone left the heading stranded in its own column while the
           eyebrow chip and the buttons, being inline-flex, flew the full width.
           That is the bug. These rules move the BOX as well, with auto side
           margins and flex alignment, which is what actually relocates a column.

           Four shared classes, one job each, declared per band in SECTION_ALIGNS:
             .site-sec-head     the eyebrow / heading / lead column
             .site-sec-body     a full-width column that MOVES but whose children
                                must stay stretched, so never align-items here
             .site-sec-card     the inside of one repeated card
             .site-sec-row      a row of buttons, chips, stats or tabs

           !important, the same way [data-sec-cols] does it below, because a band
           writes its OWN shipped alignment as an inline style (alignmentStyle)
           and the shop's choice has to beat it. The two agree on every value, so
           this only ever wins a tie.

           A section the shop never touched carries no attribute, so not one rule
           here matches and it renders exactly as before. */
        [data-sec-align="left"] .site-sec { text-align: left; }
        [data-sec-align="center"] .site-sec { text-align: center; }
        [data-sec-align="right"] .site-sec { text-align: right; }

        /* The header column has to be a flex column for align-items to reach the
           eyebrow and the heading. Most already are; the Apex header block is not. */
        [data-sec-align] .site-sec-head { display: flex !important; flex-direction: column !important; }

        [data-sec-align="left"] .site-sec-head,
        [data-sec-align="left"] .site-sec-card { text-align: left !important; align-items: flex-start !important; }
        [data-sec-align="center"] .site-sec-head,
        [data-sec-align="center"] .site-sec-card { text-align: center !important; align-items: center !important; }
        [data-sec-align="right"] .site-sec-head,
        [data-sec-align="right"] .site-sec-card { text-align: right !important; align-items: flex-end !important; }

        [data-sec-align="left"] .site-sec-head,
        [data-sec-align="left"] .site-sec-body { margin-left: 0 !important; margin-right: auto !important; }
        [data-sec-align="center"] .site-sec-head,
        [data-sec-align="center"] .site-sec-body { margin-left: auto !important; margin-right: auto !important; }
        [data-sec-align="right"] .site-sec-head,
        [data-sec-align="right"] .site-sec-body { margin-left: auto !important; margin-right: 0 !important; }

        /* A HERO'S WORDS STAY IN THE PAGE COLUMN, WHATEVER THE ALIGNMENT.
           The three heroes put their words in a capped column that the band
           centres. The rules just above push a .site-sec-head to one side with
           an auto margin, which is right for a heading inside a section, but on
           a hero it dragged the whole capped column to the edge of the screen:
           on a wide screen a left aligned hero's headline sat 66px from the
           edge while the header and every section below started hundreds of
           pixels further in. Joey saw it on the service pages, 2026-09-13.
           Alignment still moves the words inside the column (text-align and
           align-items above); only the column itself stays put. Every shop. */
        [data-sec-align] .site-hero-inner.site-sec-head,
        [data-sec-align] .site-phero-inner.site-sec-head,
        [data-sec-align] .site-shero-inner.site-sec-head { margin-left: auto !important; margin-right: auto !important; }

        [data-sec-align="left"] .site-sec-body { text-align: left !important; }
        [data-sec-align="center"] .site-sec-body { text-align: center !important; }
        [data-sec-align="right"] .site-sec-body { text-align: right !important; }

        [data-sec-align="left"] .site-sec-row { justify-content: flex-start !important; }
        [data-sec-align="center"] .site-sec-row { justify-content: center !important; }
        [data-sec-align="right"] .site-sec-row { justify-content: flex-end !important; }
        @media (max-width: 900px) {
          [data-sec-spacing="compact"] .site-sec { padding-top: 48px; padding-bottom: 48px; }
          [data-sec-spacing="normal"] .site-sec { padding-top: 76px; padding-bottom: 76px; }
          [data-sec-spacing="roomy"] .site-sec { padding-top: 104px; padding-bottom: 104px; }
        }

        /* Per-section "How many across" setting. A grid section stamps
           data-sec-cols on its grid element; these rules override its column
           count, and stay responsive so a wide choice still collapses on small
           screens (never an unreadable row of tiny cards). No attribute → the
           section keeps its own default column count. */
        [data-sec-cols="2"] { grid-template-columns: repeat(2, 1fr) !important; }
        [data-sec-cols="3"] { grid-template-columns: repeat(3, 1fr) !important; }
        [data-sec-cols="4"] { grid-template-columns: repeat(4, 1fr) !important; }
        @media (max-width: 900px) {
          [data-sec-cols="3"], [data-sec-cols="4"] { grid-template-columns: repeat(2, 1fr) !important; }
        }
        @media (max-width: 600px) {
          [data-sec-cols] { grid-template-columns: 1fr !important; }
        }

        /* Eyebrow label: accent triangle + tracked uppercase + trailing // */
        .site-eyebrow {
          display: inline-flex;
          align-items: center;
          gap: 13px;
          font-family: var(--site-font-head);
          font-weight: 600;
          text-transform: uppercase;
          letter-spacing: 0.2em;
          font-size: 13px;
          color: var(--site-accent-2);
        }
        /* Decorations render only when the eyebrow has real text, so an empty /
           unset eyebrow never shows a stray arrow or trailing marks. */
        .site-eyebrow:not(:empty)::before {
          content: "";
          width: 0; height: 0;
          border-top: 5px solid transparent;
          border-bottom: 5px solid transparent;
          border-left: 9px solid var(--site-accent);
        }
        .site-eyebrow:not(:empty)::after {
          content: "//";
          letter-spacing: -0.05em;
          color: var(--site-subtle);
          font-weight: 700;
        }
        .site-eyebrow.center { justify-content: center; }

        /* Angular clip-path cut corner (bottom-left), the signature card shape. */
        .site-cut { clip-path: polygon(0 0, 100% 0, 100% 100%, 16px 100%, 0 calc(100% - 16px)); }
        .site-cut-lg { clip-path: polygon(0 0, 100% 0, 100% 100%, 22px 100%, 0 calc(100% - 22px)); }

        /* Corner brackets in the shop accent. */
        .site-brk { position: relative; }
        .site-brk::before, .site-brk::after {
          content: ""; position: absolute; width: 16px; height: 16px; z-index: 3; pointer-events: none;
        }
        .site-brk::before { top: 12px; left: 12px; border-top: 2px solid var(--site-accent-2); border-left: 2px solid var(--site-accent-2); }
        .site-brk::after { bottom: 12px; right: 12px; border-bottom: 2px solid var(--site-accent-2); border-right: 2px solid var(--site-accent-2); }

        /* Carbon weave + blueprint dot-grid section textures. */
        .site-carbon {
          background-image:
            repeating-linear-gradient(45deg, rgba(255,255,255,.014) 0 1px, transparent 1px 5px),
            repeating-linear-gradient(-45deg, rgba(255,255,255,.014) 0 1px, transparent 1px 5px);
        }
        .site-dotgrid { background-image: radial-gradient(rgba(255,255,255,.05) 1px, transparent 1.4px); background-size: 24px 24px; }

        /* Accent edge glow in the top-right of a section. */
        .site-glow { position: relative; }
        .site-glow::before {
          content: ""; position: absolute; top: 0; right: 0; width: 40%; height: 60%;
          pointer-events: none; z-index: 0;
          background: radial-gradient(120% 100% at 100% 0%, var(--site-accent-glow), transparent 70%);
        }
        .site-glow > * { position: relative; z-index: 1; }

        /* ── Media block ──────────────────────────────────────────────────
           A photo, an uploaded video, or an embedded video, with optional words
           beside it. The five arrangements are pure CSS off data-mb-layout, so
           the component never branches on layout. Written against the shared
           site variables only, no template-specific tokens, so the same block
           works under classic and under Apex.

           The DOM order is always words then media. That keeps the reading
           order sensible for a screen reader and means the one column phone
           layout needs no rules at all: it simply falls out of the source
           order. Only "media left" reorders, and only on wide screens. */
        .site-mb-grid { display: grid; gap: clamp(28px, 4vw, 56px); align-items: center; }
        .site-mb-media { min-width: 0; }
        .site-mb-photo,
        .site-mb-video {
          display: block;
          width: 100%;
          height: auto;
          border-radius: 4px;
        }
        /* A 16 by 9 window for an embedded player. aspect-ratio rather than the
           old padding trick, so the frame is one element and cannot drift. */
        .site-mb-frame { position: relative; width: 100%; aspect-ratio: 16 / 9; }
        .site-mb-frame iframe {
          position: absolute; inset: 0;
          width: 100%; height: 100%;
          border: 0;
          border-radius: 4px;
        }
        .site-mb-head {
          font-family: var(--site-font-head);
          font-size: clamp(26px, 3.2vw, 42px);
          line-height: 1.12;
          margin: 0 0 18px;
          color: var(--site-fg);
        }
        .site-mb-body { color: var(--site-muted, var(--site-fg)); line-height: 1.65; font-size: 16px; }
        .site-mb-body p { margin: 0 0 14px; }
        .site-mb-body p:last-child { margin-bottom: 0; }
        .site-mb-body ul { margin: 0 0 14px; padding-left: 20px; }
        .site-mb-body li { margin: 0 0 7px; }
        .site-mb-btn { margin-top: 26px; }

        /* Media only. The picture carries the band on its own. */
        .site-mb[data-mb-layout="media_only"] .site-mb-grid { grid-template-columns: 1fr; }

        /* Centered. The media wide across the middle, the words centered under
           it in a narrow measure so the line length stays readable. */
        .site-mb[data-mb-layout="centered"] .site-mb-grid {
          grid-template-columns: 1fr;
          justify-items: center;
        }
        .site-mb[data-mb-layout="centered"] .site-mb-media { order: 1; width: 100%; }
        .site-mb[data-mb-layout="centered"] .site-mb-copy {
          order: 2;
          text-align: center;
          max-width: 720px;
        }

        /* Stacked. The other way round and at a different width: the words come
           FIRST, and the media sits under them inset to a narrower column. Two
           genuinely different shapes, not two names for one. */
        .site-mb[data-mb-layout="stacked"] .site-mb-grid {
          grid-template-columns: 1fr;
          justify-items: center;
          gap: clamp(24px, 3vw, 40px);
        }
        .site-mb[data-mb-layout="stacked"] .site-mb-copy {
          text-align: center;
          max-width: 760px;
        }
        .site-mb[data-mb-layout="stacked"] .site-mb-media { width: min(100%, 900px); }

        /* Words only. No picture at all: the heading, the words and the button,
           in the normal content column. The band's background is whatever the
           shop set behind it in "Behind this section", so nothing is needed here
           for that. */
        .site-mb[data-mb-layout="no_media"] .site-mb-grid { grid-template-columns: 1fr; }

        /* ── Side by side, EDGE TO EDGE ──────────────────────────────────────
           The picture runs from the middle of the page out to the edge of the
           screen, and the full height of the band, top and bottom. The words
           keep the ordinary content column on the other half, so a heading here
           still lines up with every other heading on the page.

           HOW IT REACHES THE EDGE WITHOUT 100vw. The band drops the capped,
           centred content column for these two arrangements and lets the grid
           span the section's own full width, so each half is exactly half the
           SCREEN. That matters: 100vw includes the scrollbar on the platforms
           that reserve one, which is the classic way a full bleed band gives a
           page a horizontal scrollbar. Nothing here reads vw at all.

           WHERE THE WORDS SIT. Their half then pads itself back in to the
           content column's own edge: half the content box measured from the
           middle, plus the page gutter, with the plain gutter as the floor for
           a screen narrower than the content box. Percentages inside a grid item
           resolve against that item's own track, which is exactly the half we
           are measuring from.

           THE BAND'S HEIGHT is set by the words, not by the picture. The picture
           is laid over its half and cropped to fill it, so a tall portrait photo
           cannot stretch the band and a short one cannot leave a gap. A minimum
           height keeps a one line heading from producing a letterbox. */
        @media (min-width: 901px) {
          /* !important, and it is load bearing. The band gives up its own top and
             bottom padding so the picture can reach the top and bottom edges, and
             three other rules set that padding: the base .site-sec, the Apex
             template's own, and the shop's Spacing choice. Two of the three are
             injected after this one at equal specificity, so anything short of
             !important loses to whichever landed last. The rhythm is not lost, it
             moves to the words (--site-mb-pad-t / -b below), which is the only
             column that still needs it. */
          .site-mb[data-mb-layout="media_right"],
          .site-mb[data-mb-layout="media_left"] {
            padding-top: 0 !important;
            padding-bottom: 0 !important;
          }
          .site-mb[data-mb-layout="media_right"] > .site-wrap,
          .site-mb[data-mb-layout="media_left"] > .site-wrap {
            max-width: none;
            padding: 0;
          }
          .site-mb[data-mb-layout="media_right"] .site-mb-grid,
          .site-mb[data-mb-layout="media_left"] .site-mb-grid {
            grid-template-columns: 1fr 1fr;
            gap: 0;
            align-items: stretch;
            min-height: var(--site-mb-min-h, 460px);
          }
          /* Nothing written yet, so there is no second column to give half the
             screen to. The picture takes the whole band instead. */
          .site-mb[data-mb-layout="media_right"] .site-mb-grid[data-mb-words="0"],
          .site-mb[data-mb-layout="media_left"] .site-mb-grid[data-mb-words="0"] {
            grid-template-columns: 1fr;
          }
          /* The copy keeps the band's own vertical rhythm, which the section
             root just gave up, and stays vertically centred beside the picture.
             --site-mb-pad mirrors the section spacing the shop chose, below. */
          .site-mb[data-mb-layout="media_right"] .site-mb-copy,
          .site-mb[data-mb-layout="media_left"] .site-mb-copy {
            align-self: center;
            padding-top: var(--site-mb-pad-t, 104px);
            padding-bottom: var(--site-mb-pad-b, 104px);
          }
          .site-mb[data-mb-layout="media_right"] .site-mb-copy {
            padding-left: max(
              var(--site-gutter),
              calc(100% - var(--site-content-max, 1760px) / 2 + var(--site-gutter))
            );
            padding-right: clamp(28px, 4vw, 56px);
          }
          .site-mb[data-mb-layout="media_left"] .site-mb-copy {
            padding-right: max(
              var(--site-gutter),
              calc(100% - var(--site-content-max, 1760px) / 2 + var(--site-gutter))
            );
            padding-left: clamp(28px, 4vw, 56px);
          }
          /* The only reorder in the whole block: the media moves to column one
             and the words to column two. Source order is untouched. */
          .site-mb[data-mb-layout="media_left"] .site-mb-copy { order: 2; }
          .site-mb[data-mb-layout="media_left"] .site-mb-media { order: 1; }

          .site-mb[data-mb-layout="media_right"] .site-mb-media,
          .site-mb[data-mb-layout="media_left"] .site-mb-media {
            position: relative;
            align-self: stretch;
          }
          .site-mb[data-mb-layout="media_right"] .site-mb-media > *,
          .site-mb[data-mb-layout="media_left"] .site-mb-media > * {
            position: absolute;
            inset: 0;
            width: 100%;
            height: 100%;
            border-radius: 0;
            object-fit: cover;
          }
          /* An embedded player cannot be cropped, so its 16 by 9 window is
             dropped and the player fills the half instead. The provider
             letterboxes inside it, which is the honest result: edge to edge, and
             nothing of the video lost. */
          .site-mb[data-mb-layout="media_right"] .site-mb-frame,
          .site-mb[data-mb-layout="media_left"] .site-mb-frame { aspect-ratio: auto; }
          .site-mb[data-mb-layout="media_right"] .site-mb-frame iframe,
          .site-mb[data-mb-layout="media_left"] .site-mb-frame iframe { border-radius: 0; }
        }

        /* The band's own copy of the section spacing, so the words keep the exact
           rhythm they would have had after the section root gives its padding up.
           Every value here is read from, or matches, the rule it stands in for:
           the base 104px, the Apex template's own pair, and the three Spacing
           choices. Declared in that order so the shop's choice is last and wins.
           Scoped to this block, so no other band's padding is touched. */
        .site-mb { --site-mb-pad-t: 104px; --site-mb-pad-b: 104px; }
        [data-site-template="apex"] .site-mb {
          --site-mb-pad-t: var(--ax-sec-pad-t, clamp(80px, 7.6vw, 118px));
          --site-mb-pad-b: var(--ax-sec-pad-b, clamp(80px, 7.6vw, 118px));
        }
        [data-sec-spacing="compact"] .site-mb { --site-mb-pad-t: 64px; --site-mb-pad-b: 64px; }
        [data-sec-spacing="normal"] .site-mb { --site-mb-pad-t: 104px; --site-mb-pad-b: 104px; }
        [data-sec-spacing="roomy"] .site-mb { --site-mb-pad-t: 148px; --site-mb-pad-b: 148px; }

        /* PHONE AND TABLET. "Left" and "right" stop meaning anything once the
           two halves stack, so edge to edge stops meaning a half and starts
           meaning the full width of the screen: the picture spans the whole
           band, at its natural height, and the words sit above it in the normal
           padded column. Nothing is cropped, because there is no other column to
           match a height to. */
        @media (max-width: 900px) {
          .site-mb[data-mb-layout="media_right"] > .site-wrap,
          .site-mb[data-mb-layout="media_left"] > .site-wrap { padding: 0; }
          .site-mb[data-mb-layout="media_right"] .site-mb-copy,
          .site-mb[data-mb-layout="media_left"] .site-mb-copy { padding: 0 var(--site-gutter); }
          .site-mb[data-mb-layout="media_right"] .site-mb-photo,
          .site-mb[data-mb-layout="media_left"] .site-mb-photo,
          .site-mb[data-mb-layout="media_right"] .site-mb-video,
          .site-mb[data-mb-layout="media_left"] .site-mb-video { border-radius: 0; }
        }

        /* ── Edit mode only ──────────────────────────────────────────────────
           The words are click-to-edit on the page, so an empty field has to be
           big enough to click and the body has to keep the line breaks the owner
           types. Neither rule can reach a public page: the classes are only ever
           put on in edit mode. */
        .site-mb-body-edit { min-height: 1.65em; }
        /* Only WHILE typing. A contenteditable box collapses the newlines that
           make paragraphs unless it is told to keep whitespace, and the value is
           read straight back out of it. */
        .site-mb-body-edit[data-editing="true"] { white-space: pre-wrap; }
        /* A button with a label but no link yet. It looks like the button it is
           about to be, and is deliberately not a link to nowhere. */
        .site-mb-btn-draft { opacity: 0.75; cursor: default; }
        /* Somewhere to click when the arrangement wants a picture and none has
           been chosen yet. */
        .site-mb-pick {
          display: flex; align-items: center; gap: 12px;
          min-height: 200px;
          padding: 24px;
          border: 1px dashed var(--site-border);
          color: var(--site-muted, var(--site-fg));
          font-size: 13px;
          line-height: 1.5;
        }

        /* Edit mode prompt for a block with nothing in it yet. Never rendered on
           a public page: a block with no media and no words draws nothing there,
           so a half finished block is never published. */
        .site-mb-empty {
          display: flex; align-items: center; gap: 14px;
          padding: 28px 24px;
          border: 1px dashed var(--site-border);
          border-radius: 4px;
          color: var(--site-muted, var(--site-fg));
        }
        .site-mb-empty strong { display: block; font-size: 14px; color: var(--site-fg); margin-bottom: 3px; }
        .site-mb-empty span { display: block; font-size: 13px; line-height: 1.5; }

        /* ── Certifications, the brand wall ───────────────────────────────
           Every tile is the same box whether it holds a logo or a name. That
           is the point: the platform logo library starts empty, so the ALL
           NAMES state is the one this band ships in and it has to look
           deliberate rather than like a grid of holes. A logo is contained
           inside the same 52px band a name is set in, so a wall that is half
           logos and half names still lines up.

           Written against the shared site variables only, no template
           specific tokens, so it works under classic and under Apex. */
        .site-cert-head {
          font-family: var(--site-font-head);
          font-size: clamp(24px, 2.6vw, 36px);
          line-height: 1.15;
          margin: 0 0 14px;
          color: var(--site-fg);
        }
        .site-cert-intro {
          color: var(--site-muted, var(--site-fg));
          font-size: 16px;
          line-height: 1.65;
          max-width: 720px;
          margin: 0 0 34px;
        }
        .site-cert-head + .site-cert-grid { margin-top: 30px; }
        /* auto-fit rather than a fixed count, so a shop with three brands and a
           shop with fourteen both get full rows. The shared "How many across"
           setting stamps data-sec-cols on this grid and overrides it. */
        /* The column count is set inline by the band from how many brands there
           are, so no row is ever left with one stray tile. This is only the
           fallback for a band that somehow renders without it. */
        .site-cert-grid {
          display: grid;
          grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
          gap: 16px;
          align-items: stretch;
        }
        /* Two across on a phone whatever was chosen for a wide screen, because
           one brand per row turns a six brand wall into six screens of
           scrolling. Declared after the shared data-sec-cols rules above and at
           the same specificity, so for THIS band it is the one that lands. */
        @media (max-width: 600px) {
          .site-cert-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; gap: 12px; }
        }
        /* STRIP, the arrangement the band ships in and the one that replaced the
           film cards on the home page. No grid, no frames, no borders: a single
           wrapping row of marks that centres itself, so two brands read as two
           marks in the middle of the band rather than as two thirds of a row.
           Declared after the grid rules and after the phone override, and the
           overrides are !important for the same reason those are: the shared
           "How many across" rule stamps a grid-template-columns on this same
           element and would otherwise win. */
        .site-cert-grid[data-brand-layout='strip'] {
          display: flex !important;
          flex-wrap: wrap;
          align-items: center;
          justify-content: flex-start;
          gap: 30px 54px;
          grid-template-columns: none !important;
        }
        /* The row lines up with the heading above it rather than picking a side
           of its own. It used to carry its own pair of alignment rules here; it
           now carries the shared .site-sec-row class instead, so the row and
           every other button row on the site move from one place. Left stays the
           base above, which also covers a section carrying no alignment at all. */
        .site-cert-grid[data-brand-layout='strip'] .site-cert-item {
          background: transparent;
          border: 0;
          min-height: 0;
          padding: 0;
          gap: 8px;
          /* The mark sizes itself to the word or the logo inside it rather than
             filling a track, which is what makes the row read as a row. */
          flex: 0 0 auto;
          max-width: 100%;
        }
        .site-cert-grid[data-brand-layout='strip'] .site-cert-mark {
          width: auto;
          height: 40px;
        }
        .site-cert-grid[data-brand-layout='strip'] .site-cert-logo { max-height: 40px; }
        /* A wall of names has frames holding it together. A strip of names does
           not, so the names carry a little more weight and sit at a steadier size
           to stop the row reading as loose body copy. */
        .site-cert-grid[data-brand-layout='strip'] .site-cert-name {
          font-size: clamp(16px, 1.6vw, 21px);
          font-weight: 700;
          opacity: 0.86;
        }
        @media (max-width: 600px) {
          .site-cert-grid[data-brand-layout='strip'] { gap: 20px 30px; }
          .site-cert-grid[data-brand-layout='strip'] .site-cert-mark { height: 32px; }
          .site-cert-grid[data-brand-layout='strip'] .site-cert-logo { max-height: 32px; }
        }
        .site-cert-item {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          gap: 10px;
          min-height: 118px;
          padding: 22px 16px;
          background: var(--site-card-bg);
          border: none;
        }
        .site-cert-mark {
          display: flex;
          align-items: center;
          justify-content: center;
          width: 100%;
          height: 52px;
        }
        .site-cert-logo {
          display: block;
          max-height: 52px;
          max-width: 100%;
          width: auto;
          height: auto;
          object-fit: contain;
        }
        .site-cert-name {
          font-family: var(--site-font-head);
          font-size: clamp(15px, 1.5vw, 19px);
          font-weight: 600;
          text-transform: uppercase;
          letter-spacing: 0.07em;
          line-height: 1.2;
          text-align: center;
          color: var(--site-fg);
        }
        .site-cert-note {
          font-size: 10.5px;
          font-weight: 600;
          text-transform: uppercase;
          letter-spacing: 0.14em;
          line-height: 1.4;
          text-align: center;
          color: var(--site-accent-2);
        }
        /* Edit mode prompt for a band with no brands in it yet. Never rendered
           on a public page: a band with nothing to show draws nothing there. */
        .site-cert-empty {
          display: flex; align-items: center; gap: 14px;
          padding: 28px 24px;
          border: 1px dashed var(--site-border);
          color: var(--site-muted, var(--site-fg));
        }
        .site-cert-empty strong { display: block; font-size: 14px; color: var(--site-fg); margin-bottom: 3px; }
        .site-cert-empty span { display: block; font-size: 13px; line-height: 1.5; }
        
  /* ---- Shaping: square ---- */
  [data-shape="square"] .site-btn,
  [data-shape="square"] .site-cut,
  [data-shape="square"] .site-cut-lg { clip-path: none; border-radius: 0; }

  /* ---- Shaping: rounded ---- */
  [data-shape="rounded"] .site-btn,
  [data-shape="rounded"] .site-cut,
  [data-shape="rounded"] .site-cut-lg { clip-path: none; border-radius: var(--site-radius, 14px); }

  /* ---- Shaping: angular / notch (bottom-left cut) ---- */
  [data-shape="angular"][data-astyle="notch"] .site-btn { border-radius: 0; clip-path: polygon(0 0,100% 0,100% 100%,10px 100%,0 calc(100% - 10px)); }
  [data-shape="angular"][data-astyle="notch"] .site-cut { border-radius: 0; clip-path: polygon(0 0,100% 0,100% 100%,16px 100%,0 calc(100% - 16px)); }
  [data-shape="angular"][data-astyle="notch"] .site-cut-lg { border-radius: 0; clip-path: polygon(0 0,100% 0,100% 100%,22px 100%,0 calc(100% - 22px)); }

  /* ---- Shaping: angular / bevel (top-left + bottom-right cut) ---- */
  [data-shape="angular"][data-astyle="bevel"] .site-btn { border-radius: 0; clip-path: polygon(9px 0,100% 0,100% calc(100% - 9px),calc(100% - 9px) 100%,0 100%,0 9px); }
  [data-shape="angular"][data-astyle="bevel"] .site-cut { border-radius: 0; clip-path: polygon(14px 0,100% 0,100% calc(100% - 14px),calc(100% - 14px) 100%,0 100%,0 14px); }
  [data-shape="angular"][data-astyle="bevel"] .site-cut-lg { border-radius: 0; clip-path: polygon(18px 0,100% 0,100% calc(100% - 18px),calc(100% - 18px) 100%,0 100%,0 18px); }

  /* ---- Shaping: angular / chamfer (all four corners cut) ---- */
  [data-shape="angular"][data-astyle="chamfer"] .site-btn { border-radius: 0; clip-path: polygon(8px 0,calc(100% - 8px) 0,100% 8px,100% calc(100% - 8px),calc(100% - 8px) 100%,8px 100%,0 calc(100% - 8px),0 8px); }
  [data-shape="angular"][data-astyle="chamfer"] .site-cut { border-radius: 0; clip-path: polygon(13px 0,calc(100% - 13px) 0,100% 13px,100% calc(100% - 13px),calc(100% - 13px) 100%,13px 100%,0 calc(100% - 13px),0 13px); }
  [data-shape="angular"][data-astyle="chamfer"] .site-cut-lg { border-radius: 0; clip-path: polygon(18px 0,calc(100% - 18px) 0,100% 18px,100% calc(100% - 18px),calc(100% - 18px) 100%,18px 100%,0 calc(100% - 18px),0 18px); }

  /* ---- Shaping: angular / slash (larger bottom-right cut) ---- */
  [data-shape="angular"][data-astyle="slash"] .site-btn { border-radius: 0; clip-path: polygon(0 0,100% 0,100% calc(100% - 12px),calc(100% - 12px) 100%,0 100%); }
  [data-shape="angular"][data-astyle="slash"] .site-cut { border-radius: 0; clip-path: polygon(0 0,100% 0,100% calc(100% - 22px),calc(100% - 22px) 100%,0 100%); }
  [data-shape="angular"][data-astyle="slash"] .site-cut-lg { border-radius: 0; clip-path: polygon(0 0,100% 0,100% calc(100% - 30px),calc(100% - 30px) 100%,0 100%); }

  /* ---- Angles: the shared part ----
     ONE site-wide setting decides which way every angled device on the site
     leans. Most of those devices belong to the Apex template and their rules
     live beside them in APEX_CSS; the slash marks below are the one angled
     device both templates share, so it is handled here.

     No attribute is the lean the site has always had, so an untouched shop is
     byte-identical. Specificity is one attribute above the base rule, so these
     win wherever the base rule is declared. */
  [data-angle="reverse"] .site-slashes i { transform: skewX(24deg); }
  [data-angle="straight"] .site-slashes i { transform: none; }

  /* ---- Accents ----
     Decorative accent marks layered on the REAL cards and section headers,
     keyed off data-accent on the site root. Every card carries an aria-hidden
     .site-acc layer; its ::before / ::after become the per-style marks and are
     clipped to the card by the card's own clip-path, so corners never break.
     Section headers are decorated in pure CSS off the shared .site-eyebrow and
     .site-wrap. No attribute on the root = no accents = existing shops are
     pixel-identical (the .site-acc layer stays inert with no pseudo content).
     Accents use the shop accent color (--site-accent). */

  /* The card accent layer: inert until a style gives its pseudos content. */
  .site-acc { position: absolute; inset: 0; z-index: 4; pointer-events: none; }

  /* Under any accent: anchor the layer to each card, and suppress the default
     .site-brk corner brackets so the chosen accent fully replaces them. */
  [data-accent] .site-cut, [data-accent] .site-cut-lg { position: relative; }
  [data-accent] .site-brk::before, [data-accent] .site-brk::after { display: none; }
  /* Section-header accent marks FRAME the eyebrow (only where a non-hero section
     has an eyebrow with real text), instead of floating on the section container
     where they overlapped the heading text or showed with no eyebrow at all. */
  [data-accent] .site-wrap:not(.site-hero-inner):not(.site-phero-inner):not(.site-shero-inner) .site-eyebrow { position: relative; }

  /* ===== BRACKETS: corner brackets on cards + a section corner bracket. ===== */
  [data-accent="brackets"] .site-acc::before {
    content: ""; position: absolute; top: 12px; left: 12px; width: 18px; height: 18px;
    border-top: 2px solid var(--site-accent); border-left: 2px solid var(--site-accent);
  }
  [data-accent="brackets"] .site-acc::after {
    content: ""; position: absolute; bottom: 12px; right: 12px; width: 18px; height: 18px;
    border-bottom: 2px solid var(--site-accent); border-right: 2px solid var(--site-accent);
  }
  [data-accent="brackets"] .site-wrap:not(.site-hero-inner):not(.site-phero-inner):not(.site-shero-inner) .site-eyebrow:not(:empty)::before {
    content: ""; position: absolute; top: -11px; left: -13px; width: 14px; height: 14px;
    border: none; border-top: 2px solid var(--site-accent); border-left: 2px solid var(--site-accent);
  }

  /* ===== PRECISION: index numbers + tick marks on cards, index + accent
     line by the section heading. ===== */
  [data-accent="precision"] .site-wrap { counter-reset: siteacc; }
  [data-accent="precision"] .site-acc { counter-increment: siteacc; }
  [data-accent="precision"] .site-acc::before {
    content: counter(siteacc, decimal-leading-zero);
    position: absolute; top: 12px; left: 14px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-weight: 700; font-size: 12px; color: var(--site-accent);
  }
  /* Cards that already render their own number opt out of the generated index. */
  [data-accent="precision"] .site-acc-plain { counter-increment: none; }
  [data-accent="precision"] .site-acc-plain::before { content: none; }
  [data-accent="precision"] .site-acc::after {
    content: ""; position: absolute; top: 14px; right: 14px; width: 16px; height: 2px;
    background: var(--site-accent);
    box-shadow: 0 5px 0 rgba(255,255,255,.35), 0 10px 0 rgba(255,255,255,.2);
  }
  [data-accent="precision"] .site-eyebrow:not(:empty)::after {
    content: "[ 01 ]"; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    letter-spacing: 0; color: var(--site-subtle); font-weight: 700;
  }
  [data-accent="precision"] .site-wrap:not(.site-hero-inner):not(.site-phero-inner):not(.site-shero-inner) .site-eyebrow:not(:empty)::before {
    content: ""; position: absolute; top: -9px; left: 0; width: 40px; height: 2px;
    border: none; background: var(--site-accent);
  }

  /* ===== SPORT: brackets + diagonal slashes + a left rail on cards, slash +
     connector accents by the section heading. ===== */
  [data-accent="sport"] .site-acc::before {
    content: ""; position: absolute; top: 12px; left: 12px; width: 16px; height: 16px;
    border-top: 2px solid var(--site-accent); border-left: 2px solid var(--site-accent);
  }
  [data-accent="sport"] .site-acc::after {
    content: ""; position: absolute; top: 12px; right: 12px; width: 40px; height: 11px;
    background: repeating-linear-gradient(115deg, var(--site-accent) 0 3px, transparent 3px 7px);
  }
  [data-accent="sport"] .site-cut, [data-accent="sport"] .site-cut-lg {
    border-left: 3px solid var(--site-accent);
  }
  [data-accent="sport"] .site-eyebrow:not(:empty)::after {
    content: ""; display: inline-block; width: 34px; height: 12px;
    background: repeating-linear-gradient(115deg, var(--site-accent) 0 3px, transparent 3px 7px);
  }
  [data-accent="sport"] .site-wrap:not(.site-hero-inner):not(.site-phero-inner):not(.site-shero-inner) .site-eyebrow:not(:empty)::before {
    content: ""; position: absolute; top: -8px; left: 0; width: 5px; height: 5px; border-radius: 50%;
    border: none; background: var(--site-accent);
    box-shadow: 9px 0 0 rgba(255,255,255,.3), 18px 0 0 rgba(255,255,255,.18);
  }

