/* components part 8 of 11 — split for the host's 16KB FTP ceiling.
   Generated by split_for_ftp.py; edit the prototype, not this. */


.c{--rowh:calc(var(--gw) / var(--dens) * var(--colscale));
   position:relative;display:block;padding:0;border:0;background:var(--grey);
   cursor:zoom-in;overflow:hidden;
   flex-grow:var(--ar);flex-basis:calc(var(--ar) * var(--rowh));flex-shrink:1;min-width:0;
   /* the spike killer: without it an unlucky row inflates to 2.26x --rowh */
   /* 1.9, not 1.5. The cap stops one freak-ratio frame spiking a row, but at 1.5 it sat
      BELOW the growth factor ordinary rows legitimately need — measured up to 1.909
      uncapped at a 360px wall — so it was clipping normal rows and leaving the white
      wedge on the right. 1.9 is the smallest value that clears the current 267-frame
      set: zero short mid-list rows at every wall width from 360 to 3000, with row
      composition byte-identical to 1.5 at all of them. Re-check it if the density or
      the aspect-ratio clamp changes. */
   max-width:calc(var(--ar) * var(--rowh) * var(--rowcap));
   aspect-ratio:var(--ar)}
/* content-visibility:auto used to live here as an optimisation for 233 frames. It
   also stops the browser rendering the subtree until it is nearly on screen, and a
   lazy <img> inside unrendered content does not begin loading either — so fast
   scrolling landed on rows of empty grey boxes that only filled in after they were
   already in view. The aspect-ratio box already reserves the layout, which was the
   other thing content-visibility was buying. */
.c img{width:100%;height:100%;object-fit:cover;display:block;transition:filter .35s}
/* The hover says "this opens" and nothing else — no title card, no zoom, matching
   the gallery on the service pages. */
.c:hover,.c:focus,.c:focus-visible{background:var(--grey);color:var(--ink)}
.c:hover img,.c:focus-visible img{filter:brightness(.9)}
.c:focus-visible{outline:2px solid var(--accent);outline-offset:2px;z-index:2}
/* the last row must not stretch its survivors across the full viewport */
.wall::after{content:"";flex-grow:1e6;flex-basis:0;min-width:0}@container wall (width < 1041px){ .c{--colscale:1.30}}@container wall (width >= 2500px){ .c{--colscale:.78}}@supports not (container-type:inline-size){
  @media(max-width:760px){ .wall{--colscale:1.30} }}
/* One frame may be pulled out of the justified run and given a row to itself, so it
   reads as roughly a two-row element. It cannot be done inside a row: every card in a
   line lands at `--rowh + freespace/sum(grow)`, a height independent of the card,
   because grow and basis are both proportional to --ar — that identity IS the flush
   row. A card with a doubled basis is therefore taller than its row-mates, the line's
   cross size takes the max, and align-items:stretch overrides the others'
   aspect-ratio: measured, a 16:9 exterior beside a doubled card rendered at 1.035 and
   lost 42% of its width to object-fit:cover.
   Two zero-height full-width spacers fence the frame onto its own line instead, and
   nothing else in the wall changes size at all.
   2.5 and not 2: a three-up row settles about 26% above --rowh once free space is
   distributed, so 2.5x --rowh lands at 1.98x the neighbouring rows.
   flex-basis:100% is the shortcut that does NOT work — line breaking uses the
   hypothetical main size, which is already clamped by max-width, so the cap silently
   lets a neighbour back onto the line and crushes it. */
.brk{flex:0 0 100%;height:0;margin:0;padding:0}
.brk[hidden]{display:none}
/* A frame named in `pair` runs two-up instead of three, for emphasis. Doubling the basis
   is safe HERE and not in a normal row because these are declared in adjacent pairs: both
   cards in the row get the same multiplier, so the row still lands flush and neither is
   stretched past its aspect ratio. Reuses --colscale rather than a new mechanism. */
.c.pair{--colscale:1.5}
/* Full width, not a centred island. At 2.5x --rowh the frame came out 813px inside a
   1322px wall — 61% — which left white down both sides and read as a broken row rather
   than a feature. Taking the whole width removes the gaps and makes the emphasis look
   deliberate.
   The height comes from aspect-ratio, NOT from `height:calc(var(--rowh)*2.5)`. --rowh is
   a PERCENTAGE (calc(100%/6.1)), and a percentage height resolves against the parent's
   height — which for a flex item in a wrap container is indefinite, so it silently fell
   back to auto and the frame rendered 1148px tall at its native 1.5. 2.4 is two normal
   rows at any wall width, and .c img is object-fit:cover so the crop takes sky and
   foreground off a dusk aerial, which it can afford. */
.c.feat{flex:0 0 100%;max-width:100%;aspect-ratio:2.4}
/* A filtered-out feature must take its fences with it, or the wall keeps a hole and a
   stranded two-up where the frame used to be. */
.c.feat[hidden] + .brk,
.brk:has(+ .c.feat[hidden]){display:none}
.c[hidden]{display:none}

/* A panorama opens into a viewer rather than a flat image, so it has to announce
   itself before the click. This is the one mark left on a frame, and it is a
   control's affordance, not a caption. */
/* The 360 marker reads like a video thumbnail's play button: centred, large enough to
   be the first thing you see, and light rather than heavy so it sits ON the image
   instead of punching a hole in it. A corner chip said "this is tagged 360"; a centre
   disc says "this one opens and turns", which is the thing worth communicating. */
.pbadge{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
        width:62px;height:62px;display:grid;place-items:center;border-radius:50%;
        pointer-events:none;background:rgba(255,255,255,.24);
        -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
        border:1.5px solid rgba(255,255,255,.7);
        box-shadow:0 2px 14px rgba(16,15,13,.22);
        color:#fff;font-size:11px;font-weight:800;letter-spacing:.04em;
        line-height:1;transition:background .25s,transform .25s,border-color .25s}
.pbadge svg{position:absolute;inset:0;width:100%;height:100%;
            fill:none;stroke:rgba(255,255,255,.85);stroke-width:1.1}@media(prefers-reduced-motion:no-preference){
  .pbadge svg{animation:pspin 9s linear infinite}}@keyframes pspin{to{transform:rotate(360deg)}}@media(max-width:700px){.pbadge{width:50px;height:50px;font-size:10px}}
.c.pano:hover .pbadge{background:rgba(255,255,255,.34);border-color:#fff;transform:translate(-50%,-50%) scale(1.06)}

/* ---------------------------------------------------------------- controls
   Every background below is stated explicitly, including on :hover. The parent theme
   paints `button:hover{background-color:#CC3366}`, and a rule that sets only colour
   and border lets that pink through — which is exactly what happened on the chips. */

/* Sidebar beside the wall on desktop; a horizontal strip below ~1100px, where a rail
   would eat a third of the width that the images need. */
/* The rail is inset from the left, the wall is not inset from the right. The old
   inset was the page gutter (72px), which pushed the filters into the middle of
   nowhere while the images they filter ran off the edge. */
/* The site's `section{padding-block:clamp(78px,10vw,128px)}` is right for a pf-band of
   prose and wrong here: the wall IS the page, and 128px of white between the hero and
   the first frame reads as a loading gap. */
.pf{display:grid;grid-template-columns:212px minmax(0,1fr);gap:clamp(18px,2vw,32px);
    align-items:start;padding-left:clamp(16px,2.2vw,34px);padding-right:0;
    padding-block:clamp(14px,1.6vw,26px) clamp(30px,4vw,60px)}
/* ...and the line above has been silently losing the cascade since it was written.
   `<section class="pf">` is also matched by the prototype's
   `section:not([class*="elementor"]){padding-block:clamp(78px,10vw,128px)}`, and :not()
   takes the specificity of its argument — so that rule is (0,1,1) against `.pf` at (0,1,0)
   and wins on specificity no matter what the source order is. The wall opened on 128px of
   white instead of the intended 25.6px. Restate it at (0,1,1) and the tie breaks our way
   on source order, because this sheet is appended after the prototype's.
   padding-block ONLY: widening `.pf` itself would also outrank the <=1100px rule below and
   put the 34px left inset back on the wall on every phone. */
section.pf{padding-block:clamp(14px,1.6vw,26px) clamp(30px,4vw,60px)}
/* Five filter groups are taller than a laptop viewport, and a sticky rail that
   overflows just loses its bottom rows — including Clear filters. Scroll inside it. */
.pf-side{position:sticky;top:calc(var(--head-h) + 15px);display:flex;flex-direction:column;gap:20px;
         padding:4px 6px 24px 0;min-width:0;
         max-height:calc(100vh - 116px);overflow-y:auto;overscroll-behavior:contain;
         scrollbar-width:thin;scrollbar-color:var(--hair) transparent}
.pf-side::-webkit-scrollbar{width:5px}
.pf-side::-webkit-scrollbar-thumb{background:var(--hair);border-radius:3px}
.pf-side::-webkit-scrollbar-track{background:transparent}
.fgroup{display:flex;flex-direction:column;gap:4px;min-width:0}
/* The parent theme sets h3 from the Elementor kit as `.elementor-kit-5 h3`, which
   is one specificity point above a bare `.fg-t` — the rail's labels came out at
   heading size. Scoping to .pf-side wins without an !important. */
.pf-side .fg-t{margin:0 0 4px;font-size:11px;font-weight:700;letter-spacing:.13em;
      line-height:1.3;text-transform:uppercase;color:var(--muted)}
.f{display:flex;align-items:center;gap:9px;width:100%;text-align:left;
   border:1px solid transparent;background:transparent;border-radius:8px;cursor:pointer;
   padding:7px 10px;font-family:var(--sans);font-size:13.5px;font-weight:600;
   color:var(--body);transition:.16s}
.fi{width:15px;height:15px;flex:0 0 15px;opacity:.62}
.ff{width:15px;flex:0 0 15px;font-size:12.5px;line-height:1;text-align:center;
    font-style:normal}
.f span:not(.ff){flex:1 1 auto;min-width:0}
.f i{font-style:normal;font-size:11.5px;color:var(--muted);
     font-variant-numeric:tabular-nums}
/* :hover AND :focus, every time. The parent theme's reset paints BOTH halves of
   button:hover/button:focus solid #CC3366; our components defended hover and forgot
   focus, so every chip flashed pink on click and stayed pink until focus moved. */
.f:hover,.f:focus{background:var(--grey);color:var(--ink)}
.f:hover .fi,.f:focus .fi{opacity:1}
.f.on:focus{background:var(--ink);color:#fff}
.f:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.f.on{background:var(--ink);border-color:var(--ink);color:#fff}
.f.on .fi{opacity:1}
.f.on i{color:rgba(255,255,255,.62)}
.f[disabled]{opacity:.3;cursor:not-allowed;background:transparent}
/* The long tail of markets, folded away until asked for. */
.fgroup .extra{display:none}