/* =========================================================
   SV Security Services — site stylesheet
   Grid: 1180 frame · 40px margins · 12 cols · 20px gutters
   Type: 8 roles, 16px body floor
   Colour: navy structural · red reserved for action/escalation
   Red is NEVER text on navy (2.3:1). Pale blue is the dark-surface accent.
   ========================================================= */

/* ---------- tokens ---------- */
:root{
  --navy:#0b1b33;
  --navy-deep:#071223;
  --navy-hi:#12294a;
  --blue:#1b4fa0;
  --blue-pale:#7fa6e0;
  /* ONE accent red: #f01830, the mark's own, the colour of "Answerable to you."
     Measured against every surface on this site it is 3.8-4.3:1, which passes the
     3:1 threshold for rules, borders, icons, dots and headline-size text on all of
     them, and misses the 4.5:1 that small text needs on all of them. So it is used
     for exactly those roles, and small labels that used to be red are now ink or
     white rather than a second, weaker red.
     --red is a deeper shade of the same hue, kept only for solid fills that carry
     white text: white on #f01830 is 4.30 and fails, white on #c8102e is 5.88. */
  --accent:#f01830;
  --blue-wash:#e8eef7;
  --red:#c8102e;
  --red-hi:#e01536;

  --paper:#ffffff;
  --surface:#f5f7fa;
  --surface-2:#e9eef5;
  --line:#d3dbe6;
  --line-soft:#e7ecf3;

  --ink:#0b1b33;
  /* The old --ink-2 #41536e and --ink-3 #5c6d88 read as washed-out grey against
     the navy headings above them. Body copy now sits at near-full ink; only true
     metadata is stepped back, and only slightly. */
  --ink-2:#1c2c45;
  --ink-3:#3a4c66;

  --on-navy:#ffffff;
  --on-navy-2:#ffffff;
  --on-navy-3:rgba(255,255,255,.88);
  --rule-navy:rgba(255,255,255,.16);

  --ok:#1d6b45;
  --ok-bg:#e6f2ec;
  --err:#a3261b;
  --err-bg:#fbeceb;

  --sans:"Archivo",system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,Menlo,Consolas,monospace;

  /* type scale — 8 text roles, plus one display numeral for the stat figures */
  --fs-label:.8125rem;    /* 12 — uppercase labels only */
  --fs-caption:.9375rem; /* 14 — metadata, never sentences of prose */
  --fs-body:1rem;       /* 16 — reading floor */
  --fs-lead:1.125rem;   /* 18 */
  --fs-card:1.375rem;   /* 22 */
  --fs-section:2rem;    /* 32 */
  --fs-page:2.75rem;    /* 44 */
  --fs-hero:3.75rem;    /* 60 */

  /* spacing — three vertical values, by role */
  --s1:8px; --s2:16px; --s3:24px; --s4:32px; --s6:48px; --s8:64px; --s12:96px;

  --measure:68ch;
  --gut:24px;
  --padx:48px;
}

/* ---------- reset ---------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font:400 var(--fs-body)/1.65 var(--sans);
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block}
h1,h2,h3,h4{margin:0;font-weight:800;letter-spacing:-.025em;line-height:1.1;text-wrap:balance}
p{margin:0}
ul{margin:0;padding:0;list-style:none}
/* Links stay blue on purpose. Red is the error colour in the forms, and an inline
   link in the same red reads as something having gone wrong. Focus rings stay
   pale blue for the same reason: an accent-coloured ring disappears on accent-
   coloured controls. */
a{color:var(--blue);text-underline-offset:3px}
a:hover{color:var(--red)}
button{font:inherit}

::selection{background:var(--red);color:#fff}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:2px}
.navbar :focus-visible{outline-color:var(--blue-pale)}

.skip{position:absolute;left:-9999px;top:0;z-index:100;background:#fff;color:var(--navy);
  padding:12px 18px;font-weight:700}
.skip:focus{left:8px;top:8px}

/* ---------- layout ---------- */
.wrap{max-width:1440px;margin:0 auto;padding:0 var(--padx)}
.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--gut);align-items:start}
.c2{grid-column:span 2}.c3{grid-column:span 3}.c4{grid-column:span 4}
.c5{grid-column:span 5}.c6{grid-column:span 6}.c7{grid-column:span 7}
.c8{grid-column:span 8}.c9{grid-column:span 9}.c12{grid-column:span 12}

section{padding:var(--s12) 0}
section.band{padding:var(--s8) 0}
.sec-surface{background:var(--surface)}
.sec-navy{background:var(--navy);color:var(--on-navy)}
.sec-navy h2,.sec-navy h3{color:#fff}
/* --red, not --accent: this surface carries white body text, and white on
   #f01830 is 4.30 where white on #c8102e is 5.88. */
.sec-red{background:var(--red);color:#fff}
.sec-red h2,.sec-red h3{color:#fff}
.sec-red .lede,.sec-red p{color:#fff}
.sec-red .btn-white:hover{background:#fff;color:var(--red)}
.sec-red .btn-ghost-d:hover{background:rgba(255,255,255,.14)}

/* nothing reads past 68ch */
main p{max-width:var(--measure)}
/* .lede and .body-2 are both "the text under the heading" and now share a size,
   so a section does not change type size halfway down. */
.lede{font-size:var(--fs-lead);line-height:1.6;color:var(--ink-2);max-width:var(--measure)}
.sec-navy .lede,.sec-red .lede,.hero .lede{color:var(--on-navy-2)}
.body-2{font-size:var(--fs-lead);line-height:1.6;color:var(--ink-2);max-width:var(--measure)}
/* Paragraph rhythm. Every one of these gaps used to be set inline - 34 of them
   across nine pages, in five different sizes for the same job (10px, 12px, s2,
   s3). Cards that are flex/grid containers (.svc, .cred, .person) space their
   own children with gap and are deliberately not matched here; .spec is not a
   flex container, so it still needs the explicit step. */
main h2 + .lede{margin-top:var(--s3)}
main .lede + .body-2,main .body-2 + .body-2{margin-top:var(--s3)}
main h3 + .body-2{margin-top:10px}
/* .svc is a flex column with its own gap, so the rule above would stack a margin
   on top of it and double the space. Same reason .spec needs its own value. */
.svc h3 + .body-2{margin-top:0}
/* .spec is also a flex column with gap:10px. An earlier comment here claimed it
   was not, and the 10px margin that claim justified had been doubling the space
   under every .spec heading ever since. Zero: the gap already does it. */
.spec h3 + .body-2{margin-top:0}
.sec-navy .body-2,.hero .body-2{color:var(--on-navy-2)}

h1{font-size:var(--fs-page)}
h2{font-size:var(--fs-section)}
h3{font-size:var(--fs-card);font-weight:700}
h4{font-size:var(--fs-lead);font-weight:700;letter-spacing:-.01em}
.h-sm{font-size:var(--fs-lead);font-weight:700;letter-spacing:-.01em}

/* more space above a heading than below it */
.sec-head{margin-bottom:var(--s6)}
.sec-head p{margin-top:var(--s2)}

.label{font:500 var(--fs-label)/1.4 var(--sans);letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-3)}
.sec-navy .label,.sec-red .label,.hero .label{color:var(--on-navy-3)}
.caption{font-size:var(--fs-caption);color:var(--ink-3);line-height:1.55}

/* ---------- topbar + nav ---------- */
.topbar{background:var(--navy-deep);color:var(--on-navy-3)}
.topbar .wrap{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  min-height:40px;flex-wrap:wrap;padding-top:6px;padding-bottom:6px}
.topbar span{font:400 var(--fs-caption)/1.5 var(--mono)}
.topbar .hot{color:#fff}
.topbar a{color:var(--on-navy-3)}
.topbar a:hover{color:#fff}
/* Icon plus word: the glyph alone is a guessing game for anyone who does not
   recognise it, and the topbar has room for four more characters. */
.topbar .iglink{display:inline-flex;align-items:center;gap:6px;vertical-align:-3px}
.topbar .iglink svg{width:15px;height:15px;flex:none;
  stroke:currentColor;fill:none;stroke-width:1.6}
.topbar .iglink:hover svg{color:#fff}

.navbar{background:var(--navy);color:#fff;position:sticky;top:0;z-index:50;
  border-bottom:1px solid var(--rule-navy)}
.navbar .wrap{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  min-height:92px}
.brand{display:flex;align-items:center;gap:12px;text-decoration:none;color:#fff;flex:none}
/* Two-tone mark: ~15% of it is dark charcoal that vanishes on navy (1.3:1),
   so it needs a light chip. The chip is now genuinely white; the old JPEG
   carried a dirty grey background that read as a sticker on the navy bar. */
.brand img{width:68px;height:53px;object-fit:contain;background:#fff;padding:6px 8px}
.brand b{display:block;font:800 var(--fs-lead)/1.2 var(--sans);letter-spacing:-.005em;
  color:#fff}
.brand span{display:block;font:500 var(--fs-label)/1.4 var(--mono);letter-spacing:.05em;
  color:var(--on-navy-2)}
/* The separators carry the logo's red so the wordmark and the mark read as one
   lockup. They are punctuation, and the words either side are the content. */
.brand span i{font-style:normal;color:#fff}

.nav{display:flex;align-items:center;gap:var(--s4)}
.nav ul{display:flex;gap:var(--s3);align-items:center}
.nav a{color:var(--on-navy-2);text-decoration:none;font-size:var(--fs-caption);font-weight:500;
  padding:6px 0;border-bottom:2px solid transparent;transition:color .15s,border-color .15s}
.nav a:hover{color:#fff;border-bottom-color:var(--rule-navy)}
.nav a[aria-current="page"]{color:#fff;border-bottom-color:var(--accent)}
/* Must out-specify `.nav a` (0,1,1) or that rule strips the padding to 6px 0
   and the button collapses to a 29px sliver. */
.nav a.navcta{display:inline-flex;align-items:center;justify-content:center;gap:10px;
  background:var(--red);color:#fff;text-decoration:none;
  padding:0 22px;min-height:46px;border-bottom:0;
  font:700 var(--fs-body)/1 var(--sans);letter-spacing:.01em;
  white-space:nowrap;transition:background .15s,transform .12s}
.nav a.navcta:hover{background:var(--red-hi);color:#fff;border-bottom:0}
.nav a.navcta:active{transform:translateY(1px)}
.navcta .dot{width:7px;height:7px;border-radius:50%;background:#fff;flex:none}

/* The top utility bar is hidden below 680px, which took Instagram with it. On a
   phone it lives here instead, beside the menu button, so it is still reachable
   from the top of the page rather than only from the footer. Hidden above 680px
   because the utility bar already carries it there. */
.ignav{display:none;align-items:center;justify-content:center;
  width:44px;height:44px;flex:none;color:#fff;margin-left:auto;margin-right:10px}
.ignav svg{width:22px;height:22px;stroke:currentColor;fill:none;stroke-width:1.6}
.ignav:hover{color:var(--accent)}
.burger{display:none;background:none;border:1px solid var(--rule-navy);color:#fff;
  padding:10px;cursor:pointer;line-height:0}

/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;
  padding:15px 26px;font:700 var(--fs-body)/1 var(--sans);text-decoration:none;
  border:1px solid transparent;cursor:pointer;transition:background .15s,color .15s,border-color .15s}
.btn-red{background:var(--red);color:#fff}
.btn-red:hover{background:var(--red-hi);color:#fff}
.btn-white{background:#fff;color:var(--navy)}
.btn-white:hover{background:var(--blue-wash);color:var(--navy)}
.btn-navy{background:var(--navy);color:#fff}
.btn-navy:hover{background:var(--navy-hi);color:#fff}
.btn-ghost{border-color:var(--line);color:var(--ink);background:transparent}
.btn-ghost:hover{border-color:var(--navy);color:var(--navy);background:var(--surface)}
.btn-ghost-d{border-color:rgba(255,255,255,.34);color:#fff;background:transparent}
.btn-ghost-d:hover{border-color:#fff;background:rgba(255,255,255,.08);color:#fff}
.btn[disabled]{opacity:.5;cursor:not-allowed}
.btnrow{display:flex;flex-wrap:wrap;gap:12px}

.ic{width:18px;height:18px;flex:none;stroke:currentColor;fill:none;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round}
.ic-lg{width:26px;height:26px}
/* .ic strokes and does not fill; the WhatsApp mark is a solid glyph. */
.ic-solid{fill:currentColor;stroke:none}

/* ---------- hero ---------- */
.hero{background:var(--navy);color:#fff;overflow-x:clip}
.hero .grid{align-items:stretch}
.hero-copy{padding:var(--s8) 0 var(--s8)}
.hero h1{font-size:var(--fs-hero);line-height:1.02;letter-spacing:-.03em;margin-bottom:var(--s3)}
.hero h1 em{font-style:normal;color:var(--accent)}
.hero .lede{margin-bottom:var(--s6);max-width:52ch}
/* Dateline, not a badge. The old pill carried "Since 2018 / 150+ personnel",
   which the stats band restates 300px lower in far bigger type. Only the place
   was unique, so only the place stayed. The rule runs out to the column edge and
   lines up with the stats band, framing the headline between two horizontals. */
.dateline{max-width:none;display:flex;align-items:center;gap:16px;margin-bottom:var(--s4);
  font:500 var(--fs-caption)/1 var(--mono);letter-spacing:.14em;
  text-transform:uppercase;color:#fff;white-space:nowrap}
.dateline::after{content:"";flex:1 1 auto;height:1px;background:var(--rule-navy)}

.hero-media{position:relative;background:var(--navy-hi);display:flex;align-items:flex-end;
  min-height:560px;height:100%;
  margin-right:calc((100vw - min(100vw, 1440px)) / -2 - var(--padx))}

/* Three figures across the copy column.
   Equal thirds of a 7-column parent land on no column edge - measured at 1440 the
   old three-up started at x=48, 314 and 579 while the grid's own edges are at 48,
   161, 273, 386, 499. So the block is a 7-column subgrid of its parent and each
   figure spans 2, which puts the three left edges exactly on columns 1, 3 and 5.
   The accent rule over each one rhymes with the credentials strip below the hero,
   so the two blocks read as the same kind of object. */
.stats{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--gut)}
.stat{grid-column:span 2;border-top:2px solid var(--accent);padding-top:var(--s3)}
.stat b{display:block;font:800 3rem/1 var(--sans);letter-spacing:-.04em;color:#fff;
  font-variant-numeric:tabular-nums}
/* The "+" and the wordmark separators are the only places the accent lands on
   something small enough to need 4.5:1, and it measures 4.00 on navy. They are
   punctuation, so they go white rather than pull in a second, lighter red - the
   accent still reads loudly from the rules above each figure. */
.stat b i{font-style:normal;font-size:1.5rem;color:#fff;margin-left:2px}
.stat span{display:block;margin-top:10px;font:500 var(--fs-label)/1.4 var(--mono);
  letter-spacing:.1em;text-transform:uppercase;color:#fff}

/* ---------- credentials ----------
   Four claims a buyer checks before calling. Not cards: a rule over each, the
   claim in full-strength ink, the proof under it. The rule is red because these
   are the page's assurances, which is the role red carries everywhere here. */
.creds{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--gut)}
.cred{border-top:2px solid var(--accent);padding-top:var(--s3);display:grid;gap:10px;
  align-content:start}
.cred .ic{color:var(--accent)}
.cred b{font:700 var(--fs-body)/1.3 var(--sans);color:var(--ink)}
.cred p{font-size:var(--fs-caption);color:var(--ink-2);line-height:1.55;max-width:30ch}
.sec-navy .cred b{color:#fff}
.sec-navy .cred p{color:var(--on-navy-2)}

/* ---------- photographs ----------
   Uniform 4:3 tiles so the grid never gaps, and the eighth cell is a fact rather
   than a filler image. Sources are 1400px and 700px, chosen by srcset. */
.gallery{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--gut)}
/* ---------- photographs ----------
   Three tile widths, not one square. Forcing every photograph to 4:3 cost up to
   57% of the picture - the portraits lost their subjects' heads and feet. Each
   photograph now goes in the tile closest to its own shape: span 3 for portraits,
   span 4 for 4:3 landscapes, span 8 for the very wide one. Worst crop is 17% and
   the average is 10%. Rows still total 12 columns, so every tile starts and ends
   on a grid edge like everything else on the site.

   The caption sits under the photograph rather than over it: as an overlay it was
   white text on a gradient that fades to transparent at its top edge, and half
   these photographs have white walls or bright sky exactly there - measured at
   1.17:1. The accent rule above it is the same device .cred, .vow and .stat use. */
.gallery{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--gut)}
.gallery figure{margin:0;grid-column:span 3;background:var(--surface-2);
  border:1px solid var(--line);overflow:hidden;display:flex;flex-direction:column;
  transition:border-color .15s}
.gallery figure.w4{grid-column:span 4}
.gallery figure.w8{grid-column:span 8}
.gallery figure.w12{grid-column:span 12}
.gallery img{display:block;width:100%;height:300px;object-fit:cover;
  transition:transform .4s ease}
.gallery figure:hover img{transform:scale(1.03)}
.gallery figure:hover{border-color:var(--accent)}
.gallery figcaption{flex:1;padding:11px 13px;border-top:2px solid var(--accent);
  background:#fff;font:500 var(--fs-label)/1.45 var(--mono);letter-spacing:.03em;
  color:var(--ink)}
/* The figure tile is built like a photograph tile - a fixed-height body with a
   caption under it - so it measures the same as its neighbours in any row. */
.gallery .fact{background:var(--navy);border-color:var(--navy)}
.gallery .fact-body{height:300px;display:flex;flex-direction:column;
  justify-content:center;padding:var(--s3)}
.gallery .fact b{font:800 2.75rem/1 var(--sans);letter-spacing:-.035em;color:#fff;
  font-variant-numeric:tabular-nums}
.gallery .fact b i{font-style:normal;font-size:1.35rem;color:#fff;margin-left:2px}
.gallery .fact figcaption{background:var(--navy);color:#fff}

/* A single photograph used as a page's lead image. */
.shot{margin:0;border:1px solid var(--line);background:var(--surface-2)}
/* One shape for every service photo. The sources are a mix of portrait and
   landscape (0.57 to 1.78), and at native ratio the portrait ones rendered
   994px and 1308px tall against 285px on security - the column beside them
   was left half empty. Centred crop: the subjects sit mid-frame in both. */
.shot img{display:block;width:100%;height:auto;
  aspect-ratio:4/3;object-fit:cover;object-position:center}
.shot figcaption{padding:12px 14px;font:500 var(--fs-caption)/1.5 var(--mono);
  color:var(--ink-3);border-top:1px solid var(--line)}
.hero-media .shot{position:absolute;inset:0;border:0;background:none}
/* object-position is for the tablet range only. There the box is landscape and
   this portrait source is cropped top and bottom - centred, the window lands on
   the chests. Biased to 18% it keeps the faces. On desktop the box is portrait,
   the crop is horizontal, and the vertical value does nothing. */
.hero-media .shot img{width:100%;height:100%;aspect-ratio:auto;object-fit:cover;
  object-position:50% 18%}

/* which of the three companies delivers a given service */
.svc-by{font:500 var(--fs-label)/1 var(--mono);letter-spacing:.09em;
  text-transform:uppercase;color:var(--ink-3)}

/* ---------- cards / panels ---------- */
.panel{background:#fff;border:1px solid var(--line);padding:var(--s4)}
.grid > [class^="c"]{align-self:stretch}
/* A photo row is two columns of unequal content. The photo sets the row height on
   one page and the text does on another, and whichever came up shorter was left
   carrying the whole difference underneath it - 249px under the facilities text at
   1440, 253px under the manpower photo at 1024. Centring splits that difference, so
   the short side sits against the tall one instead of trailing a void. Scoped to a
   column whose only child is the photo, which is the hero exempt: its figure is
   wrapped in .hero-media, not a direct child of the column. */
.grid:has(> [class^="c"] > .shot:only-child) > [class^="c"]{align-self:center}
.panel:only-child,.person:only-child,.quote:only-child{height:100%}
.grid > [class^="c"] > .svc:only-child{height:100%}
/* No height here. The grid stretches the column that holds a card, so height:100%
   resolves against the stretched column - and where a column holds three cards,
   each one became the full column height and the stack overflowed by two thirds of
   it, running down through the footer. A card only fills its column when it is the
   only thing in it, which is the rule below. Third time this bug class has appeared
   in this stylesheet: see .contactcard in revision 4 and .spec in revision 5. */
.svc{display:flex;flex-direction:column;gap:var(--s2);
  background:#fff;border:1px solid var(--line);padding:var(--s4);text-decoration:none;color:inherit;
  transition:border-color .15s,transform .15s}
/* a.svc is 0,1,1 and out-specified the uniform card hover further up, so the
   linked cards were still going to navy while every other card went to the
   accent. Same border colour, and the lift stays because these are clickable. */
a.svc:hover{border-color:var(--accent);transform:translateY(-2px);color:inherit}
/* Same card, laid on its side: used where the column is narrow and the text is
   one line, so a stacked card would waste most of its height. */
.svc-row{flex-direction:row;align-items:flex-start;gap:var(--s3);padding:var(--s3);height:auto}
.svc-row .ic-lg{flex:none;margin-top:3px}
.svc-row h3{font-size:var(--fs-lead);margin-bottom:10px}
.svc-row p{font-size:var(--fs-caption)}
/* A static card: same surface, no link affordance, for pages the reader is on. */
.svc-static{cursor:default;gap:10px}
.svc-static:hover{transform:none;box-shadow:none}
.svc-static h3{font-size:var(--fs-lead)}
.svc-static p{font-size:var(--fs-body);color:var(--ink-2)}
/* On a tinted section the card needs to stay the lighter surface to read as a card. */
.sec-surface .svc-static{background:#fff}
.svc .ic-lg{color:var(--accent)}
.svc h3{font-size:var(--fs-card)}
.svc p{color:var(--ink-2);font-size:var(--fs-body)}
.svc .more{margin-top:auto;padding-top:var(--s2);display:inline-flex;align-items:center;gap:8px;
  font-weight:700;font-size:var(--fs-caption);color:var(--red)}

.g2{display:grid;grid-template-columns:1fr 1fr;gap:var(--gut)}
.g1{display:grid;grid-template-columns:1fr;gap:var(--s3)}
@media (max-width:680px){.g2{grid-template-columns:1fr}}
.scope{display:grid;gap:10px}
/* A scope list is a block like any other: after a heading or a paragraph it takes
   the same step paragraphs take after each other. Without this the list jammed
   straight against the paragraph above it. .spec .scope and .shot + .scope are
   more specific and keep their own tighter and wider gaps. */
main h2 + .scope,main h3 + .scope,main p + .scope{margin-top:var(--s3)}
.shot + .scope{margin-top:var(--s4)}
.scope li{display:grid;grid-template-columns:20px 1fr;gap:10px;align-items:start;
  color:var(--ink-2);font-size:var(--fs-body)}
.scope .ic{width:16px;height:16px;margin-top:5px;color:var(--accent)}
.sec-navy .scope li,.hero .scope li{color:var(--on-navy-2)}
.sec-navy .scope .ic,.hero .scope .ic{color:var(--accent)}

/* deploy steps — numbering earns its place: this is a sequence */
.step{border-top:1px solid var(--rule-navy);padding-top:var(--s3)}
.step .n{font:700 var(--fs-caption)/1 var(--mono);color:#fff;
  letter-spacing:.1em;display:block;margin-bottom:var(--s2)}
.step h3{font-size:var(--fs-lead);margin-bottom:10px}
.step p{color:var(--on-navy-2);font-size:var(--fs-body)}

/* ---------- journey: static, everything visible ---------- */
.journey{display:grid;gap:0}
.jrow{display:grid;grid-template-columns:150px 28px 1fr;gap:var(--s3);
  grid-template-areas:"date mark body";
  padding:var(--s4) 0;align-items:start;position:relative}
.jdate{grid-area:date}.jmark{grid-area:mark}.jbody{grid-area:body}
.jdate{font:600 var(--fs-caption)/1.5 var(--mono);letter-spacing:.04em;color:var(--red);
  padding-top:2px}
/* one continuous rail, drawn behind the dots.
   align-self:stretch matters: the row is align-items:start, so without it the
   mark column collapses to the dot and the rail renders as a short stub. */
.jmark{position:relative;display:flex;justify-content:center;align-self:stretch}
.jmark::before{content:"";position:absolute;left:50%;margin-left:-1px;
  top:0;bottom:calc(var(--s4) * -2 - 10px);width:2px;background:var(--line)}
.jrow:first-child .jmark::before{top:14px}
.jrow:last-child .jmark::before{bottom:auto;height:14px}
.jdot{position:relative;z-index:1;width:16px;height:16px;border-radius:50%;
  background:var(--paper);border:3px solid var(--accent);margin-top:6px}
.jrow.on .jdot{background:var(--accent);border-color:var(--accent);width:20px;height:20px;margin-top:4px}
.jbody h3,.jbody h4{margin-bottom:10px}
.jbody p{color:var(--ink-2);max-width:60ch}
.jfig{display:flex;gap:var(--s4);flex-wrap:wrap;margin-top:12px}
.jfig div{font:500 var(--fs-caption)/1.4 var(--mono);color:var(--ink-3)}
.jfig b{display:block;font:800 var(--fs-card)/1.1 var(--sans);color:var(--navy);letter-spacing:-.02em}



/* ---------- team ---------- */
.person{background:#fff;border:1px solid var(--line);display:flex;flex-direction:column;height:100%}
/* height:auto is load-bearing. The width/height attributes on the <img> are
   presentational hints, and while height resolves from them aspect-ratio is
   ignored - the three director photos rendered 0.78, 1.10 and 0.59 instead of
   4:3. Same trap as .shot img. */
.person img{aspect-ratio:4/3;height:auto;object-fit:cover;width:100%;
  border-bottom:1px solid var(--line)}
.person .pbody{padding:var(--s3);display:flex;flex-direction:column;gap:12px;flex:1}
.person h3{font-size:var(--fs-lead)}
.person .role{font:500 var(--fs-label)/1.4 var(--mono);letter-spacing:.11em;text-transform:uppercase;
  color:var(--red)}
.person .quals{font-size:var(--fs-caption);color:var(--ink-3)}
.person p{font-size:var(--fs-body);color:var(--ink-2)}
.person .said{margin-top:auto;padding-top:var(--s3);border-top:1px solid var(--line-soft);
  font-size:var(--fs-body);font-style:italic;color:var(--ink)}

/* ---------- forms ---------- */
.form{display:grid;gap:var(--s3)}
.field{display:flex;flex-direction:column;gap:8px}
.field > label{font:600 var(--fs-caption)/1.4 var(--sans);letter-spacing:0;
  color:var(--ink)}
.field .req{color:var(--red)}
.field input,.field select,.field textarea{
  width:100%;padding:13px 14px;font:400 var(--fs-body)/1.4 var(--sans);color:var(--ink);
  background:#fff;border:1px solid var(--line);border-radius:0;transition:border-color .15s}
.field textarea{min-height:120px;resize:vertical}
.field input:hover,.field select:hover,.field textarea:hover{border-color:var(--ink-3)}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--navy);outline-offset:1px}
.field .hint{font-size:var(--fs-caption);color:var(--ink-3)}
.field .err{display:none;font-size:var(--fs-caption);color:var(--err);font-weight:500}
.field.invalid input,.field.invalid select,.field.invalid textarea{border-color:var(--err);
  background:var(--err-bg)}
.field.invalid .err{display:block}
.formrow{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3)}
.checks{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.check{display:flex;align-items:center;gap:10px;font-size:var(--fs-body);color:var(--ink-2);
  cursor:pointer}
.check input{width:24px;height:24px;accent-color:var(--accent);flex:none;padding:0;
  border:1px solid var(--line);cursor:pointer}
.check:hover{color:var(--ink)}
.formnote{font-size:var(--fs-caption);color:var(--ink-3);max-width:58ch}
.formstatus{display:none;padding:14px 16px;font-size:var(--fs-body);font-weight:500;
  border:1px solid transparent}
.formstatus.ok{display:block;background:var(--ok-bg);border-color:var(--ok);color:var(--ok)}
.formstatus.bad{display:block;background:var(--err-bg);border-color:var(--err);color:var(--err)}

/* ---------- contact ---------- */
.contactcard{border:1px solid var(--line);padding:var(--s3);background:#fff}
.contactcard dt{margin-bottom:8px}
.contactcard dd{margin:0}
.contactcard a{font:500 var(--fs-lead)/1.5 var(--mono);color:var(--navy);text-decoration:none;
  display:block;word-break:break-word}
.contactcard a:hover{color:var(--red)}
.contactcard a.small{font-size:var(--fs-body)}

/* Scoped to the contact card, not the whole section. It changes which desk's
   number and email are shown and nothing else - sitting full width above both
   columns, it read as though it also governed the enquiry form. */
/* The label was sitting straight on top of the control with nothing between them.
   It is the question the three buttons answer, so it gets the accent rule and
   real breathing room rather than being another grey caption. */
.desk-label{color:var(--ink);font-weight:600;display:flex;align-items:center;gap:10px;
  margin-bottom:var(--s3)}
.desk-label::after{content:"";flex:1 1 auto;height:2px;background:var(--accent)}
.deskswitch{display:grid;grid-template-columns:1fr;gap:1px;background:var(--line);
  border:1px solid var(--line)}
/* A button with no colour set takes the UA's pure black, which is the one colour
   on this site that is not in the palette. */
.deskswitch button{background:#fff;color:var(--ink);border:1px solid transparent;padding:16px 14px;cursor:pointer;text-align:left;
  transition:background .15s,color .15s}
.deskswitch button:hover{background:var(--surface)}
.deskswitch button:hover{border-color:var(--accent)}
.deskswitch button[aria-selected="true"]{background:var(--navy);color:#fff;
  box-shadow:inset 0 3px 0 0 var(--accent)}
.deskswitch b{display:block;font-size:var(--fs-body);font-weight:700}
.deskswitch span{display:block;margin-top:4px;font-size:var(--fs-caption);color:var(--ink-3)}
.deskswitch button[aria-selected="true"] span{color:var(--on-navy-3)}


/* ---------- careers language switch ---------- */
/* The language choice sits with the form now, not in the page header. It is not
   site navigation - it changes this one panel - and the point at which someone
   needs it is the point at which they start typing. */
.langpick{margin:calc(var(--s4) * -1) calc(var(--s4) * -1) var(--s4);
  padding:var(--s3) var(--s4);background:var(--navy);border-bottom:2px solid var(--accent)}
.langpick .label{color:#fff;margin-bottom:10px}

/* Five languages, not three. At max-content and nowrap the bar was 437px wide and
   ran 97px past a 375px viewport, putting the whole page into horizontal scroll.
   max-content keeps it tight to its buttons when they fit on one line; max-width
   makes it wrap when they do not, and flex:1 on the buttons makes the wrapped row
   fill its width instead of leaving a bare navy block beside the last one. */
.langbar{display:flex;flex-wrap:wrap;gap:1px;background:var(--rule-navy);
  border:1px solid var(--rule-navy);width:max-content;max-width:100%}
.langbar button{flex:1 1 auto;background:var(--navy);color:var(--on-navy-2);border:0;padding:11px 15px;
  font:600 var(--fs-caption)/1 var(--sans);cursor:pointer;transition:background .15s,color .15s}
.langbar button:hover{background:var(--navy-hi);color:#fff}
.langbar button[aria-pressed="true"]{background:#fff;color:var(--navy)}
[data-lang]{display:none}
[data-lang].show{display:block}

/* ---------- footer ---------- */
.footer{background:var(--navy-deep);color:var(--on-navy-2);padding-top:var(--s8)}
.footer .h-foot{font:600 var(--fs-label)/1.4 var(--mono);letter-spacing:.12em;
  text-transform:uppercase;color:#fff;margin-bottom:var(--s3)}
.footer a{color:var(--on-navy-2);text-decoration:none;font-size:var(--fs-body)}
.footer a:hover{color:#fff}
.footer li{margin-bottom:11px}
.footer .addr{font-size:var(--fs-body);line-height:1.7;max-width:34ch}
.footcos{display:grid;gap:var(--s3);margin-top:var(--s3)}
.footco b{display:block;font-size:var(--fs-body);color:#fff}
.footco a{font-family:var(--mono);font-size:var(--fs-caption)}
.social{display:inline-flex;align-items:center;gap:10px;margin-top:var(--s3);
  min-height:44px;font-family:var(--mono);font-size:var(--fs-caption)}
.social .ic{color:var(--accent)}
.social:hover .ic{color:#fff}
.footbottom{margin-top:var(--s8);border-top:1px solid var(--rule-navy);padding:var(--s3) 0;
  display:flex;justify-content:space-between;gap:var(--s3);flex-wrap:wrap;
  font:400 var(--fs-caption)/1.6 var(--mono);color:var(--on-navy-3)}
.footbottom a{font-size:var(--fs-caption);color:var(--on-navy-3)}

/* ---------- mobile action bar ---------- */
.actionbar{display:none;position:fixed;left:0;right:0;bottom:0;z-index:60;
  grid-template-columns:1fr 1fr;gap:1px;background:rgba(255,255,255,.2)}
.actionbar a{display:flex;align-items:center;justify-content:center;gap:9px;padding:16px;
  font:700 var(--fs-body)/1 var(--sans);text-decoration:none;color:#fff}
.actionbar .call{background:var(--red)}
.actionbar .wa{background:var(--navy)}

/* ---------- page header ---------- */
.pagehead{background:var(--navy);color:#fff;padding:var(--s8) 0}
.pagehead h1{font-size:var(--fs-page);margin-bottom:var(--s2)}
.pagehead p{color:var(--on-navy-2);max-width:var(--measure);font-size:var(--fs-lead)}
.crumb{font:400 var(--fs-caption)/1.5 var(--mono);color:var(--on-navy-3);margin-bottom:var(--s3)}
.crumb a{color:var(--on-navy-3)}
.crumb a:hover{color:#fff}

/* ---------- prose (legal pages) ---------- */
.prose{max-width:var(--measure)}
.prose h2{font-size:var(--fs-card);margin:var(--s6) 0 var(--s2)}
.prose h2:first-child{margin-top:0}
.prose p{margin-bottom:var(--s2);color:var(--ink-2)}
.prose ul{list-style:disc;padding-left:22px;margin-bottom:var(--s2);color:var(--ink-2)}
.prose li{margin-bottom:8px}

/* Email addresses and URLs are single unbreakable tokens. Inside a card they
   have 64px less room than they did as a plain column, and
   svmanpowersolution21@gmail.com is 30 characters - enough to push a 320px page
   into horizontal scroll. break-word only acts on words that would overflow. */
.caption,.svc p,.cred p,.footer .addr{overflow-wrap:break-word}

@media (max-width:560px){
  /* 32px of padding each side out of a 265px column is most of the card. */
  .svc,.svc-static{padding:var(--s3)}
}

@media (max-width:1024px){
  .creds{grid-template-columns:repeat(2,1fr);gap:var(--s4)}
  /* Below the full grid the three widths collapse to a plain two-up: at this size
     a span-8 tile would be almost the whole row on its own. */
  .gallery{grid-template-columns:repeat(2,1fr)}
  .gallery figure,.gallery figure.w4,.gallery figure.w8,
  .gallery figure.w12{grid-column:span 1}
  .gallery img,.gallery .fact-body{height:250px}
  /* Eight photographs tile evenly two-up; the ninth tile is the figure, so it
     takes the full width rather than sitting alone with an empty half beside it.
     figure.fact, not .fact: the tile also carries w4, and .gallery figure.w4 is
     0,2,1 where .gallery .fact is only 0,2,0. */
  .gallery figure.fact{grid-column:span 2}
  .gallery .fact-body{height:auto;padding:var(--s4) var(--s3);
    flex-direction:row;align-items:baseline;gap:var(--s3)}
}
@media (max-width:560px){
  .creds{grid-template-columns:1fr;gap:var(--s3)}
  .gallery{grid-template-columns:1fr}
  /* The fact tile spans 2 in the two-up layout above. Left at span 2 against a
     single explicit column it creates an implicit second track, and tiles
     auto-placed into that track came out 2px wide with a zero-width image -
     half the gallery invisible on a phone, with no overflow to give it away. */
  .gallery figure.fact{grid-column:span 1}
  .gallery img,.gallery .fact-body{height:280px}
  /* At one column each tile is its own row, so the fact tile no longer inherits
     the photographs' height from the grid and has to match it itself. */
  .gallery .fact b{font-size:1.75rem}
}

/* =========================================================================
   Text setting.

   Measured before this: 38 paragraphs across the site ended in a stub last
   line under a fifth of the column - that is the "messy line" feeling, and it
   is what text-wrap:pretty fixes, by letting the browser pull a word back
   rather than stranding one.

   Justification is applied from 768px up only. Measured line lengths are
   49-76 characters there, which justifies cleanly; on phones the same
   paragraphs run 31-41 characters, and justifying that short a measure opens
   visible gaps between words in every line. Hyphenation is on wherever text is
   justified, which is what keeps the word spacing even.
   ========================================================================= */
.prose p,.prose li,.lede,.body-2,main p,.vow p,.jbody p,.svc p,.step p,
.quote blockquote,.person p,.scope li{text-wrap:pretty}

@media (min-width:768px){
  /* Card columns run ~28 characters at desktop widths, which justifies into
     visible word gaps. Justification is for the wide prose measures only. */
  /* Justification survives only on the legal pages, which have the long
     paragraphs it needs. Everywhere else it kept producing the gaps it is meant
     to avoid: a two-line lede stretches its first line to the margin and leaves
     the second short, and hyphenation - the usual remedy - splits words across
     lines, which is worse. Leads and body copy are ranged left with
     text-wrap:pretty doing the work on the rag instead. */
  .prose p,.prose li{text-align:justify;hyphens:manual;-webkit-hyphens:manual}
  /* Anything inside a card is ranged left whatever class it carries. .body-2 is
     0,1,0 and appears inside these cards, so the reset has to out-specify it. */
  .svc p,.svc .body-2,.cred p,.cred .body-2,.step p,.person p,
  .quote blockquote,.contactcard p{text-align:left;hyphens:manual}
  /* Headings, pull quotes, labels, addresses and anything monospaced stay
     ranged left: they are display text, not running prose. */
  h1,h2,h3,h4,.label,.caption,.quote blockquote,.footer .addr,
  .crumb,.dateline,.motto{text-align:left;hyphens:manual}
}

/* ---------- responsive ---------- */
@media (max-width:1024px){
  :root{--fs-hero:3rem;--fs-page:2.25rem;--fs-section:1.75rem;--gut:20px;--padx:28px}
  .hero-media{margin-right:0}
  .hero-media{min-height:420px;margin-right:0}
  .c3,.c4,.c5{grid-column:span 6}
  /* A grid that holds a major column (c7/c8/c9) is a two-part split, not a card
     row. The major half goes full width at this size, so its partner has to as
     well - otherwise it is stranded at half width with the other half empty, which
     happened on every c8+c4, c7+c5 and c4+c8 pair across the site. Card grids
     (c3 x4, c4 x3, c6+c6) hold no major column and keep tiling two-up.
     :has() carries this; where it is unsupported the layout is the older one,
     which is untidy rather than broken. #contact keeps an explicit rule as the
     one case worth covering either way. */
  .grid:has(> .c7, > .c8, > .c9) > [class^="c"]{grid-column:span 12}
  #contact .c5{grid-column:span 12}
  .c7,.c8,.c9{grid-column:span 12}
  .hero .c7,.hero .c5{grid-column:span 12}
}
/* eight nav items plus a phone CTA stop fitting well before 1024 */
@media (max-width:1180px){
  .nav ul{display:none}
  /* media queries add no specificity, so this must match .nav a.navcta */
  .nav a.navcta{display:none}
  .burger{display:block}
  .navbar .wrap{position:relative}
  .nav.open{position:absolute;left:0;right:0;top:100%;background:var(--navy);
    border-bottom:1px solid var(--rule-navy);padding:var(--s3) 28px;z-index:2}
  .nav.open ul{display:grid;gap:var(--s2)}
  .nav.open a{font-size:var(--fs-lead);border-bottom:0}
}
@media (max-width:820px){
  .topbar .wrap{justify-content:center;text-align:center}
  .topbar .addr-line{display:none}
  .actionbar{display:grid}
  body{padding-bottom:56px}
  .navbar{position:static}
}
@media (max-width:680px){
  :root{--fs-hero:2.25rem;--fs-page:2rem;--gut:16px;--padx:20px}
  .c2,.c3,.c4,.c5,.c6,.c7,.c8,.c9{grid-column:span 12}
  .formrow,.checks{grid-template-columns:1fr}
  .jrow{grid-template-columns:1fr;gap:8px}
  .jmark{display:none}
  section{padding:var(--s8) 0}
}

/* small phones: the brand lockup has to be allowed to shrink */
@media (max-width:560px){
  .brand{flex:1 1 auto;min-width:0}
  .brand img{width:52px;height:41px}
  .brand b{font-size:var(--fs-caption)}
  .brand span span{display:none}
  .navbar .wrap{min-height:64px;gap:var(--s2)}
}

/* every tappable control clears the 44px touch minimum */
.burger{min-width:44px;min-height:44px;display:none;place-items:center}
@media (max-width:1180px){.burger{display:grid}}
.langbar button,.deskswitch button{min-height:44px}

@media (prefers-reduced-motion:reduce){
  *{transition:none!important;animation:none!important;scroll-behavior:auto!important}
}

@media print{
  .navbar,.topbar,.actionbar{display:none}
  body{color:#000}
}

/* ---------- interaction: a small, consistent lift ---------- */
/* Every card, clickable or not, answers the cursor the same way: the border goes
   to the accent red. Cards you can press also lift; cards you only read do not,
   because a lift promises something to click. */
.svc:hover,.svc-static:hover,.panel:hover,.cred:hover,.person:hover,
.quote:hover,.contactcard:hover,.gallery figure:hover,.vm-item:hover,
.vow:hover,.step:hover{border-color:var(--accent)}
.cred:hover,.vm-item:hover,.vow:hover,.step:hover{border-top-color:var(--accent)}

/* A lift is an affordance: only things you can actually click get one.
   .person and .quote are read, not pressed, so they stay put. */
.panel{
  transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease}
.panel:hover{transform:translateY(-3px);
  box-shadow:0 8px 22px -10px rgba(11,27,51,.30);border-color:var(--accent)}
a.svc:hover{box-shadow:0 10px 26px -12px rgba(11,27,51,.34)}
.btn{transition:background .15s,color .15s,border-color .15s,transform .18s ease,box-shadow .18s ease}
/* The buttons had the transform in their transition but nothing ever set one.
   They now lift on hover like the cards, and press back down on click. */
.btn:hover{transform:translateY(-2px)}
.btn-red:hover,.btn-navy:hover{box-shadow:0 10px 26px -12px rgba(11,27,51,.45)}
.btn-white:hover{box-shadow:0 10px 26px -12px rgba(0,0,0,.35)}
.btn:active{transform:translateY(0)}
.btn:active{transform:translateY(1px)}

/* ---------- timeline: the present state ----------
   TODAY was a gradient wash fading out to the right, which is the one emphasis
   device on this site that is not a card and not a rule. It is a card now, with
   the accent on top, so it matches .vow, .cred and .vm-item. */
.jfig{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s3)}
.jrow.on .jbody{background:#fff;border:1px solid var(--line);
  border-top:2px solid var(--accent);padding:var(--s3);transition:border-color .15s}
.jrow.on .jbody:hover{border-color:var(--accent)}
.jrow.on .jbody h3,.jrow.on .jbody h4{margin-bottom:var(--s3)}
.jfig b{color:var(--ink)}
@media (max-width:680px){
  .jfig{grid-template-columns:1fr 1fr}
  .jrow.on .jbody{padding:var(--s3) var(--s2)}
}

/* ---------- map ---------- */
.mapembed{width:100%;height:280px;border:1px solid var(--line);display:block;filter:grayscale(.2)}

/* ---------- containers, by role -------------------------------------------
   Refero/impeccable both flag "everything in a card" as the top AI tell.
   The system here is deliberate:
     .svc / form  -> a card, because you click it or type into it
     .person      -> a media block (photo + biography)
     .spec        -> an informational column: hairline rule, no box
   -------------------------------------------------------------------------- */
.spec{border-top:1px solid var(--line);padding-top:var(--s3);
  display:flex;flex-direction:column;gap:10px}
/* height:100% only when the column holds nothing else, otherwise it resolves
   against a row sized by a taller sibling column and pushes its neighbours out */
.grid > [class^="c"] > .spec:only-child{height:100%}
.spec > h3,.spec > h4{margin:0}
.spec p{color:var(--ink-2)}
.spec .scope{margin-top:2px}
.sec-navy .spec,.hero .spec{border-top-color:var(--rule-navy)}
.sec-navy .spec p{color:var(--on-navy-2)}
.sec-surface .spec{border-top-color:var(--ink-3)}
/* an informational column has nothing to press, so it does not lift */
.spec:hover{transform:none;box-shadow:none}

/* testimonials read as pull quotes rather than boxes */
/* Testimonial: the organisation is the proof, so it leads. The sector tag uses
   the same vocabulary as the client filter above, which tells a reader "this is
   a site like yours" instead of just "someone was pleased". */
/* align-self:stretch (not height:100%) so quotes of unequal length still land
   their attribution rows on a common baseline across the row. */
.quote{margin:0;align-self:stretch;background:transparent;border:0;
  border-top:2px solid var(--navy);
  padding:var(--s3) 0 0;display:flex;flex-direction:column;gap:var(--s3)}

/* The client logo sits above the attribution, not instead of it: the organisation
   name stays as text for search and for anyone who cannot see the mark. Height is
   fixed so wordmarks of different proportions line up across the two cards. */
/* align-self:start because .quote is a flex column and would otherwise stretch a
   130px wordmark across the whole card. No margin either - the column already
   spaces its children with gap, and a margin on top of that doubles it. */
.quote-logo{display:block;align-self:start;height:40px;width:auto;max-width:100%;
  object-fit:contain;object-position:left center}
/* A crest is square; a wordmark is wide and short. At one shared height the crest
   shrinks to an unreadable smudge beside a wordmark, so square-ish marks get more
   height to carry the same visual weight. */
.quote-logo.crest{height:62px}
.quote-meta{display:flex;flex-wrap:wrap;align-items:center;gap:10px}
.quote-sector{font:600 var(--fs-label)/1 var(--sans);letter-spacing:.1em;
  text-transform:uppercase;color:#fff;background:var(--red);
  border:2px solid var(--red);padding:7px 10px;flex:none}
.quote-org{font:700 var(--fs-lead)/1.25 var(--sans);letter-spacing:-.015em;color:var(--ink)}
/* The quotation marks live in the text, not in a decorative pseudo-element:
   they render in the body font and keep every line flush to one left edge. */
.quote blockquote{margin:0;font-size:var(--fs-lead);line-height:1.6;
  color:var(--ink-2);max-width:52ch}
.quote figcaption{margin-top:auto;padding-top:var(--s2);
  border-top:1px solid var(--line-soft);display:flex;flex-wrap:wrap;gap:2px 10px;
  align-items:baseline}
.quote figcaption b{font:700 var(--fs-body)/1.4 var(--sans);color:var(--ink)}
.quote figcaption span{font-size:var(--fs-caption);color:var(--ink-3)}

/* ---------- craft details ---------- */
*{touch-action:manipulation}
a,button,input,select,textarea,label{-webkit-tap-highlight-color:rgba(11,27,51,.12)}
.field input[aria-invalid="true"],.field select[aria-invalid="true"],
.field textarea[aria-invalid="true"]{border-color:var(--err);background:var(--err-bg)}
.field:focus-within > label{color:var(--navy)}


/* ---------- client belt -------------------------------------------------
   One row, one direction, slow. Pauses on hover and on keyboard focus.
   Under reduced-motion it stops animating and becomes a normal scroller,
   so every client stays reachable rather than disappearing.
   ------------------------------------------------------------------------ */
.belt{position:relative;overflow:hidden;padding:var(--s3) 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  background:var(--paper)}
.belt::before,.belt::after{content:"";position:absolute;top:0;bottom:0;width:90px;z-index:2;
  pointer-events:none}
.belt::before{left:0;background:linear-gradient(90deg,var(--paper),transparent)}
.belt::after{right:0;background:linear-gradient(270deg,var(--paper),transparent)}
.belt-track{display:flex;width:max-content;gap:0;
  animation:belt-run var(--belt-speed,70s) linear infinite}
.belt:hover .belt-track,.belt:focus-within .belt-track{animation-play-state:paused}
@keyframes belt-run{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
.belt-item{flex:none;display:flex;align-items:center;justify-content:center;
  height:56px;padding:0 var(--s4);border-right:1px solid var(--line-soft);
  font:600 var(--fs-body)/1.2 var(--sans);color:var(--ink-2);white-space:nowrap;
  transition:color .18s}
.belt-item:hover{color:var(--navy)}
.belt-item img{max-height:40px;width:auto;filter:grayscale(1);opacity:.8;
  transition:filter .2s,opacity .2s}
.belt-item:hover img{filter:none;opacity:1}
@media (prefers-reduced-motion:reduce){
  .belt{overflow-x:auto}
  .belt-track{animation:none;width:auto}
  .belt::before,.belt::after{display:none}
}

/* ---------- vision & mission ---------- */
/* Cards on the navy band: a lighter navy surface so they read as objects, with
   the accent rule on top, matching .cred on the light band above. */
.vm-item{background:var(--navy-hi);border:1px solid var(--rule-navy);
  border-top:2px solid var(--accent);padding:var(--s4);height:100%}
.vm-item .label{color:#fff;margin-bottom:var(--s2)}
/* The two keys name the only two commitments on the page; they carry the weight. */
.vm-item .label.vm-key{font-weight:700;color:#fff}
.vm-item p{font:400 var(--fs-card)/1.45 var(--sans);color:#fff;max-width:34ch;
  letter-spacing:-.01em}
/* About page vision and mission. It was two unlabelled columns of body text with
   no heading at all - the quietest block on the page, carrying the two sentences
   the company is actually judged on. Same red rule as the homepage band so the
   pair read as one component across surfaces, but set at card size, given a
   heading, and closed by the motto that the statements are drawn from. */
/* A column heading: subordinate to the section h2, above the section's content. */
.colhead{font:700 var(--fs-lead)/1.3 var(--sans);letter-spacing:-.01em;color:var(--ink);
  margin-bottom:var(--s3);padding-bottom:var(--s2);border-bottom:1px solid var(--line)}
/* Vision and mission are cards here, matching the pair on the homepage band. */
.vow{background:#fff;border:1px solid var(--line);border-top:2px solid var(--accent);
  padding:var(--s4)}
/* p.vow-k, not .vow-k: `.vow p` below is 0,1,1 and would win the font shorthand
   otherwise, which silently drops the mono face and the label size. */
.vow p.vow-k{font:700 var(--fs-label)/1 var(--mono);letter-spacing:.14em;
  text-transform:uppercase;color:var(--red);margin-bottom:var(--s2);max-width:none}
/* No max-width: the card is the measure now, and a 34ch cap inside a 430px card
   was breaking lines early and leaving short middle lines. */
.vow p{font:400 var(--fs-lead)/1.55 var(--sans);letter-spacing:-.005em;
  color:var(--ink)}

/* The motto was three ragged lines wedged into a narrow column with a stray
   quote mark closing it. It now opens the band as its own line, with the mark
   set above it as a graphic rather than jammed into the sentence. */
.motto-head{display:grid;gap:var(--s2);margin-bottom:var(--s6)}
.motto-mark{font:800 4rem/.7 var(--sans);color:var(--accent);margin:0}
.sec-surface .motto,.sec-surface .motto-mark + .motto{color:var(--ink)}
.motto{font:800 var(--fs-page)/1.08 var(--sans);letter-spacing:-.03em;color:#fff;
  max-width:26ch;text-wrap:balance}
.motto span{color:var(--accent);display:block}

/* ---------- form success ---------- */
.formstatus.sending{display:block;background:var(--surface);border-color:var(--line);
  color:var(--ink-2)}
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* =========================================================================
   Phone optimisation. Measured at 375x812 before these rules:
   145px of chrome before any content, a 1558px hero, a 3038px clients
   section, and footer links only 19px tall.
   ========================================================================= */
@media (max-width:680px){

  /* The utility bar was 80px of an 812px screen. Its phone number is already
     in the pinned action bar and inside the menu, so it is pure overhead here. */
  .topbar{display:none}

  /* ...so Instagram moves into the navbar here, at the same breakpoint. Any
     earlier and it would show twice: once in the bar, once beside the menu. */
  .ignav{display:inline-flex}

  /* Hero: get the headline, the promise and the buttons into the first screen. */
  .hero-copy{padding:var(--s6) 0 var(--s4)}
  .hero .lede{font-size:var(--fs-body);margin-bottom:var(--s4)}
  /* The three places need 504px of nowrap text but only get 335px on a 375px
     phone, so "Serving across Tamil Nadu" was silently cut to "SERVING AC" -
     clipped by .hero overflow-x:clip, which is why it never showed up as an
     overflow. It wraps here instead, and the trailing rule line is dropped
     because a flex:1 line after a wrapped row lands on a row of its own. */
  .dateline{margin-bottom:var(--s3);gap:4px 12px;letter-spacing:.1em;
    flex-wrap:wrap;white-space:normal}
  .dateline::after{display:none}
  .hero .btnrow{margin-bottom:var(--s4)!important}
  .hero .btn{width:100%}
  .hero-media{min-height:280px}

  /* Three figures read better side by side than stacked down the page. */
  .stats{grid-template-columns:repeat(3,1fr);gap:var(--s2)}
  .stat{grid-column:span 1;padding-top:var(--s2)}
  .stat b{font-size:1.75rem}
  .stat b i{font-size:.95rem}
  /* 11px was below the point where a label stays comfortably readable on a
     phone; 12px still fits three stats across 360px. */
  .stat span{margin-top:8px;font-size:12px;letter-spacing:.03em}

  .belt-item{padding:0 var(--s3);height:48px;font-size:var(--fs-caption)}
  .belt::before,.belt::after{width:40px}

  /* Director slots: 4:3 portraits stacked ran to 2471px. */
  .person img{aspect-ratio:16/10}

  /* Section rhythm was still 64px top AND bottom on phones, so every boundary
     between two blocks cost 128px - about a sixth of an iPhone screen, five
     times over on About. 48px keeps the blocks clearly separate at half the cost.
     .pagehead sets its own; .hero carries an inline padding:0 and is untouched. */
  main > section:not(.pagehead){padding:var(--s6) 0}

  /* 22px statements run to five lines on a phone; 18px keeps them as statements
     without turning each one into its own screenful. */
  .vow p{font-size:var(--fs-lead)}

  /* The merged About section on a phone: the motto is display type and takes the
     page width down a step, the column heads tighten, and the timeline rail sits
     closer to the text because there is far less width to spend. */
  .motto{font-size:var(--fs-section)}
  .motto-mark{font-size:2.75rem}
  .motto-head{margin-bottom:var(--s4)}
  .colhead{margin-bottom:var(--s3);font-size:var(--fs-body)}
  .c7 .colhead{margin-top:var(--s6)}
  .vow{padding:var(--s3)}

  /* The homepage hero was tightened in revision 9 but the interior page heads
     were missed, so every one of them opened with 290-495px of near-empty navy
     before a single line of content. 64px top and bottom becomes 32/40. */
  .pagehead{padding:var(--s4) 0 40px}
  .pagehead p{font-size:var(--fs-body)}

  /* Labels sit a touch larger on a phone. */
  .field > label{font-size:var(--fs-caption)}
  /* Links sitting inline inside a sentence are left alone on purpose:
     WCAG 2.5.8 exempts them, and padding them breaks the line box. */

}

/* Very small phones: the belt and figures need one more step down. */
@media (max-width:339px){
  .stat b{font-size:1.4rem}
  .stat span{font-size:10px;letter-spacing:.02em}
  .belt-item{padding:0 var(--s2)}
}


/* =========================================================================
   Touch targets apply wherever the burger nav does, not only on phones.
   Tablets in the 681-1024 range are touch-first too, and were still
   shipping 19px footer links.
   Links sitting inline inside a sentence are deliberately excluded:
   WCAG 2.5.8 exempts them and padding them breaks the line box.
   ========================================================================= */
@media (max-width:1024px){
  .footer li{margin-bottom:2px}
  .footer li a,.footer .footco a,.contactcard a{
    display:flex;align-items:center;min-height:44px}
  .footbottom a,.crumb a,.scope a,.topbar a{
    display:inline-flex;align-items:center;min-height:44px}
  .brand{min-height:44px}
  .check{min-height:44px}
  .check input{width:24px;height:24px}
}

/* ---------- timeline on a phone: keep the rail, stack the text beside it ---------- */
@media (max-width:680px){
  .jrow{grid-template-columns:20px 1fr;gap:0 var(--s3);
    grid-template-areas:"mark date" "mark body";padding:var(--s3) 0}
  .jmark{display:flex}
  .jdate{margin-bottom:6px}
  .jrow:first-child .jmark::before{top:12px}
  .jmark::before{bottom:calc(var(--s3) * -2 - 10px)}

  /* The figure inside is position:absolute and adds no height, so min-height is
     the only thing giving the hero image a box on a phone. At 0 it showed
     nothing at all. Placeholders are gone, so this is always a real photo. */
  .hero-media{min-height:320px}
}

@media (max-width:680px){
  .quote blockquote{font-size:var(--fs-body)}
  .quote-org{font-size:var(--fs-body)}
}
