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

/* The rating cluster in the footer. Deliberately NOT .client-rating: that component is
   drawn for a light band, its rules live in the page-gated components sheet which loads
   after this one, and at equal specificity it won every property — `Rated 4.9` computed
   to var(--ink) on a var(--dark) footer, i.e. black on black. Standalone rules instead.
   `.foot-rating .hero-avatars img` is (0,2,1) so it also clears the bare
   `.hero-avatars img` rule at (0,1,1). */
/* "See our reviews" is coming out everywhere: the plan is to link the Clutch profile
   from the rating itself. Hidden rather than deleted so the markup and the data-proof
   hooks stay intact for that swap. */
.rl-more{display:none}@media(max-width:1040px){
  .timeline{grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:44%;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:14px;-webkit-overflow-scrolling:touch}
  .timeline .step{scroll-snap-align:start}
  .timeline .step:not(:last-child)::after{display:none}}@media(max-width:760px){
  .vs-cols{grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:84%;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:12px;-webkit-overflow-scrolling:touch}
  .vs-cols>.vs-card{scroll-snap-align:start}}@media(max-width:700px){
  .cardgrid.four{grid-template-columns:none!important;grid-auto-flow:column;grid-auto-columns:74%;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:12px;-webkit-overflow-scrolling:touch}
  .cardgrid.four>.mini{scroll-snap-align:start}
  .timeline{grid-auto-columns:80%}}@media(max-width:900px){
  .cardgrid.ind{grid-template-columns:repeat(3,1fr);grid-auto-flow:row;grid-template-rows:none;grid-auto-columns:auto;overflow-x:visible;gap:14px 10px;padding-bottom:0}
  .cardgrid.ind .mini.svc{flex-direction:column;text-align:center;gap:10px;padding:14px 8px}
  .cardgrid.ind .mini.svc .svc-img{width:100%;height:auto;max-width:104px}
  .cardgrid.ind .mini.svc .svc-body{text-align:center}
  .cardgrid.ind .mini.svc h3{font-size:14px;line-height:1.2}
  .cardgrid.ind .mini.svc p{display:none}
  /* Collapsed, not display:none: the link's ::after is what makes the tile clickable,
     and overflow:hidden does not clip it because its containing block is the card. */
  .cardgrid.ind .mini.svc .svc-more{height:0;margin:0;padding:0;overflow:hidden}}
/* reveal */
.rv{opacity:0;transform:translateY(20px);transition:opacity 1s ease,transform 1s cubic-bezier(.2,.7,.2,1)}
.rv.in{opacity:1;transform:none}@media(prefers-reduced-motion:reduce){.rv{opacity:1;transform:none;transition:none}.card img,.mini.svc .svc-img,.mini.why .why-img{transition:none}}

/* live colour switcher */
body.mono .btn-p{background:var(--ink);border-color:var(--ink)}
body.mono .btn-p:hover{background:#000;border-color:#000}
body.mono .ba-knob svg{color:var(--ink)}
.note{position:fixed;right:12px;bottom:12px;max-width:330px;z-index:210;background:var(--white);border:1px solid var(--hair);color:var(--muted);font-size:10.5px;letter-spacing:.02em;line-height:1.4;text-align:center;padding:9px 13px;border-radius:6px;box-shadow:0 6px 24px rgba(0,0,0,.1)}
/* TESTIMONIAL / client story (reviews page). Unscoped on purpose (RULE 0). Named .tst because .rv is the scroll-reveal hook.
   The country/role filters are CSS only: :has() scopes each rule to .wrap-wide, so the radio
   inputs, the chip labels and .tst-list can live anywhere in the markup instead of needing to
   stay flat siblings of the inputs.
   A new country needs its id (tf-xx) added to the selector lists below and one hide rule. */
section.tst-sec{padding-top:clamp(28px,2.8vw,52px)}
.tst-head{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:clamp(24px,3vw,52px);align-items:stretch;margin:12px 0 clamp(30px,3.6vw,44px)}
.tst-head-txt{max-width:640px;min-width:0}
.tst-head h1{font-size:clamp(38px,4.9vw,58px);font-weight:650;letter-spacing:-0.024em;line-height:1.0;margin:0 0 18px}
.tst-head-txt p{font-size:19px;color:var(--muted);max-width:48ch;line-height:1.55;margin:0}
/* margin-block only: the sitewide mobile rule (below) bleeds .client-rating to the
   viewport edge and repositions it with margin-left, so a plain `margin` shorthand here
   would stomp that left offset and shove the whole row (with it) off-screen right --
   that was the "Rated 4.9... See o[ur reviews]" cutoff and the misalignment with the H1. */
.tst-head-txt .client-rating{margin-block:16px 22px}
/* Stats stay pinned to the top (level with the H1), the 8-logo grid sinks to the bottom
   of the row, level with the left column's subtext -- .tst-head is stretched so this
   column has the full row height to distribute into. The whole block left-aligns to its
   own column (it already reads as "the right side" just by being in the right column --
   it doesn't also need to hug the page's outer edge). Desktop only (>900px) gets the
   4-column grid; below that .tst-head collapses to one column and this reverts to the
   sitewide bled/scrollable .trust-stats/.client-logos treatment (see the max-width:900px
   block far above), same as every other page. */
/* The block itself (as a whole) right-aligns to match the page edge the header's own
   right-side content (nav, "GET A QUOTE") touches -- same idea as the H1 column hugging
   the left edge. Content INSIDE each row/cell still starts from the left (see
   justify-items/justify-content below on .client-logos), just the outer block sits right. */
.tst-side{min-width:0;display:flex;flex-direction:column;align-items:flex-end;text-align:right}
/* Each cell's height is set inline per mark (see reviews.py) -- a square icon like
   Brookfield/Perkins/Larsen needs real height to read at the same visual weight as a wide
   wordmark, since its rendered WIDTH shrinks in lockstep with height. 32px is only the
   fallback for a cell nobody tuned. */
.tst-side .client-logos .logo-cell{height:32px;align-items:center}
/* max-width is a fixed px, not 100%: at mobile .logo-cell has no width of its own (flex:0 0
   auto from the sitewide bled/scroll rule), so "100%" was circular against an
   indeterminate parent and silently gave up constraining anything -- object-fit:contain
   still reported height:100% via getComputedStyle, but painted at the SVG's full natural
   size, cap-height easily 100px+ for an 11:1 wordmark like Foster's. */
/* max-height:none overrides the sitewide .logo-cell img{max-height:36px} rule (line ~467,
   used by the normal trust-band logos elsewhere on the site) -- without it, every hero
   logo taller than 36px silently painted at 36px regardless of the per-mark inline
   height, which is why Brookfield/Perkins looked stuck "too small" no matter what height
   was set on the cell. Larsen (an inline <svg>, not <img>) was never hit by that rule,
   which is why it alone rendered at its intended size. */
.tst-side .client-logos .logo-cell img{height:100%;width:auto;max-width:150px;max-height:none;object-fit:contain}
.tst-side .client-logos .logo-cell svg{height:100%;width:auto;max-width:150px}
/* width:100% is NOT desktop-only. The sitewide bled/scroll rule positions these rows with
   margin-left:calc(50% - var(--bleed)/2), and that 50% resolves against THIS box -- so the
   maths only lands on the viewport edge while this box is full-width and centred. Under
   901px .tst-side switches to align-items:flex-start, which shrink-wrapped .clients to
   382px, and the logo row was flung 153px off the left edge with Foster sliced in half. */
.tst-side .clients{margin-top:0;padding-top:0;border-top:0;width:100%}@media(min-width:901px){
  /* Lost in the left-align rewrite: this is what actually pins stats to the top and
     lets the logo grid sink to the bottom of the stretched row. */
  .tst-side{justify-content:flex-end}
  /* Exactly 4 columns so 8 logos is always 2 clean rows, not a wrap that reflows
     differently at every width. minmax(0,1fr), not bare 1fr: a bare 1fr track still
     grows to its item's min-content size before sharing space equally, so the row was
     silently demanding ~500px of content (150+150+98+48 + gaps) inside a ~414px box and
     bleeding Perkins+Will/Larsen past the page's own right edge. minmax(0,..) forces
     genuinely equal columns; object-fit:contain then just shrinks each mark to fit. */
  /* Centred, not edge-aligned. The eight marks have wildly different proportions (a 48px
     square against a 132px wordmark), so pinning them to one edge made the gaps between
     the marks themselves read as random. Centring each in its own column puts the
     whitespace on both sides and the rhythm comes out even. */
  .tst-side .client-logos{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));column-gap:18px;row-gap:10px;justify-items:center;align-items:center;width:100%}
  .tst-side .client-logos .logo-cell{width:100%;min-width:0;justify-content:center}
  /* The cap has to be the COLUMN, not a fixed 150px. Below ~1200px the four columns are
     only ~90px wide, so a 150px-capped wordmark overhung its cell by 30px on each side
     and printed straight over its neighbours. 100% is safe here (unlike at mobile, where
     .logo-cell has no width of its own) because the cell is width:100% of a real track. */
  .tst-side .client-logos .logo-cell img,.tst-side .client-logos .logo-cell svg{max-width:100%}}
.tst-r{position:absolute;opacity:0;pointer-events:none;width:1px;height:1px}
.tst-filter{display:flex;flex-wrap:wrap;gap:8px}
.tst-chip{display:inline-flex;align-items:center;gap:8px;font-size:13.5px;font-weight:600;color:var(--ink);background:var(--white);border:1px solid var(--hair);border-radius:999px;padding:10px 15px;cursor:pointer;line-height:1;transition:background .15s,border-color .15s,color .15s}
.tst-chip:hover{border-color:var(--faint)}
.tst-chip .n{font-weight:500;color:var(--muted)}
.tst-chip .tst-flag{width:18px;height:13px}
.wrap-wide:has(#tf-all:checked) .tst-filters label[for=tf-all],.wrap-wide:has(#tf-no:checked) .tst-filters label[for=tf-no],.wrap-wide:has(#tf-uk:checked) .tst-filters label[for=tf-uk],.wrap-wide:has(#tf-fi:checked) .tst-filters label[for=tf-fi],.wrap-wide:has(#tf-ee:checked) .tst-filters label[for=tf-ee],.wrap-wide:has(#tr-all:checked) .tst-filters label[for=tr-all],.wrap-wide:has(#tr-architect:checked) .tst-filters label[for=tr-architect],.wrap-wide:has(#tr-developer:checked) .tst-filters label[for=tr-developer],.wrap-wide:has(#tr-agency:checked) .tst-filters label[for=tr-agency]{background:var(--ink);border-color:var(--ink);color:#fff}