/* Self-hosted web fonts: the latin subsets Google Fonts serves, kept local so
   nothing render-blocking comes from a third party and the CSP can stay tight.
   Source Sans 3 is one variable file covering 400-700. */
@font-face{font-family:Oxygen;font-style:normal;font-weight:400;font-display:swap;src:url(fonts/oxygen-400.woff2) format("woff2")}
@font-face{font-family:Oxygen;font-style:normal;font-weight:700;font-display:swap;src:url(fonts/oxygen-700.woff2) format("woff2")}
/* Setronics: the brand heading face (converted from the supplied OTFs,
   renamed internally; public-use font). Regular and Bold. */
@font-face{font-family:Setronics;font-style:normal;font-weight:400;font-display:swap;src:url(fonts/setronics-400.woff2) format("woff2")}
@font-face{font-family:Setronics;font-style:normal;font-weight:700;font-display:swap;src:url(fonts/setronics-700.woff2) format("woff2")}
@font-face{font-family:"Source Sans 3";font-style:normal;font-weight:400 700;font-display:swap;src:url(fonts/source-sans-3.woff2) format("woff2")}
/* ==========================================================================
   Setronics — site stylesheet
   Palette and type sampled from setronics.com; layout rebuilt as static HTML.
   ========================================================================== */

:root{
  --red:#dd3333; --red-dark:#b32626;
  --navy:#05263e; --ink:#252626; --body:#59595b; --mute:#babdbf;
  --band:#f0f2f7; --rule:#e4e6ea; --cell-rule:#e4e1df;
  /* Sampled from the animated logo's square progression - brand colour that
     existed in the mark but had never made it into the interface. */
  --gold:#fab20b; --gold-2:#fbc64b; --gold-3:#fcd57a; --gold-4:#fddd92;
  --shell:1180px;
  --pad-section:clamp(2.2rem,4.6vw,3.4rem);
  --radius:6px;
  --shadow:0 1px 2px rgba(5,38,62,.05),0 8px 24px -12px rgba(5,38,62,.18);
}

*{box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}
}
body{margin:0;background:#fff;color:var(--body);
  font-family:"Source Sans 3","Source Sans Pro",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  font-size:17px;line-height:1.7;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
h1,h2,h3,h4,h5{font-family:Setronics,Oxygen,"Trebuchet MS",Verdana,sans-serif;color:var(--ink);font-weight:400;line-height:1.2;margin:0;text-wrap:balance}
/* Oxygen at 400 read tentative at display sizes. 700 with slightly negative
   tracking gives the top of the hierarchy authority; card and list headings
   stay at 400 so the two levels are told apart by weight, not just size. */
/* Large headings take the Regular cut - the face is sturdy enough that Bold at
   these sizes overwhelms the page. Bold stays on small titles (cards, footer). */
h1,.section-head h2,.cat-head h2,.hero h1,.pagehead h1,.cta h2{font-weight:400;letter-spacing:0}
p{margin:0}
p + p{margin-top:1rem}
a{color:var(--red);text-decoration:none}
a:hover{text-decoration:underline}
img{max-width:100%;height:auto}
:where(a,button,input,select,textarea,summary):focus-visible{outline:2px solid var(--red);outline-offset:3px}
.shell{width:min(100% - 2.5rem,var(--shell));margin-inline:auto}
.narrow{max-width:74ch}
.skip{position:absolute;left:-9999px}
.skip:focus{left:1rem;top:1rem;z-index:99;background:#fff;padding:.6rem 1rem;box-shadow:0 2px 10px rgba(0,0,0,.2)}
.visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---------- utility bar ---------- */
.util{background:var(--red);color:#fff;font-size:.92rem}
.util .shell{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem 1.5rem;padding:.6rem 0}
.util a{color:#fff;display:inline-flex;align-items:center;min-height:24px}
.util a[aria-current]{border-bottom:2px solid #fff;padding-bottom:2px}
.util .social{display:flex;gap:.5rem;margin-right:auto}
.util .social a{padding:.3rem;margin:-.3rem 0;min-width:24px;justify-content:center}
.util svg{width:15px;height:15px;fill:currentColor;display:block}

/* ---------- header ---------- */
.site-head{position:sticky;top:0;z-index:40;background:#fff;border-bottom:1px solid var(--rule)}
.site-head .shell{display:flex;align-items:center;gap:1rem 2rem;padding:1.15rem 0}
.brand{display:block;line-height:0}
.brand:hover{text-decoration:none}
/* The source art is 653x184, so displaying it around 190px wide gives roughly
   3x pixel density - crisp on retina. width/height attributes stay intrinsic
   so the aspect ratio is reserved before the image loads (no layout shift). */
.brand img{display:block;width:100%;height:auto;max-width:min(190px,46vw)}
/* Top menu, dropdown items and the phone Menu button share the heading face. */
.site-nav,.nav-toggle{font-family:Setronics,Oxygen,"Trebuchet MS",sans-serif}
.site-nav{margin-left:auto;display:flex;align-items:center;gap:.5rem 1.9rem;font-size:1rem}
.site-nav > a,.site-nav > .has-sub > a,.site-nav > .has-sub > button{color:var(--ink);background:none;border:0;padding:0;
  font:inherit;cursor:pointer;display:inline-flex;align-items:center;gap:.35rem;white-space:nowrap}
.has-sub{display:inline-flex;align-items:center;gap:.3rem}
/* The caret is its own control, so it needs a real target of its own - the
   glyph is 9px, well under the 24x24 minimum for a tappable control. The
   negative margin keeps the visual spacing tight without shrinking the target. */
.sub-toggle{display:inline-flex;align-items:center;justify-content:center;
  min-width:26px;min-height:26px;padding:0;margin-inline:-.35rem}
/* Light the section while any of its pages is open. */
.has-sub[data-section] > a{color:var(--red)}
.site-nav a:hover,.site-nav button:hover{color:var(--red);text-decoration:none}
.site-nav [aria-current="page"]{color:var(--red);box-shadow:inset 0 -2px 0 var(--red)}
.has-sub{position:relative}
.has-sub > button svg{width:9px;height:9px;fill:currentColor;transition:transform .18s ease;display:block}
.has-sub > button[aria-expanded="true"] svg{transform:rotate(180deg)}
.has-sub > .sub{position:absolute;top:calc(100% + .9rem);left:-1rem;min-width:250px;background:#fff;border:1px solid var(--rule);
  box-shadow:var(--shadow);padding:.5rem 0;display:none;z-index:50;border-radius:var(--radius);overflow:hidden}
.has-sub > .sub[data-open]{display:block}
/* The panel sits .9rem below the button. That gap is outside .has-sub, so a
   pointer crossing it fires mouseleave and shuts the menu before it can be
   used. This transparent strip bridges the gap as part of the panel. */
@media (min-width:961px){
  .has-sub > .sub::before{content:"";position:absolute;left:0;right:0;top:-1.1rem;height:1.1rem}
}
.has-sub > .sub a{display:block;padding:.5rem 1.2rem;color:var(--ink);font-size:.94rem}
.has-sub > .sub a:hover{background:var(--band);color:var(--red);text-decoration:none}
.nav-toggle{display:none;margin-left:auto;background:none;border:1px solid var(--rule);border-radius:2px;
  padding:.5rem .7rem;cursor:pointer;color:var(--ink);align-items:center;gap:.5rem;font:inherit;font-size:.85rem}
.nav-toggle svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2}

/* ---------- hero ---------- */
.hero{position:relative;background:var(--navy) center/cover no-repeat;color:#fff;padding:clamp(4rem,11vw,8rem) 0;text-align:center;isolation:isolate}
/* Background carousel - four slides crossfading on an 8s cadence, matching the
   WordPress hero. Pure CSS: each slide runs the same 32s loop offset by 8s, so
   there is no JS, nothing to initialise and nothing to go wrong if it fails. */
.hero-slides{position:absolute;inset:0;z-index:-2;overflow:hidden}
.hero-slide{position:absolute;inset:0;background:center center no-repeat;opacity:0;
  animation:heroFade 32s infinite;
  background-size:cover}

/* Showing the whole banner and never re-cropping it are the same problem: give
   the hero the artwork's own 1400:577 ratio and `cover` fits exactly, so every
   slide is fully visible edge to edge with nothing cut off. It scales with the
   window, but uniformly - the framing never changes.
   Below 1000px that ratio would leave the band too short for the headline, so
   the hero goes back to a normal padded block and the image crops instead. */
@media (min-width:1000px){
  .hero{aspect-ratio:1400/577;display:grid;place-items:center;padding-block:0}
}
.hero-slide:nth-child(1){animation-delay:0s}
.hero-slide:nth-child(2){animation-delay:8s}
.hero-slide:nth-child(3){animation-delay:16s}
.hero-slide:nth-child(4){animation-delay:24s}
@keyframes heroFade{
  0%{opacity:0}      4%{opacity:1}      25%{opacity:1}
  29%{opacity:0}     100%{opacity:0}
}
/* Anyone who has asked for less motion gets the first slide, held still. */
@media (prefers-reduced-motion:reduce){
  .hero-slide{animation:none}
  .hero-slide:nth-child(1){opacity:1}
}
.hero::before{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(5,38,62,.55),rgba(5,38,62,.68));z-index:-1}
.hero h1{color:#fff;font-size:clamp(2.1rem,6vw,3.5rem);letter-spacing:.01em}
.hero p{max-width:62ch;margin:1.2rem auto 0;color:rgba(255,255,255,.88);font-size:clamp(1.02rem,2.1vw,1.2rem)}
.hero .btnrow{margin-top:2rem}

/* ---------- page title band ---------- */
.pagehead{background:var(--band);border-bottom:1px solid var(--rule);padding:clamp(1.5rem,3vw,2.1rem) 0;text-align:center}
.pagehead h1{font-size:clamp(1.85rem,4.2vw,2.45rem)}
.pagehead .kicker{color:var(--red-dark);letter-spacing:.18em;text-transform:uppercase;font-size:.76rem;font-weight:600;margin-bottom:.5rem}
.pagehead p{max-width:68ch;margin:.8rem auto 0}
/* The band is a title strip, not a hero: the rule under the heading sits
   tighter here than the one used to separate content sections. */
.pagehead .divider{margin:.7rem auto 0}
.pagehead .divider:last-child{margin-bottom:0}

/* ---------- generic section ---------- */
.section{padding:var(--pad-section) 0}
.section.band{background:var(--band)}
.section-head{text-align:center;margin-bottom:clamp(1.8rem,4vw,2.6rem)}
/* When the head is the whole section (home About band) nothing follows it,
   so its bottom margin would stack onto the section padding. */
.section-head:last-child{margin-bottom:0}
.section-head h2{font-size:clamp(1.6rem,4vw,2.25rem)}
.section-head p{max-width:70ch;margin:1rem auto 0}
/* The logo animates a run of gold squares that resolve into the red wordmark.
   That progression is the most distinctive thing the brand owns, so the section
   divider reuses it rather than being an anonymous rule. */
.divider{width:50px;height:5px;border:0;margin:1.15rem auto 1.35rem;background-repeat:no-repeat;background-size:5px 5px;
  background-image:linear-gradient(var(--gold-4),var(--gold-4)),linear-gradient(var(--gold-3),var(--gold-3)),
    linear-gradient(var(--gold-2),var(--gold-2)),linear-gradient(var(--gold),var(--gold)),
    linear-gradient(var(--red),var(--red)),linear-gradient(var(--red),var(--red));
  background-position:0 0,9px 0,18px 0,27px 0,36px 0,45px 0}

/* ---------- cards ---------- */
.cards{list-style:none;margin:0;padding:0;display:grid;gap:1.5rem;
  grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
/* Six paragraph-length cards at the default 260px track fall into a ragged
   4 + 2. A wider track gives 3 + 3 and lets the prose set on a readable measure. */
.cards-3{grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}
@media (min-width:1000px){.cards-3{grid-template-columns:repeat(3,1fr)}}
.card{background:#fff;border:1px solid var(--rule);border-radius:var(--radius);overflow:hidden;padding:1.7rem 1.5rem;display:flex;flex-direction:column;gap:.7rem;
  transition:border-color .18s ease,box-shadow .18s ease,transform .18s ease}
.card:hover{border-color:var(--red);box-shadow:var(--shadow);transform:translateY(-2px)}
/* Cards on white sections take the band tint so they read as a surface rather
   than an outline; on grey band sections they stay white for the same reason.
   Hover lifts a tinted card to white so the movement has a colour cue too. */
.section:not(.band) .card{background:var(--band)}
.section:not(.band) .card:hover,.section:not(.band) .card:focus-within{background:#fff}
/* A hairline that widens from the left edge on hover - the same left-to-right
   reveal the logo uses, at card scale. */
.card::before{content:"";position:absolute;left:-1px;top:-1px;height:3px;width:0;background:var(--red);
  transition:width .22s ease}
.card:hover::before,.card:focus-within::before{width:calc(100% + 2px)}
.card h3{font-size:1.18rem}
.card p{font-size:.97rem}
/* Icon and title share a line: at three-up the stacked icon spent a lot of
   vertical space on decoration, and sitting it beside the heading turns it into
   a label you scan. It aligns to the heading's first line, not the block's
   centre, so multi-line titles stay tidy. */
.card{display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:.8rem;align-content:start}
.card-ico{grid-column:1;width:30px;height:30px;color:var(--red);margin-top:.15rem}
.card h3{grid-column:2;align-self:start}
.card p,.card .more,.card > :not(.card-ico):not(h3){grid-column:1/-1}
/* Cards built without an icon keep the heading on the full width. */
.card:not(:has(.card-ico)) h3{grid-column:1/-1}
/* Linked cards get a single arrow on the heading rather than a repeated
   "Learn more" row; it nudges on hover so the card still feels actionable. */
.card:has(a) h3::after{content:"\2192";margin-left:.4em;color:var(--red);
  display:inline-block;transition:transform .18s ease}
.card:has(a):hover h3::after,.card:has(a):focus-within h3::after{transform:translateX(4px)}
.card a::after{content:"";position:absolute;inset:0}
.card{position:relative}

/* "Open" cards (Services page): no box. A large outlined icon sits above a
   dark title, then the copy, then a red action link - the whole tile is still
   one link via the h3 anchor's ::after overlay. */
.cards.open{gap:2.6rem clamp(1.5rem,4vw,3.5rem)}
.section:not(.band) .cards.open .card,.cards.open .card{background:transparent;border:0;border-radius:0;
  overflow:visible;padding:0;box-shadow:none;transform:none;display:flex;flex-direction:column;gap:.85rem}
.cards.open .card::before{display:none}
.cards.open .card-ico{width:54px;height:54px;margin:0 0 .35rem}
.cards.open .card-ico .ico{stroke-width:1.35}
.cards.open .card h3{font-size:1.4rem;font-weight:400}
.cards.open .card h3 a{color:var(--ink)}
.cards.open .card h3::after{content:none}
.cards.open .card p{margin:0;color:var(--body);font-size:1.03rem}
.cards.open .card .more{margin-top:auto;font-weight:600;color:var(--red-dark);font-size:1.03rem}
.cards.open .card .more::after{content:"\2192";margin-left:.4em;display:inline-block;transition:transform .18s ease}
.cards.open .card:hover .more,.cards.open .card:focus-within .more{text-decoration:underline}
.cards.open .card:hover .more::after,.cards.open .card:focus-within .more::after{transform:translateX(4px)}
.cards.open .card:hover h3 a,.cards.open .card:focus-within h3 a{color:var(--ink);text-decoration:none}

/* ---------- feature rows ---------- */
/* Matches the live site's service list: a 63px icon column holding a small
   mark, with the text starting immediately beside it. The original does this
   with float + overflow:hidden; grid gets the same geometry without the
   clearing problems, and keeps the icon and text aligned to a shared baseline. */
.rows{display:grid;gap:clamp(1.6rem,3vw,2rem);--row-icon:48px;--row-gap:15px}
.row{display:grid;gap:1rem var(--row-gap);grid-template-columns:minmax(0,1fr);align-items:start;
  padding-bottom:clamp(1.6rem,3vw,2rem);border-bottom:1px solid var(--rule)}
.rows .row:last-child{border-bottom:0;padding-bottom:0}
@media (min-width:800px){
  .row{grid-template-columns:var(--row-icon) minmax(0,1fr)}
}
.row .icon .ico{width:40px;height:40px}
/* The service mark at the head of its own page. Floated so the opening
   sentence sets beside it and the copy then closes back under it, the way a
   magazine sets an opening ornament - rather than the mark sitting on a line
   of its own with the text pushed below. */
.row-ico{float:left;width:52px;height:52px;color:var(--red);margin:.15rem 1.1rem .5rem 0}
/* The closing line has a red left rule, so it must never sit in the float's
   indent - it clears instead. */
.shell.split .close{clear:left}
/* No tinted tile here: the live site shows a bare 40px mark, and a filled
   square at this size would out-weigh the heading beside it. */
.row .icon{width:48px;display:flex;align-items:flex-start;justify-content:flex-start;
  color:var(--red);margin-top:2px}
.row h2{font-size:clamp(1.4rem,3.2vw,1.8rem);scroll-margin-top:5.5rem}
.row .tag{color:var(--red);font-size:.95rem;font-style:italic;margin-bottom:.9rem}
.row .close{margin-top:1.1rem;font-family:Oxygen,sans-serif;color:var(--ink);font-size:1.05rem;
  border-left:3px solid var(--red);padding-left:1rem}

/* ---------- benefit list ---------- */
.benefits{list-style:none;margin:1.4rem 0 0;padding:0;display:grid;gap:.75rem;
  grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
.benefits li{display:flex;gap:.75rem;align-items:flex-start;font-size:.99rem}
.benefits li::before{content:"";flex:none;width:18px;height:18px;margin-top:.32rem;border-radius:50%;
  background:var(--red) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m4 12.5 5.5 5.5L20 6.5'/%3E%3C/svg%3E") center/11px no-repeat}

/* ---------- jump nav ---------- */
.jump{padding-bottom:clamp(1.6rem,3.6vw,2.4rem)}
.jump ul{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;justify-content:center;gap:.6rem}
.jump a{display:inline-block;border:1px solid var(--rule);color:var(--body);
  padding:.42rem 1rem;font-size:.83rem;letter-spacing:.09em;text-transform:uppercase}
.jump a:hover{border-color:var(--red);color:var(--red);text-decoration:none}

/* ---------- partner logo grid ---------- */
.cat{padding:clamp(2.2rem,5vw,3.2rem) 0;scroll-margin-top:5.5rem}
.cat:nth-of-type(even){background:var(--band)}
.cat-head{text-align:center;margin-bottom:clamp(1.5rem,3.4vw,2.1rem)}
.cat-head h2{font-size:clamp(1.5rem,3.6vw,2.05rem)}
.cat-head .divider{margin:.85rem auto 1rem}
.cat-head .icon{width:46px;height:46px;border-radius:50%;background:var(--red);color:#fff;
  display:inline-flex;align-items:center;justify-content:center;margin-bottom:.9rem}
.cat-head .icon svg{width:23px;height:23px;fill:currentColor}
/* The rules between cells are drawn by each cell rather than by a coloured
   container showing through a 1px gap - with the container technique, a part
   final row leaves a block of bare grid colour where the missing cells are. */
.grid{list-style:none;margin:0;padding:0;display:grid;gap:0;
  background:#fff;border:1px solid var(--cell-rule);border-right:0;border-bottom:0;
  /* 260px gave 4 across the 1180px shell, 210 gave 5; 180 gives 6 and still
     collapses to 5/4/3/2/1 as the viewport narrows. Tighter tiles so the mark
     fills more of its cell instead of floating in whitespace. */
  grid-template-columns:repeat(auto-fill,minmax(180px,1fr))}
.cell{background:#fff;display:flex;align-items:center;justify-content:center;padding:.75rem .7rem;min-height:84px;
  box-shadow:inset -1px -1px 0 var(--cell-rule)}
/* Every logo ships on an identical 600x200 transparent canvas, pre-scaled for
   even optical weight, so the tile only has to size the canvas. Shown in the
   manufacturers' own colours: these are brand marks and partners expect them
   reproduced accurately. No blend mode - it alters colour over any non-white. */
.cell img{display:block;width:100%;max-width:160px;height:auto}

/* ---------- logo strip ---------- */
/* Manufacturer partners - a continuous marquee rather than a static grid, to
   match the carousel on the WordPress home page. It runs at that carousel's
   pace (one logo every ~4s) but scrolls continuously instead of stepping, so
   there is no library to load and nothing to initialise. Logos are shown in
   their own colours. */
/* No panel and no border: multiply blending drops the logos' white grounds out,
   so they sit straight on the band and the row reads as a passing ribbon of
   marks rather than a white slab pasted onto the section. The mask fades to
   transparent at both ends so logos enter and leave instead of being clipped. */
.logo-marquee{overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 10%,#000 90%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 10%,#000 90%,transparent)}
.strip{list-style:none;margin:0;padding:0;display:flex;width:max-content;
  animation:logoScroll 112s linear infinite}
.strip li{flex:0 0 auto;width:clamp(158px,21vw,226px);display:flex;
  align-items:center;justify-content:center;padding:.35rem 1.1rem;min-height:66px}
/* Sized by width, not height. Every mark is area-normalised inside its own
   canvas - 600x220 for the partner set the strip now shares, 600x186 for the
   six that appear here only - so one width gives the row even optical weight
   whichever canvas a logo came from. No blend mode: these tiles carry a real
   alpha channel, and multiply would shift the brand colours. */
.strip img{width:100%;max-width:191px;height:auto}
/* 191px is the ceiling, not an arbitrary stop: the Setronics mark in the
   header renders 190px wide, and a partner logo should never out-scale the
   brand whose page it sits on. */
@keyframes logoScroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
/* Let a visitor stop it to read a logo. */
.logo-marquee:hover .strip,.logo-marquee:focus-within .strip{animation-play-state:paused}
@media (prefers-reduced-motion:reduce){
  .strip{animation:none;width:auto;flex-wrap:wrap;justify-content:center}
  .strip .dup{display:none}
  .logo-marquee{-webkit-mask-image:none;mask-image:none}
}

/* The partners strip is a trust signal, not a destination: it earns a glance,
   not a screen. It gets its own tighter vertical rhythm so the eye moves from
   the executive team straight on to the testimonials. Everything here is
   scoped to .partners so the shared .section/.section-head rhythm that the
   other 32 pages depend on is untouched. */
.section.partners .section-head{margin-bottom:1.15rem}
.section.partners .section-head p{margin-top:.55rem}
.partners-more{text-align:center;margin-top:1rem}

/* ---------- team ---------- */
.team{list-style:none;margin:0;padding:0;display:grid;gap:2rem;grid-template-columns:repeat(auto-fit,minmax(290px,1fr))}
.team article{background:#fff;border:1px solid var(--rule);height:100%}
.team img{width:100%;aspect-ratio:1/1;object-fit:cover;object-position:center;display:block;background:var(--band)}
.team .txt{padding:1.5rem}
.team h3{font-size:1.3rem}
.team .role{color:var(--red);letter-spacing:.1em;text-transform:uppercase;font-size:.78rem;font-weight:600;margin:.35rem 0 .9rem}
.team p{font-size:.95rem}

/* ---------- testimonial carousel ---------- */
/* The track is just a scroll-snapping overflow container, so it works with no
   JS: swipe on touch, arrow keys once focused (hence tabindex on the region).
   The arrows are an enhancement site.js reveals. */
.carousel{position:relative}
.car-track{display:flex;gap:1.6rem;list-style:none;margin:0;padding:.25rem 0;
  overflow-x:auto;scroll-snap-type:x mandatory;scroll-behavior:smooth;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none;-ms-overflow-style:none}
.car-track::-webkit-scrollbar{display:none}
.car-track:focus-visible{outline:2px solid var(--red);outline-offset:3px}
.car-slide{flex:0 0 100%;scroll-snap-align:start}
@media (min-width:700px){.car-slide{flex-basis:calc((100% - 1.6rem) / 2)}}
@media (min-width:1050px){.car-slide{flex-basis:calc((100% - 3.2rem) / 3)}}
/* Stretch keeps every card the height of the tallest in view, so the row does
   not jump as quotes of different lengths scroll past. */
.car-slide figure{margin:0;height:100%;display:flex;flex-direction:column;
  background:#fff;border:1px solid var(--rule);border-radius:var(--radius);border-top:3px solid var(--red);
  padding:1.5rem 1.5rem 1.3rem}
.car-slide blockquote{margin:0;flex:1;font-size:1rem;line-height:1.55}
.car-slide blockquote p{margin:0}
.car-slide figcaption{margin-top:1.1rem;font-family:Oxygen,sans-serif;
  font-weight:700;font-size:.9rem;color:var(--ink)}
.car-btn{position:absolute;top:50%;transform:translateY(-50%);z-index:2;
  width:40px;height:40px;display:flex;align-items:center;justify-content:center;
  background:#fff;color:var(--ink);border:1px solid var(--rule);border-radius:50%;
  cursor:pointer;box-shadow:0 1px 4px rgba(0,0,0,.12)}
.car-btn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}
.car-btn:hover{background:var(--red);color:#fff;border-color:var(--red)}
.car-btn[disabled]{opacity:.3;cursor:default;box-shadow:none}
.car-btn[disabled]:hover{background:#fff;color:var(--ink);border-color:var(--rule)}
.car-prev{left:-20px}
.car-next{right:-20px}
.car-pause{position:static;transform:none;margin:.9rem auto 0;width:32px;height:32px}
.car-pause svg{width:14px;height:14px}
.car-pause .i-play{display:none}
.car-pause[data-paused="true"] .i-pause{display:none}
.car-pause[data-paused="true"] .i-play{display:block}
@media (max-width:1240px){.car-prev{left:4px}.car-next{right:4px}}
/* Below 700px a card is the full width of the track, so arrows floating over it
   sit on top of the quote. Drop them onto their own row underneath instead. */
@media (max-width:699px){
  /* The full-width track would otherwise stretch the button columns and fling
     them apart, so the buttons get content-sized columns with 1fr gutters
     either side to absorb the slack and centre the group. */
  .carousel{display:grid;grid-template-columns:1fr auto auto auto 1fr;
    align-items:center;gap:.8rem .7rem}
  .car-track{grid-row:1;grid-column:1 / -1;justify-self:stretch}
  .car-prev{grid-row:2;grid-column:2}
  .car-pause{grid-row:2;grid-column:3;margin:0}
  .car-next{grid-row:2;grid-column:4}
  .car-btn{position:static;transform:none}
}
@media (prefers-reduced-motion:reduce){.car-track{scroll-behavior:auto}}

/* ---------- quotes ---------- */
.quotes{columns:2 330px;column-gap:1.7rem;margin:0;padding:0}
.quotes .quote{position:relative;margin:0 0 1.7rem;break-inside:avoid;background:#fff;
  border:1px solid var(--rule);padding:2.4rem 1.6rem 1.5rem;border-radius:var(--radius);
  transition:border-color .18s ease,box-shadow .18s ease}
/* An open quote set in the brand gold, sitting behind the text rather than
   indenting it. Decorative only - the <blockquote> already carries the
   semantics, so this must never reach the accessibility tree. */
.quotes .quote::before{content:"\201C";position:absolute;left:1rem;top:.1rem;
  font:700 3.6rem/1 Georgia,'Times New Roman',serif;color:var(--gold);opacity:.42;
  pointer-events:none}
.quotes .quote:hover{border-color:var(--mute);box-shadow:0 2px 14px rgb(5 38 62 / .07)}
.quotes blockquote{margin:0;font-size:.98rem}
.quotes blockquote p + p{margin-top:.7rem}
/* The claim the card is making, sized to be read at a glance. */
.quotes .pull{margin:0;color:var(--ink);font-size:1.06rem;line-height:1.5;font-weight:600}
/* Progressive disclosure: the full quote stays available but never competes
   with the claim above it. */
.quotes details{margin-top:.9rem}
.quotes summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;
  gap:.4rem;color:var(--red);font-family:Oxygen,sans-serif;font-size:.85rem;font-weight:700;
  letter-spacing:.04em;padding:.35rem 0;min-height:24px}
.quotes summary::-webkit-details-marker{display:none}
.quotes summary::after{content:"\203A";transform:rotate(90deg);transition:transform .18s ease;
  font-size:1.1rem;line-height:1}
.quotes details[open] summary::after{transform:rotate(-90deg)}
.quotes summary:hover,.quotes summary:focus-visible{text-decoration:underline}
.quotes details p{margin-top:.8rem;font-size:.95rem}
/* Name in ink, role in grey: one line of hierarchy instead of a bold run-on. */
.quotes figcaption{margin-top:1.15rem;padding-top:.9rem;border-top:1px solid var(--rule);
  font-family:Oxygen,sans-serif;font-size:.9rem}
.quotes figcaption b{display:block;color:var(--ink);font-weight:700}
.quotes figcaption span{display:block;color:var(--body);font-weight:400;font-size:.86rem;
  margin-top:.15rem}

/* ---------- trust ---------- */
.trust{border-top:1px solid var(--rule);background:#fff;padding:clamp(2rem,4.4vw,2.8rem) 0}
.trust ul{list-style:none;margin:0;padding:0;display:grid;gap:1.6rem;grid-template-columns:repeat(4,1fr)}
.trust li{display:flex;align-items:center;gap:.9rem;justify-content:center}
.trust svg{width:32px;height:32px;flex:none;stroke:var(--red);fill:none;stroke-width:1.5}
/* Every inline icon on the site is drawn on one 24 grid with one stroke. */
.ico{display:block;width:100%;height:100%;fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;stroke-linejoin:round}
.trust b{display:block;font-family:Oxygen,sans-serif;color:var(--ink);font-weight:700;font-size:1rem;line-height:1.25}
.trust span{font-size:.88rem;color:var(--body)}
/* Breakpoints sit after the base .trust li rule so their justify-content wins. */
@media (max-width:820px){.trust ul{grid-template-columns:repeat(2,1fr);gap:1.4rem 1rem}.trust li{justify-content:flex-start}}
/* 399px = the point where .grid logo cells (minmax 180px) collapse to one per row inside the 2.5rem-padded shell */
@media (max-width:399px){.trust ul{grid-template-columns:1fr;gap:1.1rem}}

/* ---------- buttons + cta ---------- */
.btnrow{display:flex;flex-wrap:wrap;gap:.8rem;justify-content:center}
.btn{display:inline-block;background:var(--red);color:#fff;padding:.78rem 1.7rem;font-weight:600;font-size:.9rem;
  letter-spacing:.09em;text-transform:uppercase;border:0;cursor:pointer;font-family:inherit;transition:background .18s ease,color .18s ease}
/* Primary buttons stay in the brand on hover. --red-dark was already in the
   palette for this and had never been used; it darkens enough to register as
   feedback without dropping the button out of the brand into near-black. */
.btn:hover{background:var(--red-dark);color:#fff;text-decoration:none}
.btn.ghost{background:transparent;color:var(--red-dark);box-shadow:inset 0 0 0 1px currentColor}
.btn.ghost:hover{background:var(--red);color:#fff;box-shadow:none}
.cta{background:var(--red);color:#fff;padding:clamp(2.2rem,4.8vw,3rem) 0;text-align:center}
.cta h2{color:#fff;font-size:clamp(1.4rem,3.4vw,1.9rem)}
.cta p{margin:.6rem auto 1.4rem;max-width:56ch;color:#fff}
.cta .btn{background:#fff;color:var(--red)}
.cta .btn:hover{background:var(--ink);color:#fff}
.cta .btn.ghost{background:transparent;color:#fff;box-shadow:inset 0 0 0 1px rgba(255,255,255,.7)}
.cta .btn.ghost:hover{background:#fff;color:var(--red);box-shadow:none}
/* The ghost button's red-on-navy in the hero fell far below AA. On any dark
   ground the outline button goes white. */
.hero .btn.ghost{color:#fff;box-shadow:inset 0 0 0 1px rgba(255,255,255,.7)}
.hero .btn.ghost:hover{background:#fff;color:var(--navy);box-shadow:none}

/* ---------- forms ---------- */
.form-grid{display:grid;gap:1.1rem;grid-template-columns:repeat(auto-fit,minmax(240px,1fr))}
.field{display:flex;flex-direction:column;gap:.4rem}
.field.full{grid-column:1/-1}
.field label{font-family:Oxygen,sans-serif;color:var(--ink);font-size:.88rem;letter-spacing:.05em}
.field .req{color:var(--red)}
.field input,.field select,.field textarea{font:inherit;font-size:1rem;color:var(--ink);background:#fff;
  border:1px solid var(--rule);padding:.7rem .85rem;border-radius:2px;width:100%}
.field textarea{min-height:150px;resize:vertical}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--red);outline:none;box-shadow:0 0 0 3px rgba(221,51,51,.12)}
.form-note{font-size:.86rem;color:var(--body);margin-top:1rem}
/* The form is the one thing on these pages a visitor has to act on, so it gets
   a surface of its own. The contact details beside it stay as plain content -
   the difference in weight is what marks one as the task and one as reference. */
.form-card{background:#fff;border:1px solid var(--rule);border-radius:var(--radius);box-shadow:var(--shadow);
  padding:clamp(1.4rem,3.2vw,2.2rem)}
.form-card h2{font-size:1.35rem}
.split{display:grid;gap:clamp(2rem,5vw,3.5rem);grid-template-columns:minmax(0,1fr)}
@media (min-width:900px){.split{grid-template-columns:minmax(0,1.25fr) minmax(0,1fr)}}
.info-list{list-style:none;margin:1.4rem 0 0;padding:0;display:grid;gap:1.1rem}
.info-list li{display:flex;gap:.9rem;align-items:flex-start}
.info-list svg{width:20px;height:20px;flex:none;margin-top:.35rem;stroke:var(--red);fill:none;stroke-width:1.7}
.info-list b{display:block;font-family:Oxygen,sans-serif;color:var(--ink)}

/* ---------- pdf embed ---------- */
.pdf-frame{width:100%;height:min(80vh,900px);border:1px solid var(--rule);background:var(--band)}
.pdf-actions{margin-top:1.2rem;display:flex;flex-wrap:wrap;gap:.8rem;justify-content:center}

/* ---------- footer ---------- */
.foot{background:var(--navy);color:#c6cdd4;padding:clamp(2.6rem,5vw,3.6rem) 0 1.6rem;font-size:.95rem}
.foot .cols{display:grid;gap:2rem clamp(1.5rem,4vw,3rem);grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
.foot h2,.foot h3{color:#fff;font-size:1.2rem;font-weight:400;letter-spacing:.02em;margin-bottom:.35rem}
.foot h2::after,.foot h3::after{content:"";display:block;width:26px;height:2px;background:rgba(255,255,255,.35);margin:.5rem 0 .8rem}
.foot h3 + h3,.foot ul + h3{margin-top:1.6rem}
.foot ul{list-style:none;margin:0 0 .4rem;padding:0;display:grid;gap:.44rem}
.foot li{display:flex;gap:.6rem;align-items:flex-start}
.foot li::before{content:"";width:5px;height:5px;background:#7f8f9c;flex:none;margin-top:.62rem}
.foot a{color:#c6cdd4}
.foot a:hover{color:#fff}
.foot .contact li::before{display:none}
.foot .contact svg{width:15px;height:15px;stroke:var(--red);fill:none;stroke-width:1.7;flex:none;margin-top:.4rem}
.legal{border-top:1px solid rgba(255,255,255,.13);margin-top:2.4rem;padding-top:1.2rem;
  display:flex;flex-wrap:wrap;gap:.5rem 1.4rem;justify-content:space-between;font-size:.86rem;color:#8fa0ad}
.legal p{margin:0}

/* ---------- responsive nav ---------- */
/* Larger utility type needs tighter spacing before it wraps to a second row. */
@media (max-width:900px){
  .util .shell{gap:.35rem 1rem;font-size:.86rem}
}
@media (max-width:960px){
  .nav-toggle{display:inline-flex}
  .site-nav{position:absolute;top:100%;left:0;right:0;background:#fff;border-bottom:1px solid var(--rule);
    box-shadow:var(--shadow);flex-direction:column;align-items:stretch;gap:0;margin:0;padding:.5rem 0;display:none}
  .site-head{position:relative}
  .site-nav[data-open]{display:flex}
  .site-nav > a{padding:.8rem 1.25rem;width:100%;justify-content:space-between}
  /* Stacked nav: the label takes the row, the caret sits at its end. */
  .site-nav > .has-sub{display:flex;justify-content:space-between;align-items:stretch;flex-wrap:wrap;gap:0}
  .site-nav > .has-sub > a{flex:1;padding:.8rem 1.25rem}
  .site-nav > .has-sub > .sub-toggle{padding:.8rem 1.25rem}
  .has-sub > .sub{flex-basis:100%}
  .site-nav [aria-current="page"]{box-shadow:inset 3px 0 0 var(--red)}
  .has-sub > .sub{position:static;border:0;box-shadow:none;background:var(--band);min-width:0;padding:.25rem 0}
  .has-sub > .sub a{padding-left:2.25rem}
}
@media (max-width:640px){
  /* The six utility links wrapped onto three lines, so roughly 100px of red
     band pushed every page down before any content appeared. Held on one line
     that scrolls sideways instead: the links stay reachable and the bar costs
     one row. */
  .util .shell{font-size:.85rem;gap:0 1.1rem;flex-wrap:nowrap;overflow-x:auto;
    scrollbar-width:none;-ms-overflow-style:none}
  .util .shell::-webkit-scrollbar{display:none}
  .util a{white-space:nowrap}
  .util .social{margin-right:.5rem;gap:.8rem}
  .quotes{columns:1}
}

@media (max-width:560px){
  /* Side-by-side buttons wrapped to different widths and read as a ragged
     stack. Full width on one axis is tidier and gives a bigger tap target. */
  .btnrow{flex-direction:column;align-items:stretch}
  .btnrow .btn{text-align:center;width:100%}
  /* Footer links sat about 5px apart, well under a comfortable touch target. */
  .foot ul{gap:.55rem}
  .foot li::before{margin-top:.85rem}
  .foot a{display:inline-block;padding:.2rem 0}
}
/* Touch devices: link lists in the footer and the sibling rail get a 24px
   minimum hit area (WCAG 2.5.8) without changing the type size. */
@media (max-width:640px){
  .aside-links a{display:inline-block;padding:.2rem 0}
  .foot .contact a{display:inline-block;padding:.2rem 0}
}
@media print{
  .util,.jump,.site-nav,.nav-toggle,.cta,.crumb,.pdf-frame{display:none}
  .site-head{position:static;border:0}
  .foot{background:#fff;color:#000}
  .cat,.card,.row{break-inside:avoid;background:#fff!important}
  .quote{break-inside:avoid}
  /* A closed <details> hides its body, so force every testimonial open on
     paper rather than printing nine one-line cards. */
  .quotes summary{display:none}
  .quotes details > *{display:block!important}
}

/* Line-card download link on the Our Partners page head. */
.pagehead .pdf{margin-top:1.5rem;font-size:.9rem}
.pagehead .pdf a{display:inline-flex;align-items:center;gap:.5rem;border:1px solid var(--rule);
  color:var(--body);padding:.5rem 1.1rem;letter-spacing:.06em;text-transform:uppercase;font-size:.82rem;background:#fff}
.pagehead .pdf a:hover{border-color:var(--red);color:var(--red);text-decoration:none}
.pagehead .pdf svg{width:15px;height:15px;stroke:var(--red);fill:none;stroke-width:1.7}

/* ---------- article aside ---------- */
.aside{display:grid;gap:1.4rem;align-content:start}
@media (min-width:900px){.aside{position:sticky;top:6.5rem}}
.aside-card{border:1px solid var(--rule);border-radius:var(--radius);padding:1.5rem 1.4rem;background:#fff}
.aside-card.accent{background:var(--band);border-color:transparent}
.aside-card h2{font-size:1.1rem;letter-spacing:.02em}
.aside-card h2::after{content:"";display:block;width:26px;height:2px;background:var(--red);margin:.6rem 0 .9rem}
.aside-card p{font-size:.95rem}
.aside-links{list-style:none;margin:0;padding:0;display:grid;gap:.55rem}
.aside-links a{color:var(--ink);font-size:.96rem}
.aside-links a:hover{color:var(--red);text-decoration:none}
.aside-call{margin-top:.9rem;font-size:.88rem;color:var(--body)}
.close{font-family:Oxygen,"Trebuchet MS",sans-serif;color:var(--ink);font-size:1.05rem;
  border-left:3px solid var(--red);padding-left:1rem}

/* ---------- brochure: image + text features ---------- */
.framed{display:block;width:100%;height:auto;border:1px solid var(--rule)}
.features{display:grid;gap:clamp(2rem,4.5vw,3.2rem)}
.feature{display:grid;gap:1.4rem clamp(1.5rem,4vw,3rem);align-items:center}
@media (min-width:820px){
  .feature{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  /* Alternate the image side so the column does not read as a rigid list. */
  .feature:nth-child(even) .feature-img{order:2}
}
.feature-img img{display:block;width:100%;height:auto;border:1px solid var(--rule);aspect-ratio:1200/427;object-fit:cover}
/* Product cut-outs sit on the page rather than in a frame: no border, no
   forced crop, and a little breathing room so they do not touch the text. */
.feature-img.product img{border:0;aspect-ratio:auto;object-fit:contain;padding:.5rem;
  max-width:390px;margin-inline:auto}
.feature-txt h2{font-size:clamp(1.35rem,3vw,1.7rem)}
/* Product strapline under a feature heading - same voice as .row .tag. */
.feature-txt .tagline{color:var(--red);font-size:.95rem;font-style:italic;margin-bottom:.7rem}

/* Pull quote and values line carried over from the printed brochure. */
.values{font-family:Oxygen,"Trebuchet MS",sans-serif;color:var(--red);letter-spacing:.06em;
  font-size:1.05rem;margin-top:1.6rem}
.pull{margin:1.2rem auto 0;max-width:34ch;font-family:Oxygen,"Trebuchet MS",sans-serif;
  color:var(--ink);font-size:clamp(1.15rem,2.6vw,1.45rem);line-height:1.4;quotes:"\201C" "\201D"}
.pull::before{content:open-quote}
.pull::after{content:close-quote}

/* Capability blocks inside a solution page's main column. */
.caps{display:grid;gap:1.3rem;margin-top:1.3rem}
.cap{border-left:3px solid var(--rule);padding-left:1.1rem}
.cap h3{font-size:1.05rem;margin-bottom:.3rem}
.cap p{font-size:.97rem}

/* Per-category line card download, under each category heading. */
.cat-dl{margin-top:.9rem;font-size:.85rem}
.cat-dl a{display:inline-flex;align-items:center;gap:.5rem;border:1px solid var(--rule);background:#fff;
  color:var(--body);padding:.45rem 1rem;letter-spacing:.06em;text-transform:uppercase;font-size:.78rem}
.cat-dl a:hover{border-color:var(--red);color:var(--red);text-decoration:none}
.cat-dl svg{width:14px;height:14px;stroke:var(--red);fill:none;stroke-width:1.7}

/* SMART photography is 700-1200px originals; hold the display width down so
   nothing renders below ~1.9x and looks soft on a retina screen. */
.smart-shot img{max-width:430px;margin-inline:auto;display:block;width:100%;height:auto}

/* ---------- video embed ---------- */
/* YouTube embed on topic pages (cannabis). Sized by the column, held at 16:9
   so nothing jumps when the player loads; privacy-enhanced domain. */
.video-embed{margin:1.8rem 0 0;border:1px solid var(--rule);background:var(--band)}
.video-embed iframe{display:block;width:100%;aspect-ratio:16/9;height:auto;border:0}
/* Full-bleed band under the contact split: the map runs edge to edge. */
.map-band{border-top:1px solid var(--rule);background:var(--band)}
.map-embed iframe{display:block;width:100%;height:clamp(300px,38vw,460px);border:0}
/* Anti-spam honeypot: real visitors never see it, bots fill it in. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
[data-status][data-kind="error"]{color:var(--red-dark)}
