/* =========================================================================
   LooSolution — premium layer
   Loads after styles.css and theme.css, so it inherits every token already
   defined there (--accent, --paper, --ink, --surface, --line, --on-invert).
   It defines no new colours of its own.

   WHY THIS FILE IS SHORT

   The brief asked for a 4K video hero, Three.js, Particles.js, GSAP and AOS.
   All five were left out on purpose:

   - A 4K video background is 15-40 MB and decodes on the main thread. It is
     the most reliable way to fail Largest Contentful Paint on the mid-range
     Android hardware most B2B traffic arrives on.
   - Three.js is ~600 KB gzipped before you add a scene, and there is nothing
     on this site to render in 3D. You sell a wholesale partnership to
     manufacturers, not a product to consumers.
   - Particles.js runs an uncapped rAF loop. js/ambient.js already draws a
     star field on a single canvas, pauses it when off-screen, and switches
     off under prefers-reduced-motion. It is strictly better.
   - GSAP and AOS would duplicate the .reveal IntersectionObserver and the
     .count animation that js/main.js already implements. Two libraries, ~70 KB,
     for behaviour you have.

   So this file adds only what genuinely did not exist: the hero field, the
   two new lead-capture components, and accessibility hardening.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. HERO FIELD
   Two slow radial gradients behind the hero. Composited on the GPU, animates
   only opacity and transform, so it never triggers layout or paint. This is
   the whole visual budget for the page — the partner manifest is the piece
   that should hold the eye, and adding motion around it would compete.
   ------------------------------------------------------------------------- */
.hero { position: relative; isolation: isolate; }

.hero::before {
  content: "";
  position: absolute;
  inset: -20% -10% auto -10%;
  height: 130%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(42% 46% at 22% 18%, rgba(var(--accent-rgb), .13), transparent 68%),
    radial-gradient(38% 42% at 82% 30%, rgba(0, 163, 224, .11), transparent 70%);
  animation: field-drift 28s ease-in-out infinite alternate;
  will-change: transform;
}

@keyframes field-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-2.5%, 1.5%, 0) scale(1.06); }
}

/* A single hairline that reads as the horizon under the hero. Structural,
   not decorative — it marks where the page proper begins. */
.hero::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--line) 22%, var(--line) 78%, transparent);
}

/* -------------------------------------------------------------------------
   2. WHATSAPP LAUNCHER + CHOOSER
   Bottom-left on purpose. Bottom-right is where the live-chat bubble goes,
   and stacking two floating circles in one corner is how sites end up with
   a permanent thumb-sized dead zone over their own content on mobile.

   There are two people to reach, so the button opens a chooser rather than
   dialling one of them. The whole thing is a <details> element: the toggle
   is native, needs no JS, and is keyboard-operable by default.
   ------------------------------------------------------------------------- */
.wa-dock {
  position: fixed;
  left: clamp(14px, 3vw, 26px);
  bottom: clamp(14px, 3vw, 26px);
  z-index: 900;
  transition: opacity .22s ease, visibility .22s ease, transform .22s ease;
}

/* Hidden while the contact section is on screen. If the visitor has already
   reached the form, a floating button pointing somewhere else is a leak.
   The in-page .wa-direct cards cover them at that point. */
.wa-dock.is-parked {
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  pointer-events: none;
}

.wa-launch {
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 999px;
  background: #25D366;
  color: #fff;
  box-shadow: 0 6px 20px rgba(11, 27, 43, .22);
  cursor: pointer;
  transition: transform .22s cubic-bezier(.2, .8, .3, 1), box-shadow .22s ease;
}

/* Strip the native disclosure triangle in every engine. */
.wa-launch { list-style: none; }
.wa-launch::-webkit-details-marker { display: none; }
.wa-launch::marker { content: ""; }

.wa-launch svg { grid-area: 1 / 1; width: 27px; height: 27px; fill: currentColor; }
.wa-launch-x { opacity: 0; transform: rotate(-90deg) scale(.8); transition: opacity .18s ease, transform .18s ease; }
.wa-launch-ico { transition: opacity .18s ease, transform .18s ease; }

/* Swap glyph to a close icon while the chooser is open. */
.wa-dock[open] .wa-launch-ico { opacity: 0; transform: rotate(90deg) scale(.8); }
.wa-dock[open] .wa-launch-x { opacity: 1; transform: none; }

.wa-launch:hover,
.wa-launch:focus-visible {
  transform: translateY(-2px) scale(1.05);
  box-shadow: 0 10px 26px rgba(11, 27, 43, .3);
}

.wa-panel {
  position: absolute;
  left: 0;
  bottom: calc(100% + 12px);
  width: min(300px, calc(100vw - 28px));
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--surface);
  box-shadow: 0 18px 44px rgba(11, 27, 43, .26);
  animation: wa-pop .2s cubic-bezier(.2, .8, .3, 1) both;
}

@keyframes wa-pop {
  from { opacity: 0; transform: translateY(8px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

.wa-panel-h {
  margin: 4px 6px 8px;
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--slate);
}

.wa-opt {
  display: flex;
  gap: 10px;
  align-items: center;
  padding: 9px 8px;
  border-radius: 10px;
  color: var(--ink);
  text-decoration: none;
  transition: background .16s ease;
}

.wa-opt + .wa-opt { margin-top: 2px; }
.wa-opt:hover, .wa-opt:focus-visible { background: var(--fog); }

.wa-opt-av {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  background: #25D366;
  color: #fff;
  font-family: var(--mono);
  font-size: .74rem;
  font-weight: 700;
}

.wa-opt-id { display: grid; gap: 1px; min-width: 0; }
.wa-opt-name { font-size: .92rem; font-weight: 600; line-height: 1.25; }
.wa-opt-role { font-size: .72rem; line-height: 1.3; color: var(--slate); }
.wa-opt-num { font-family: var(--mono); font-size: .74rem; color: var(--slate); }

/* -------------------------------------------------------------------------
   2b. IN-PAGE WHATSAPP CONTACTS  (#contact section)
   Sits on the inverted contact panel, so colours come from --on-invert-rgb
   rather than --ink. Two columns on desktop, one below 620px. The whole card
   is the link, which gives a target far bigger than the 44px minimum.
   ------------------------------------------------------------------------- */
.wa-direct { margin-top: var(--s7); padding-top: var(--s4); border-top: 1px solid rgba(var(--on-invert-rgb), .14); }

.wa-people {
  margin-top: var(--s4);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--s4);
  list-style: none;
  padding: 0;
}

.wa-person-link {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  height: 100%;
  padding: 14px;
  border: 1px solid rgba(var(--on-invert-rgb), .16);
  border-radius: var(--r-md, 12px);
  background: rgba(var(--on-invert-rgb), .05);
  color: var(--on-invert);
  text-decoration: none;
  transition: background .18s ease, border-color .18s ease, transform .18s ease;
}

.wa-person-link:hover,
.wa-person-link:focus-visible {
  background: rgba(var(--on-invert-rgb), .1);
  border-color: #25D366;
  transform: translateY(-2px);
}

.wa-person-ico {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 999px;
  background: #25D366;
  color: #fff;
}

.wa-person-ico svg { width: 19px; height: 19px; fill: currentColor; }

.wa-person-id { display: grid; gap: 3px; min-width: 0; }
.wa-person-name { font-weight: 600; font-size: .98rem; line-height: 1.25; }
.wa-person-role { font-size: .76rem; line-height: 1.35; color: rgba(var(--on-invert-rgb), .6); }
.wa-person-num { font-family: var(--mono); font-size: .82rem; color: #25D366; margin-top: 2px; }

/* Footer CTA now holds a phone button and a mail button. The wrapper must not
   shrink — .foot-cta is a space-between flex row, so a shrinkable child gets
   squeezed until the two buttons wrap onto separate lines. */
.foot-cta-actions {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3, 10px);
  align-items: center;
}

.foot-cta-actions .btn { white-space: nowrap; }

/* Below the 900px footer stack, let the buttons fill the row instead. */
@media (max-width: 900px) {
  .foot-cta-actions { width: 100%; }
  .foot-cta-actions .btn { flex: 1 1 auto; text-align: center; justify-content: center; }
}

@media (max-width: 620px) {
  .wa-people { grid-template-columns: 1fr; }
  .foot-cta-actions .btn { flex: 1 1 100%; }
}

/* -------------------------------------------------------------------------
   3. EXIT-INTENT PANEL
   ------------------------------------------------------------------------- */
.exit-veil {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  padding: 24px;
  background: rgba(11, 27, 43, .58);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity .24s ease;
}

.exit-veil[hidden] { display: none; }
.exit-veil.is-open { opacity: 1; }

.exit-card {
  position: relative;
  width: min(520px, 100%);
  padding: clamp(26px, 4vw, 40px);
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--surface);
  box-shadow: 0 24px 60px rgba(11, 27, 43, .28);
  transform: translateY(14px) scale(.98);
  transition: transform .28s cubic-bezier(.2, .8, .3, 1);
}

.exit-veil.is-open .exit-card { transform: none; }

.exit-eyebrow {
  margin: 0 0 8px;
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: .04em;
  color: var(--slate);
}

.exit-card h2 {
  margin: 0 0 12px;
  font-family: var(--display);
  font-size: clamp(1.35rem, 3.4vw, 1.75rem);
  line-height: 1.18;
  color: var(--ink);
}

.exit-card p#exitBody {
  margin: 0 0 22px;
  max-width: 42ch;
  color: var(--slate);
  line-height: 1.6;
}

.exit-close {
  position: absolute;
  top: 10px; right: 12px;
  width: 36px; height: 36px;
  border: 0;
  border-radius: 999px;
  background: none;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--slate);
  cursor: pointer;
}

.exit-close:hover { background: var(--fog); color: var(--ink); }

.exit-dismiss {
  display: block;
  margin: 14px auto 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: .9rem;
  color: var(--slate);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* -------------------------------------------------------------------------
   4. ACCESSIBILITY HARDENING
   A visible focus ring on every interactive element, in brand colour. The
   :focus-visible pseudo-class means it appears for keyboard users and not on
   mouse click, so there is no reason to suppress it.
   ------------------------------------------------------------------------- */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Field-level error state that does not rely on colour alone — the border
   weight changes too, which is what WCAG 1.4.1 actually asks for. */
.field input[aria-invalid="true"],
.field select[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-color: #C0392B;
  border-width: 2px;
}

/* Reserve the error line's height so validation messages do not shift the
   form. Cumulative Layout Shift is measured for the whole session, not just
   load, so a jumping form counts against the page. */
.field .err { min-height: 1.15em; }

/* -------------------------------------------------------------------------
   5. REDUCED MOTION
   Everything above is decorative or user-triggered. Under reduced-motion the
   field stops dead and the panel appears without travel.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .hero::before { animation: none; }
  .wa-dock,
  .wa-launch,
  .wa-launch-ico,
  .wa-launch-x,
  .wa-opt,
  .wa-person-link,
  .exit-veil,
  .exit-card { transition: none; }
  .exit-card { transform: none; }
  .wa-panel { animation: none; }
  .wa-person-link:hover { transform: none; }
}

/* -------------------------------------------------------------------------
   6. PRINT
   Manufacturers forward pages to colleagues as PDFs. Strip the fixed
   furniture so it does not stamp itself across the first page.
   ------------------------------------------------------------------------- */
@media print {
  .wa-dock,
  .exit-veil { display: none !important; }
  .hero::before { display: none; }
}

/* Printed pages lose the wa.me links, so surface the numbers as text. */
@media print {
  .wa-person-link { border-color: #999; }
}

/* =========================================================================
   7. SEPTEMBER 2026 UPDATE
   Added for: five-profile leadership grid (name / role / bio / contact
   line), the six-office address list on the contact panel, and the head
   office map embed. Loaded last, so these override the grid breakpoints
   in styles.css without editing them.
   ========================================================================= */

/* -------------------------------------------------------------------------
   7.1 LEADERSHIP CARDS — bio and contact line
   The card is a <button>, so the number is text, not a tel: anchor. An <a>
   inside a <button> is invalid HTML and neither target fires reliably. The
   live tel: link is the Call action inside the profile dialog.
   ------------------------------------------------------------------------- */
.leader-bio {
  font-size: .8rem;
  line-height: 1.45;
  color: var(--slate);
  margin-top: 4px;
}

.leader-tel {
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: .01em;
  color: var(--accent-ink, var(--red-ink));
  margin-top: 6px;
}

/* Five cards across 1fr columns leaves each one narrow, so the role and
   bio must be allowed to wrap rather than blowing the column out. */
.leader-n,
.leader-r,
.leader-bio { overflow-wrap: anywhere; }

/* -------------------------------------------------------------------------
   7.2 LEADERSHIP GRID — responsive steps for five profiles
   5 across on desktop, 3 + 2 at 1080px, 2 across on tablet and small
   phones, single column only once the card would be too narrow to read.
   Two columns is kept down to 430px because the cards now carry a bio;
   five full-width cards in a row would be a long scroll otherwise.
   ------------------------------------------------------------------------- */
@media (max-width: 620px) {
  .leader-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }
  .leader-photo { width: 64px; height: 64px; margin-bottom: var(--s3); }
  .leader-initials { font-size: 1.25rem; }
  .leader-bio { font-size: .78rem; }
  /* The reveal-on-hover affordance is meaningless on touch. */
  .leader-view { opacity: 1; transform: none; }
}

@media (max-width: 430px) {
  .leader-grid { grid-template-columns: 1fr; }
  .leader-photo { width: 72px; height: 72px; }
}

/* -------------------------------------------------------------------------
   7.3 CONTACT PANEL — international office list
   Sits inside .contact-list, which is on the inverted panel, so colours
   come from --on-invert-rgb. The nested <ul> must not inherit the
   top-border the outer <li> carries.
   ------------------------------------------------------------------------- */
.cl-offices {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 4px;
}

.cl-offices li {
  padding-top: 0;
  border-top: 0;
  font-size: .95rem;
  line-height: 1.5;
  color: rgba(var(--on-invert-rgb), .86);
}

/* Marker before each international office, so the list reads as a set of
   locations rather than a wrapped paragraph. */
.cl-offices li::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  margin-right: 9px;
  border-radius: 999px;
  background: rgba(var(--on-invert-rgb), .4);
  vertical-align: middle;
  transform: translateY(-1px);
}

/* -------------------------------------------------------------------------
   7.4 CONTACT PANEL — head office map
   Keyless Google embed. Aspect-ratio rather than a fixed height so it
   never letterboxes; the iframe's own width/height attributes stay in the
   markup purely to reserve space before CSS applies.
   ------------------------------------------------------------------------- */
.contact-map {
  margin: var(--s6) 0 0;
  border: 1px solid rgba(var(--on-invert-rgb), .14);
  border-radius: var(--r-lg, 14px);
  overflow: hidden;
  background: rgba(var(--on-invert-rgb), .04);
}

.contact-map iframe {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border: 0;
  /* The embed is a light-mode Google tile set on a dark panel; a touch of
     desaturation stops it fighting the section around it. */
  filter: saturate(.92);
}

.contact-map figcaption {
  padding: 10px var(--s4);
  border-top: 1px solid rgba(var(--on-invert-rgb), .12);
  font-family: var(--mono);
  font-size: var(--t-micro, .68rem);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(var(--on-invert-rgb), .55);
}

@media (max-width: 620px) {
  .contact-map iframe { aspect-ratio: 4 / 3; }
}

/* -------------------------------------------------------------------------
   7.5 FOOTER ADDRESSES
   Left to styles.css §24.7, which already lays .foot-addr out as an
   auto-fit grid sized for six entries and carries the `flex:1 1 620px`
   basis it needs inside .foot-base. Overriding it here would have dropped
   that basis. The only change needed is tightening the minimum column so
   two "United States" entries do not force a third row on small phones.
   ------------------------------------------------------------------------- */
@media (max-width: 620px) {
  .foot-addr { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
}

/* The single WhatsApp card now spans the contact row on its own; cap it so
   it does not stretch into a letterbox on a wide viewport. */
.wa-people { max-width: 420px; }

@media print {
  .contact-map { display: none !important; }
}
