/* ==========================================================================
   LTI (Logic Technology, Inc) — Design System
   ========================================================================== */

@import url('https://api.fontshare.com/v2/css?f[]=satoshi@400,500,700,900&display=swap');

:root {
  --cream: #f8f8f5;
  --cream-rgb: 248, 248, 245;
  --cream-hover: #efeee9;
  --ink: #141414;
  --ink-rgb: 20, 20, 20;
  --hairline: rgba(var(--ink-rgb), 0.12);

  --black: #0a0a0a;
  --black-rgb: 10, 10, 10;
  --white: #ffffff;
  --white-75: rgba(247, 247, 245, 0.75);
  --white-50: rgba(247, 247, 245, 0.5);
  --hairline-dark: rgba(247, 247, 245, 0.15);

  --maroon: #650b1d;
  --maroon-rgb: 101, 11, 29;

  /* The literal LTI brand red, sampled straight from the logo/favicon
     (#650B1D). Unlike --maroon, this never shifts under dark mode — use it
     wherever a hover/fill needs to read as the actual brand color rather
     than a theme-adaptive accent. */
  --brand-red: #650b1d;

  /* A handful of small UI accents (cookie banner, a couple of hover fills)
     are deliberately a solid near-black chip regardless of site theme —
     distinct from --ink, which is the page's main text/surface color and
     DOES invert under dark mode below. */
  --surface-dark: #141414;
  --surface-dark-rgb: 20, 20, 20;

  --font: 'Satoshi', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  --container: 1280px;
  --gutter: clamp(20px, 4vw, 80px);

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ---------------------------------- Dark mode ---------------------------------- */
/* Follows the OS/browser preference by default; the toggle button (bottom
   left, added by initThemeToggle in main.js) can override it either way by
   stamping data-theme="dark"/"light" on <html> and remembering the choice.
   Only the light-surface tokens (--cream family, --ink family) invert;
   --black/--white/--maroon-as-accent and the already-dark sections (hero,
   footer, photo overlays) are unaffected, since they're a fixed design
   choice, not a light/dark surface pair. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --cream: #17181a;
    --cream-rgb: 23, 24, 26;
    --cream-hover: #202224;
    --ink: #f2f1ee;
    --ink-rgb: 242, 241, 238;
    --maroon: #b23350;
    --maroon-rgb: 178, 51, 80;
  }
}
:root[data-theme="dark"] {
  --cream: #17181a;
  --cream-rgb: 23, 24, 26;
  --cream-hover: #202224;
  --ink: #f2f1ee;
  --ink-rgb: 242, 241, 238;
  --maroon: #b23350;
  --maroon-rgb: 178, 51, 80;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; }

body {
  font-family: var(--font);
  background: var(--cream);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }
button { font-family: inherit; cursor: pointer; background: none; border: none; color: inherit; }
/* The hidden attribute must always win. Without this, any class that
   sets display (.btn is inline-flex, the modal tab bar is flex) quietly
   overrides the browser's own [hidden] rule and the element stays visible. */
[hidden] { display: none !important; }

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* ---------------------------------- Type ---------------------------------- */

h1, h2, h3, h4 {
  font-weight: 400;
  letter-spacing: -0.04em;
  line-height: 1.02;
  text-transform: uppercase;
}

.eyebrow {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--maroon);
}

.eyebrow--light { color: var(--white-75); }

p { line-height: 1.6; }

.lede {
  font-size: clamp(16px, 1.6vw, 19px);
  line-height: 1.55;
  color: rgba(var(--ink-rgb), 0.72);
  max-width: 640px;
}

.lede--light { color: var(--white-75); max-width: 640px; }

/* ---------------------------------- Buttons ---------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 20px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: 6px;
  border: 1px solid transparent;
  transition: all 0.4s var(--ease);
  white-space: nowrap;
}

.btn svg { width: 14px; height: 14px; transition: transform 0.4s var(--ease); }
.btn:hover svg { transform: translate(3px, -3px); }

.btn--ghost-light {
  background: rgba(247, 247, 245, 0.1);
  border-color: var(--white);
  color: var(--white);
}
.btn--ghost-light:hover { background: var(--brand-red); border-color: var(--brand-red); }

.btn--maroon {
  background: transparent;
  border-color: var(--ink);
  color: var(--ink);
}
.btn--maroon:hover { background: var(--maroon); border-color: var(--maroon); color: var(--white); }

/* .btn--maroon's black text/border reads fine on light sections (e.g. the
   Contact page body) but this same button also sits in the footer, which
   is always a dark photo background — needs light text there instead. */
.site-footer .btn--maroon { border-color: var(--white); color: var(--white); }
.site-footer .btn--maroon:hover { border-color: var(--maroon); color: var(--white); }

.btn--outline-dark {
  background: transparent;
  border-color: var(--hairline);
  color: var(--ink);
}
.btn--outline-dark:hover { background: var(--brand-red); color: var(--white); border-color: var(--brand-red); }

/* ---------------------------------- Header ---------------------------------- */

.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  padding: 20px 0;
  transition: background 0.4s var(--ease), padding 0.4s var(--ease);
}

.site-header.is-scrolled,
.site-header.is-light {
  background: rgba(var(--cream-rgb), 0.95);
  backdrop-filter: blur(10px);
  padding: 14px 0;
  border-bottom: 1px solid var(--hairline);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* Fixed size matches the full wordmark's own rendered dimensions, so the
   glyph+wordtext layers below (each absolutely positioned to fill it) line
   up exactly with where the combined logo used to sit. */
.logo-mark { display: block; position: relative; width: 213px; height: 32px; }

/* Each lockup is the icon ("glyph") and the "- Logic Technology, Inc" text
   layered on top of each other, split from the same two source wordmarks
   via clip-path so they stay pixel-aligned with no separate text asset.
   Hovering fades+slides the text left "into" the glyph, which slides right
   to sit centered on its own — a smooth version of what used to be an
   instant image swap. */
.logo-lockup { position: absolute; inset: 0; }
.logo-glyph {
  position: absolute; left: 0; top: 0;
  height: 32px; width: auto;
  transition: left 0.4s var(--ease);
}
.logo-wordtext {
  position: absolute; left: 0; top: 0;
  width: 213px; height: 32px;
  clip-path: inset(0 0 0 25.2%);
  transition: opacity 0.35s var(--ease), transform 0.4s var(--ease);
}
.logo-mark:hover .logo-glyph { left: 78px; }
/* While hovered (or tapped), initLogoFollow in main.js steers the lone LTI
   mark toward the pointer: --glyph-x / --glyph-y are set per pointer move,
   and the short transition turns those jumps into a smooth glide. */
.logo-mark.is-following .logo-glyph {
  left: var(--glyph-x, 78px);
  transform: translateY(var(--glyph-y, 0px));
  transition: left 0.18s var(--ease), transform 0.18s var(--ease);
}
.logo-mark:hover .logo-wordtext { opacity: 0; transform: translateX(-40px); }

/* Transparent-over-hero state shows the white wordmark; once the header
   goes solid (scrolled, or forced on light-hero pages) it swaps to the
   dark/maroon wordmark so it reads against the cream fill. */
.logo-mark .logo-lockup--dark { display: none; }
.site-header.is-scrolled .logo-mark .logo-lockup--light,
.site-header.is-light .logo-mark .logo-lockup--light { display: none; }
.site-header.is-scrolled .logo-mark .logo-lockup--dark,
.site-header.is-light .logo-mark .logo-lockup--dark { display: block; }
/* In dark mode the "solid" header fill is dark, not cream — so the swap
   above would put the dark/maroon wordmark on a dark bar and it'd vanish.
   Keep the light wordmark showing in that state instead. */
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) .site-header.is-scrolled .logo-mark .logo-lockup--light,
  html:not([data-theme="light"]) .site-header.is-light .logo-mark .logo-lockup--light { display: block; }
  html:not([data-theme="light"]) .site-header.is-scrolled .logo-mark .logo-lockup--dark,
  html:not([data-theme="light"]) .site-header.is-light .logo-mark .logo-lockup--dark { display: none; }
}
html[data-theme="dark"] .site-header.is-scrolled .logo-mark .logo-lockup--light,
html[data-theme="dark"] .site-header.is-light .logo-mark .logo-lockup--light { display: block; }
html[data-theme="dark"] .site-header.is-scrolled .logo-mark .logo-lockup--dark,
html[data-theme="dark"] .site-header.is-light .logo-mark .logo-lockup--dark { display: none; }

.main-nav { display: flex; align-items: center; gap: 40px; }

.main-nav__links { display: flex; align-items: center; gap: 32px; }

.main-nav__links a {
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--white-75);
  padding: 6px 0;
  position: relative;
  white-space: nowrap;
  transition: color 0.35s var(--ease);
}

.site-header.is-scrolled .main-nav__links a,
.site-header.is-light .main-nav__links a { color: rgba(var(--ink-rgb), 0.6); }

.main-nav__links a:hover,
.main-nav__links a.is-active { color: var(--white); }
.site-header.is-scrolled .main-nav__links a:hover,
.site-header.is-scrolled .main-nav__links a.is-active,
.site-header.is-light .main-nav__links a:hover,
.site-header.is-light .main-nav__links a.is-active { color: var(--ink); font-weight: 700; }

.main-nav__links a.is-active {
  box-shadow: 0 2px 0 0 var(--maroon);
}

.nav-toggle {
  display: none;
  background: none;
  border: none;
  /* 44px hit area (touch-target minimum) around a visually unchanged
     32x20px icon — the bars below are sized/centered independently of
     the button box so the tap target can grow without the icon growing. */
  width: 44px; height: 44px;
  position: relative;
}
.nav-toggle span {
  position: absolute; left: 50%; width: 32px; margin-left: -16px; height: 2px;
  background: var(--white-75);
  transition: all 0.4s var(--ease);
}
.site-header.is-scrolled .nav-toggle span,
.site-header.is-light .nav-toggle span { background: var(--ink); }
.nav-toggle span:nth-child(1) { top: 12px; }
.nav-toggle span:nth-child(2) { top: 21px; }
.nav-toggle span:nth-child(3) { top: 30px; }
.nav-toggle.is-open span:nth-child(1) { top: 21px; transform: rotate(45deg); }
.nav-toggle.is-open span:nth-child(2) { opacity: 0; }
.nav-toggle.is-open span:nth-child(3) { top: 21px; transform: rotate(-45deg); }

/* ---------------------------------- Hero entrance animations ---------------------------------- */
/* Gated behind .is-loaded (added by initHeroEntrance in main.js once the
   hero image has actually finished loading) so the fade/zoom plays when the
   photo is visible, instead of racing — and losing to — a slow image load. */

@keyframes heroTextIn {
  from { opacity: 0; transform: translateY(24px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---------------------------------- Dark hero sections ---------------------------------- */

.hero-dark {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  color: var(--white);
  overflow: hidden;
  background: var(--black);
}

.hero-dark__bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero-dark__bg img, .hero-dark__bg video {
  width: 100%; height: 100%; object-fit: cover;
  /* Explicit rather than relying on the (matching) default, so the crop
     stays anchored to the subject's center — the jet in the "LTI" tab's
     poster, say — through every breakpoint instead of silently drifting
     if this ever gets a non-square aspect-ratio media query later. */
  object-position: center;
  position: absolute; inset: 0;
  opacity: 0;
  transform: scale(1.1);
  transition: opacity 1.6s var(--ease), transform 2.8s var(--ease);
}
/* The LTI clip's jet sits ~70% across the frame, not in the middle. On
   portrait-ish screens object-fit:cover keeps only a narrow central strip
   of the 16:9 video, so the jet fell outside it on phones. Cropping at 72%
   brings it into view, biased right of center so it clears the headline
   (about 64% across on a phone, 67% on a portrait tablet), with its trail
   still inside the frame; wider screens barely crop sideways, so they keep
   the default centered framing. Applies to the poster frame too. */
@media (max-aspect-ratio: 4/3) {
  .hero-dark__bg video[poster$="hero-lti.jpg"] { object-position: 72% 50%; }
  /* Manufacturing clip: the welder sits just left of the frame's middle, so
     the centered crop put him toward the left edge on phones. 36% nudges
     him right, and still keeps his mask in frame as the clip drifts. */
  .hero-dark__bg video[poster$="hero-manufacturing.jpg"] { object-position: 36% 50%; }
  /* Renewables clip: the camera pans left and the nearest turbine starts
     ~76% across the frame, so the centered crop missed it for the whole
     6 seconds the slide is shown. 80% keeps it near the middle of a phone screen as it drifts. */
  .hero-dark__bg video[poster$="hero-renewables.jpg"] { object-position: 80% 50%; }
}
.hero-dark.is-loaded .hero-dark__bg img.is-active,
.hero-dark.is-loaded .hero-dark__bg video.is-active { opacity: 1; transform: scale(1); }
.hero-dark__bg::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.25) 45%, rgba(0,0,0,0.75) 100%);
}

.hero-dark__content {
  position: relative;
  z-index: 2;
  padding: 160px var(--gutter) 56px;
  max-width: var(--container);
  margin: 0 auto;
  width: 100%;
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 1.1s var(--ease) 0.3s, transform 1.1s var(--ease) 0.3s;
}
.hero-dark.is-loaded .hero-dark__content { opacity: 1; transform: translateY(0); }

.hero-dark__heading {
  font-size: clamp(32px, 5.5vw, 64px);
  max-width: 14ch;
  margin-bottom: 28px;
}

.hero-dark__tabs {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: rgba(10, 8, 8, 0.55);
  backdrop-filter: blur(6px);
}

.hero-dark__tab {
  padding: 22px var(--gutter);
  text-align: center;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--white-50);
  background: none;
  border: none;
  border-top: 1px solid rgba(255, 255, 255, 0.7);
  position: relative;
  transition: color 0.4s var(--ease);
}

.hero-dark__tab.is-active { color: var(--white); }

.hero-dark__tab:not(:last-child) { border-right: 1px solid var(--hairline-dark); }

/* Countdown fill that grows across the active tab's top edge over the
   rotator's dwell time, then resets — driven by JS toggling .is-filling. */
.hero-dark__tab-progress {
  position: absolute;
  top: -2px; left: 0;
  height: 2px;
  width: 0%;
  background: var(--maroon);
  transition-property: width;
  transition-timing-function: linear;
  transition-duration: 0s;
}
.hero-dark__tab-progress.is-filling { width: 100%; }

/* Simple, non-rotating page hero (services/about/contact) */

.hero-simple {
  position: relative;
  min-height: 72vh;
  display: flex;
  align-items: flex-end;
  color: var(--white);
  overflow: hidden;
  background: var(--black);
  padding: 160px var(--gutter) 64px;
}

.hero-simple img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; z-index: 0;
  opacity: 0;
  transform: scale(1.1);
  transition: opacity 1.6s var(--ease), transform 2.8s var(--ease);
}
.hero-simple.is-loaded img { opacity: 1; transform: scale(1); }
.hero-simple::before {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0.7) 100%);
  z-index: 1;
}
.hero-simple__inner {
  position: relative; z-index: 2; max-width: var(--container); margin: 0 auto; width: 100%;
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 1.1s var(--ease) 0.3s, transform 1.1s var(--ease) 0.3s;
}
.hero-simple.is-loaded .hero-simple__inner { opacity: 1; transform: translateY(0); }
.hero-simple__inner h1 { font-size: clamp(30px, 5vw, 54px); max-width: 20ch; }

/* Phones and tablets: every photo banner (and the About banner below)
   uses the same compact 300px height. It started with Contact, whose team
   photo is a ~3:1 panorama that a tall banner scaled up until only the
   middle quarter of the group showed; the other pages now match it. */
@media (max-width: 900px) {
  .hero-simple { min-height: 300px; padding-top: 120px; padding-bottom: 40px; }

}

/* Contact: everyone in the team photo stays visible at every screen size.
   The photo is contained (never cropped) and sits a little above center,
   between the menu bar and the headline; a blurred, darkened copy of the
   same photo fills the rest of the banner so it doesn't read as empty
   bars. isolation gives the section its own stacking context so the
   z-index:-1 blur layer sits above the section's black background but
   below the sharp photo. */
.hero-simple--team { isolation: isolate; }
.hero-simple--team img { object-fit: contain; object-position: 50% 45%; }
.hero-simple--team::after {
  content: '';
  position: absolute;
  inset: -30px;
  z-index: -1;
  background: url('../assets/images/contact-hero.jpg') center / cover no-repeat;
  filter: blur(22px) brightness(0.55);
}
/* Tablets and up: the banner is exactly the menu bar plus the full-width
   photo (3.08:1), so the photo fills it edge to edge with no blurred strip
   below it, and the page content starts right after the photo. On phones
   the photo is too short to hold the headline, so it stays contained above
   the headline with the blurred fill behind. */
@media (min-width: 601px) {
  .hero-simple--team {
    --team-top: 84px;
    min-height: calc(var(--team-top) + 100vw / 3.08);
    padding-top: calc(var(--team-top) + 24px);
  }
  .hero-simple--team img {
    top: var(--team-top);
    height: calc(100% - var(--team-top));
    object-fit: cover;
    object-position: 50% 50%;
  }
}
@media (min-width: 901px) {
  .hero-simple--team { --team-top: 72px; }
}

/* Vertically centers the text block instead of pinning it to the bottom
   edge — for a hero whose photo has a natural midline (a corridor's
   vanishing point, say) the copy reads better meeting it there. */
.hero-simple--center { align-items: center; }

/* ---------------------------------- Sections ---------------------------------- */

section { position: relative; }

.section {
  padding: clamp(60px, 10vw, 140px) 0;
}

.section--tight { padding: clamp(40px, 6vw, 80px) 0; }

.section--dark {
  background: var(--black);
  color: var(--white);
}

.section-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 40px;
  margin-bottom: 56px;
  flex-wrap: wrap;
}

.section-head h2 {
  font-size: clamp(26px, 3.6vw, 44px);
  max-width: 16ch;
  margin-top: 10px;
}

/* Reveal-on-scroll: content is always visible (never gated behind JS/observer
   timing); the class only adds a subtle upward settle for polish. */
.reveal {
  transform: translateY(16px);
  transition: transform 0.7s var(--ease);
}
.reveal.is-visible { transform: translateY(0); }

/* ---------------------------------- Services grid ---------------------------------- */

.services-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--hairline);
  border: 1px solid var(--hairline);
  border-radius: 18px;
  overflow: hidden;
}

.services-grid--3col { grid-template-columns: repeat(3, 1fr); }
/* For a shorter run of blog-style cards (e.g. 2 posts) that shouldn't be
   forced into 3 columns — combine with .services-grid--3col for its
   shared border/spacing treatment below. Still overridden by the mobile
   single-column rule near the end of this file. */
.services-grid--2col { grid-template-columns: repeat(2, 1fr); }
/* Blog cards read better as separate, evenly-spaced tiles than as one
   divided block — undo the shared hairline-grid treatment and give each
   card its own border/radius instead. */
.services-grid--3col {
  gap: clamp(28px, 3vw, 48px);
  background: none;
  border: none;
  border-radius: 0;
  overflow: visible;
}
.services-grid--3col .service-card {
  border: 1px solid var(--hairline);
  border-radius: 18px;
  overflow: hidden;
}

.service-card {
  background: var(--cream);
  padding: 40px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 40px;
  min-height: 220px;
  transition: background 0.4s var(--ease);
}
.service-card:hover { background: var(--cream-hover); }

.service-card h3 { font-size: clamp(20px, 2.2vw, 26px); max-width: 18ch; }

.service-card__num {
  font-size: 13px;
  color: var(--maroon);
  font-weight: 500;
  letter-spacing: 0.1em;
}

.service-card__arrow {
  width: 36px; height: 36px;
  border-radius: 8px;
  border: 1px solid var(--hairline);
  display: flex; align-items: center; justify-content: center;
  align-self: flex-end;
  transition: all 0.4s var(--ease);
}
.service-card:hover .service-card__arrow {
  background: var(--maroon);
  border-color: var(--maroon);
  color: var(--white);
  transform: rotate(45deg);
}
.service-card__arrow svg { width: 16px; height: 16px; }

/* ---------------------------------- Stats ---------------------------------- */

.stats-strip {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: end;
  /* Taller than before — the source photo is a fairly square 1.5:1 aerial
     shot, and the old short/wide band cropped out most of its height,
     leaving mostly blank sky visible. This still stays a compact strip
     rather than growing to the photo's full un-cropped height. */
  min-height: clamp(480px, 50vw, 760px);
  background: var(--cream);
  overflow: hidden;
}
/* Sized taller than the strip and nudged up via JS scroll position (see
   initStatsParallax in main.js) at a fraction of the page's own scroll
   speed, so it drifts slower than the foreground — the "lags behind" look. */
.stats-strip__bg {
  position: absolute;
  top: -20%; left: 0;
  width: 100%; height: 170%;
  object-fit: cover;
  /* Anchored to the top of the source photo (the skyline against open sky),
     tuned together with the top/height offsets above so that when the
     section is scrolled to sit centered in the viewport (the parallax's
     resting point, given initStatsParallax's 0.25 speed), the crop favors
     the skyline over deep fog — while keeping enough slack on both sides
     that the drift never exposes an edge while the section is on screen. */
  object-position: 50% 50%;
  z-index: 0;
  will-change: transform;
}
.stat {
  position: relative;
  z-index: 1;
  padding: 28px var(--gutter);
  text-align: center;
  /* No backdrop-filter here on purpose: this panel sits over the
     scroll-parallaxed background image (see initStatsParallax in main.js),
     and blurring content that repaints every scroll frame is a well-known
     jank source. A more opaque flat panel gets a similar frosted look
     without forcing a re-blur on every frame. */
  background: rgba(255, 255, 255, 0.92);
  border-right: 1px solid rgba(0, 0, 0, 0.08);
}
.stat:last-child { border-right: none; }
.stat__num {
  font-size: clamp(32px, 4vw, 52px);
  color: #1a1a1a;
  letter-spacing: -0.03em;
}
.stat__label {
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(0, 0, 0, 0.55);
  margin-top: 8px;
}

/* ---------------------------------- Client logos ---------------------------------- */

.clients-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 48px;
  margin-top: 50px;
}
.clients-row img { max-height: 58px; width: auto; }
/* Most of these are full-color brand marks that read fine as-is on any
   background, but a few mix in pure-black ink (wordmarks, taglines) that
   would vanish on a dark page. For just those, swap in a pre-recolored
   variant (same file, black ink pixels flipped to white, everything else
   untouched) instead of a background chip — keeps the layout identical to
   the light version, just with legible text. */
.client-logo--dark { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .client-logo--light { display: none; }
  :root:not([data-theme="light"]) .client-logo--dark { display: inline-block; }
}
:root[data-theme="dark"] .client-logo--light { display: none; }
:root[data-theme="dark"] .client-logo--dark { display: inline-block; }

/* ---------------------------------- Testimonials ---------------------------------- */

.testimonial-carousel { position: relative; }
.testimonial-track-wrap { overflow: hidden; }
.testimonial-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(247, 247, 245, 0.1);
  border: 1px solid var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--white);
  transition: background 0.4s var(--ease), border-color 0.4s var(--ease), opacity 0.4s var(--ease), transform 0.4s var(--ease);
}
.testimonial-nav svg { width: 20px; height: 20px; }
.testimonial-nav:hover { background: var(--maroon); border-color: var(--maroon); transform: translateY(-50%) scale(1.06); }
.testimonial-nav[disabled] { opacity: 0.35; pointer-events: none; }
/* Centered in the gutter margin (the empty strip the track-wrap bleeds into)
   instead of right at the card row's own edge, so it never sits on top of
   whichever card happens to be scrolled into view there. */
.testimonial-nav--prev { left: calc(var(--gutter) * -0.5 - 24px); }
.testimonial-nav--next { right: calc(var(--gutter) * -0.5 - 24px); }
@media (max-width: 900px) {
  .testimonial-nav { display: none; }
}
.testimonial-track {
  display: flex;
  gap: 28px;
  overflow-x: auto;
  cursor: grab;
  scrollbar-width: none;
  padding-bottom: 8px;
}
.testimonial-track:active { cursor: grabbing; }
.testimonial-track::-webkit-scrollbar { display: none; }
.testimonial-card {
  flex: 0 0 460px;
  background: var(--cream);
  border: 1px solid var(--hairline);
  border-radius: 16px;
  padding: 44px;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
@media (min-width: 1100px) {
  /* Stretch cards to fill the row so exactly 3 sit fully in view,
     instead of a fixed width that clips a sliver of the 3rd card. */
  .testimonial-card { flex-basis: calc((100% - 56px) / 3); }
}
/* Explicit color: the cards sit inside the dark "Our Team" band, whose white
   text color would otherwise be inherited onto the light card. */
.testimonial-card h4 { font-size: 17px; text-transform: none; letter-spacing: 0; color: var(--ink); }
.testimonial-card p { font-size: 17px; line-height: 1.6; color: rgba(var(--ink-rgb), 0.75); flex: 1; }
.testimonial-card__person {
  display: flex; align-items: center; gap: 14px;
  font-size: 14px;
  color: rgba(var(--ink-rgb), 0.55);
}
.testimonial-card__person img {
  width: 48px; height: 48px; border-radius: 50%; object-fit: cover;
}

/* ---------------------------------- Footer ---------------------------------- */

.site-footer {
  position: relative;
  background: var(--black);
  color: var(--white);
  padding: clamp(60px, 8vw, 120px) 0 30px;
  overflow: hidden;
}
.site-footer__bg { position: absolute; inset: 0; opacity: 0.18; }
.site-footer__bg img { width: 100%; height: 100%; object-fit: cover; }
.site-footer__inner { position: relative; z-index: 1; }

.site-footer__top {
  display: flex;
  justify-content: space-between;
  gap: 60px;
  flex-wrap: wrap;
  padding-bottom: 60px;
  border-bottom: 1px solid var(--hairline-dark);
}

.site-footer h3 {
  font-size: clamp(28px, 4vw, 46px);
  max-width: 12ch;
  margin-bottom: 24px;
}

.footer-cols { display: flex; gap: 80px; flex-wrap: wrap; }
.footer-col h5 {
  font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--white-50); margin-bottom: 16px;
}
.footer-col a, .footer-col p {
  display: block;
  font-size: 14px;
  color: var(--white-75);
  margin-bottom: 10px;
}
.footer-col a:hover { color: var(--white); }

.site-footer__bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
  padding-top: 24px;
  font-size: 13px;
  color: var(--white-50);
}
.footer-cookie-link {
  margin-left: 12px;
  font-size: inherit;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color 0.3s var(--ease);
}
.footer-cookie-link:hover { color: var(--white); }

.socials { display: flex; gap: 16px; }
.socials a {
  width: 36px; height: 36px;
  border: 1px solid var(--hairline-dark);
  border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  transition: all 0.35s var(--ease);
}
.socials a:hover { background: var(--maroon); border-color: var(--maroon); }
.socials svg { width: 15px; height: 15px; }

/* ---------------------------------- Utility layout blocks ---------------------------------- */

.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  align-items: center;
}

.pill-list { display: flex; flex-direction: column; gap: 0; }
.pill-list__item {
  display: flex;
  gap: 24px;
  padding: 28px 0;
  border-top: 1px solid var(--hairline);
}
.pill-list__item:last-child { border-bottom: 1px solid var(--hairline); }
.pill-list__num {
  font-size: 14px; color: var(--maroon); font-weight: 500; flex: 0 0 44px;
}
/* The text column must be allowed to shrink below its content's intrinsic
   width, otherwise flexbox lets long paragraphs overflow the row instead
   of wrapping. */
.pill-list__item > div { flex: 1 1 auto; min-width: 0; }
.pill-list__item h4 { font-size: 18px; text-transform: none; letter-spacing: 0; margin-bottom: 8px; }
.pill-list__item p { font-size: 15px; color: rgba(var(--ink-rgb), 0.68); }

.pill-list--light .pill-list__item { border-color: var(--hairline-dark); }
.pill-list--light .pill-list__num { color: var(--white); }
.pill-list--light .pill-list__item h4 { color: var(--white); }
.pill-list--light .pill-list__item p { color: var(--white-75); }

.pill-list--icons .pill-list__item { padding-top: 32px; padding-bottom: 32px; }
.pill-list__icon {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--maroon);
  margin-bottom: 16px;
}
.pill-list__icon svg { width: 20px; height: 20px; }
.pill-list--light .pill-list__icon { border-color: var(--hairline-dark); color: var(--maroon); }

.image-frame { border-radius: 20px; overflow: hidden; }
.image-frame img { width: 100%; height: 100%; object-fit: cover; }
.image-frame img[data-values-image-target] {
  opacity: 0;
  /* Paired with a slight scale-up so the image stays oversized enough to
     cover the frame throughout the slide — a pure translateY here would
     expose a gap at the bottom edge mid-animation, since object-fit:cover
     sizes the image to exactly fill the frame with nothing to spare. */
  transform: scale(1.06) translateY(-28px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.image-frame img[data-values-image-target].is-loaded { opacity: 1; transform: scale(1) translateY(0); }

/* Big centered play button so a poster frame reads as a video, not a
   static photo — hidden once playback starts (see initVideoPlayButton in
   main.js) and brought back on pause/end. */
.video-play-btn {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 84px; height: 84px;
  border-radius: 50%;
  background: var(--brand-red);
  border: none;
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.35);
  transition: transform 0.3s var(--ease), background 0.3s var(--ease), opacity 0.3s var(--ease);
  z-index: 2;
}
.video-play-btn svg { width: 42px; height: 42px; }
.video-play-btn:hover { transform: translate(-50%, -50%) scale(1.08); background: var(--maroon); }
.video-play-btn.is-hidden { opacity: 0; pointer-events: none; transform: translate(-50%, -50%) scale(0.8); }
/* For posters with their own title text and branding baked in (the "How to
   get to JGHQ" directions thumbnails) — same size/position as the default
   button, but no filled circle (the brand maroon clashed with these older,
   blue-toned stills) — just a soft translucent ring so it still reads as
   clickable. */
.video-play-btn--outline {
  background: rgba(255, 255, 255, 0.12);
  backdrop-filter: blur(6px);
  border: 1.5px solid rgba(255, 255, 255, 0.65);
  box-shadow: none;
}
.video-play-btn--outline:hover { transform: translate(-50%, -50%) scale(1.08); background: rgba(255, 255, 255, 0.22); border-color: var(--white); }
.video-play-btn--outline.is-hidden { transform: translate(-50%, -50%) scale(0.8); }

.map-frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16/7;
  border-radius: 20px;
  overflow: hidden;
  background: var(--cream);
  border: 1px solid var(--hairline);
}
.map-frame iframe { width: 100%; height: 100%; }
/* Shown until the consent-gated map loads (see initConsentGatedEmbeds). */
.map-frame[data-consent-embed] { min-height: 240px; }
.map-frame__placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 24px;
  text-align: center;
  font-size: 14px;
  color: rgba(var(--ink-rgb), 0.7);
}
.map-frame__placeholder a { font-size: 14px; color: var(--maroon); }
.map-frame.is-loaded .map-frame__placeholder { display: none; }
/* ---------------------------------- Forms ---------------------------------- */

.contact-form { display: flex; flex-direction: column; gap: 20px; }
/* Honeypot: invisible to real visitors and out of the tab order, but a
   plain <input> most bots that auto-fill every field will still populate —
   filling it in is the tell that flags a submission as spam server-side. */
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.field { display: flex; flex-direction: column; gap: 8px; }
.field[hidden] { display: none; }
.field label {
  font-size: 12px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink);
}
.field input, .field textarea, .field select {
  font-family: inherit;
  background: var(--cream);
  border: 1px solid var(--ink);
  border-radius: 10px;
  padding: 14px 16px;
  font-size: 15px;
  color: var(--ink);
  resize: vertical;
}
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none;
  border-color: var(--maroon);
}
.field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23141414' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 18px;
  padding-right: 44px;
}
.contact-form button { align-self: flex-start; }
/* Email/call block shown on the Contact page while the online form is off. */
.contact-cta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
  padding: 32px;
  border: 1px solid var(--hairline);
  border-radius: 16px;
}
.contact-cta__hint { font-size: 15px; color: rgba(var(--ink-rgb), 0.68); max-width: 46ch; }
.contact-cta__alt { font-size: 15px; color: rgba(var(--ink-rgb), 0.68); }
.contact-cta__alt a { color: var(--ink); font-weight: 500; text-decoration: underline; text-underline-offset: 3px; }
.contact-cta__alt a:hover { color: var(--maroon); }
/* Google's required reCAPTCHA disclosure, shown under each form. */
.recaptcha-notice {
  font-size: 12px;
  line-height: 1.5;
  color: rgba(var(--ink-rgb), 0.5);
}
.recaptcha-notice a { text-decoration: underline; text-underline-offset: 2px; }
.recaptcha-notice a:hover { color: var(--maroon); }
.required { color: var(--maroon); }

.contact-details { display: flex; flex-direction: column; gap: 32px; }
.contact-details__item h5 {
  font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--maroon); margin-bottom: 8px;
}
.contact-details__item p, .contact-details__item a { font-size: 18px; }
.contact-details__item a:hover { color: var(--maroon); }

/* ---------------------------------- History (About) ---------------------------------- */
/* Horizontally scrolling row of milestone cards — matches how
   ltionline.com/about actually presents this section (a native
   overflow-x:auto track), rather than a vertical stacked list.
   data-drag-scroll wires up the same mouse-drag scrolling already used
   for the testimonial carousel (see initDragScroll in main.js). */
.history-track {
  display: flex;
  overflow-x: auto;
  cursor: grab;
  padding: 0 var(--gutter) 24px;
  /* Visible on purpose (unlike the testimonial track) — with 14 cards
     spanning several screen-widths, a scrollbar signals there's more to
     see, rather than the row silently trailing off past the edge. */
  scrollbar-width: thin;
  scrollbar-color: var(--maroon) var(--hairline);
}
.history-track:active { cursor: grabbing; }
.history-track::-webkit-scrollbar { height: 6px; }
.history-track::-webkit-scrollbar-track { background: var(--hairline); border-radius: 3px; }
.history-track::-webkit-scrollbar-thumb { background: var(--maroon); border-radius: 3px; }
.history-track::-webkit-scrollbar-thumb:hover { background: var(--brand-red); }
.history-card { flex: 0 0 380px; padding-right: 56px; }
.history-card__top {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 32px;
}
.history-card__year {
  flex: 0 0 80px;
  width: 80px; height: 80px;
  border-radius: 50%;
  background: #141414;
  /* The site's own dark mode swaps the page to a near-black bg too, which
     would otherwise swallow this fixed-dark circle — the border keeps it
     legible as a shape regardless of theme. */
  border: 1px solid rgba(255, 255, 255, 0.18);
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
}
.history-card__line { flex: 1; height: 1px; background: var(--hairline); }
.history-card h3 { font-size: 24px; font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--ink); margin-bottom: 16px; }
.history-card p { font-size: 15px; line-height: 1.6; color: rgba(var(--ink-rgb), 0.68); }

/* ---------------------------------- Values tabs (About) ---------------------------------- */

.values-block { display: grid; grid-template-columns: 1fr 1fr; gap: 60px; align-items: center; }
.values-tabs { display: flex; flex-direction: column; }
.values-tab {
  padding: 24px 0;
  border-top: 1px solid var(--hairline-dark);
  cursor: pointer;
}
.values-tab:last-child { border-bottom: 1px solid var(--hairline-dark); }
.values-tab__head { display: flex; align-items: center; gap: 20px; }
.values-tab__num { font-size: 13px; color: var(--white); }
.values-tab__head h4 { font-size: 22px; color: var(--white); text-transform: uppercase; }
.values-tab__body {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.4s var(--ease);
}
.values-tab.is-active .values-tab__body { max-height: 200px; }
.values-tab__body p {
  padding: 16px 0 4px 32px;
  color: var(--white-75);
  font-size: 15px;
  max-width: 46ch;
}

/* ---------------------------------- Role detail ---------------------------------- */

.role-detail__heading {
  font-size: 20px;
  text-transform: none;
  letter-spacing: 0;
  margin: 40px 0 14px;
}
.role-detail__prose p { color: rgba(var(--ink-rgb), 0.75); margin-bottom: 14px; }
.role-detail__prose p:last-child { margin-bottom: 0; }
.role-detail__list { display: flex; flex-direction: column; gap: 10px; }
.role-detail__list li {
  position: relative;
  padding-left: 22px;
  color: rgba(var(--ink-rgb), 0.75);
  line-height: 1.6;
}
/* "How to Apply" block at the end of each role description (shown while
   online applications are switched off). */
.role-apply-note {
  margin-top: 8px;
  padding-top: 4px;
  border-top: 1px solid var(--hairline);
}
.role-apply-note p { color: rgba(var(--ink-rgb), 0.75); }
.role-apply-note a { color: var(--maroon); font-weight: 500; text-decoration: underline; text-underline-offset: 3px; }
.role-apply-note a:hover { color: var(--ink); }
.role-detail__list li::before {
  content: '';
  position: absolute;
  left: 0; top: 9px;
  width: 6px; height: 6px;
  border-radius: 1px;
  background: var(--maroon);
}

/* ---------------------------------- Role modal ---------------------------------- */

body.modal-open { overflow: hidden; }

.role-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 6vh 20px;
  overflow-y: auto;
}
.role-modal[hidden] { display: none; }
.role-modal__backdrop {
  position: fixed;
  inset: 0;
  background: rgba(var(--black-rgb), 0.6);
  backdrop-filter: blur(4px);
}
.role-modal__dialog {
  position: relative;
  background: var(--cream);
  border-radius: 16px;
  width: 100%;
  max-width: 720px;
  padding: 48px;
  text-align: left;
}
.role-modal__close {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.role-modal__close svg { width: 16px; height: 16px; }
/* Link icon next to the close button: copies this role's shareable link. */
.role-modal__copy {
  position: absolute;
  top: 18px;
  right: 62px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: background 0.3s var(--ease), color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.role-modal__copy svg { width: 16px; height: 16px; }
.role-modal__copy:hover { background: var(--surface-dark); border-color: var(--surface-dark); color: var(--white); }
.role-modal__copy-check { display: none; }
.role-modal__copy.is-copied { color: var(--maroon); border-color: var(--maroon); }
.role-modal__copy.is-copied:hover { background: transparent; color: var(--maroon); border-color: var(--maroon); }
.role-modal__copy.is-copied .role-modal__copy-link { display: none; }
.role-modal__copy.is-copied .role-modal__copy-check { display: block; }
.role-modal__copy-tip {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  padding: 6px 10px;
  border-radius: 6px;
  background: var(--surface-dark);
  color: var(--white);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease);
  z-index: 2;
}
.role-modal__copy.is-copied .role-modal__copy-tip,
.role-modal__copy.is-showing-link .role-modal__copy-tip { opacity: 1; transform: none; }
.role-modal__copy.is-showing-link .role-modal__copy-tip { white-space: normal; width: max-content; max-width: min(320px, 70vw); pointer-events: auto; user-select: all; }
.role-modal__close:hover { background: var(--surface-dark); border-color: var(--surface-dark); color: var(--white); }

.role-modal__tabs {
  display: flex;
  gap: 28px;
  border-bottom: 1px solid var(--hairline);
  margin: 24px 0 28px;
}
.role-modal__tab {
  font-family: inherit;
  background: none;
  border: none;
  padding: 0 0 12px;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(var(--ink-rgb), 0.5);
  cursor: pointer;
  position: relative;
}
.role-modal__tab.is-active { color: var(--ink); }
.role-modal__tab.is-active::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 2px;
  background: var(--maroon);
}

.field--file { gap: 10px; }
.file-upload {
  display: flex;
  align-items: center;
  gap: 14px;
  border: 1px dashed rgba(var(--ink-rgb), 0.35);
  border-radius: 10px;
  padding: 14px 16px;
}
.field .file-upload__btn {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--surface-dark);
  color: var(--white);
  border-radius: 8px;
  padding: 10px 16px;
  cursor: pointer;
  white-space: nowrap;
}
.field .file-upload__btn:hover { background: var(--maroon); }
.file-upload__name { font-size: 14px; color: rgba(var(--ink-rgb), 0.6); }
.file-upload__toggle {
  align-self: flex-start;
  font-family: inherit;
  background: none;
  border: none;
  padding: 0;
  font-size: 13px;
  text-decoration: underline;
  color: rgba(var(--ink-rgb), 0.65);
  cursor: pointer;
}
.file-upload__toggle:hover { color: var(--maroon); }

/* ---------------------------------- Services accordion (Services) ---------------------------------- */

.services-accordion { display: flex; flex-direction: column; }
.services-accordion__item { border-top: 1px solid var(--hairline); scroll-margin-top: 100px; }
.services-accordion__item:last-child { border-bottom: 1px solid var(--hairline); }
.services-accordion__head {
  display: flex;
  align-items: center;
  gap: 20px;
  width: 100%;
  padding: 22px 0;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
}
.services-accordion__icon {
  width: 64px; height: 64px; border-radius: 12px; object-fit: cover; flex-shrink: 0;
  transition: opacity 0.4s var(--ease), width 0.4s var(--ease), margin-right 0.4s var(--ease);
}
.services-accordion__item.is-active .services-accordion__icon {
  opacity: 0;
  width: 0;
  margin-right: -20px;
}
.services-accordion__head h3 { flex: 1; font-size: clamp(20px, 2.4vw, 28px); color: var(--ink); }
.services-accordion__chevron {
  flex-shrink: 0;
  width: 26px; height: 26px;
  color: rgba(var(--ink-rgb), 0.5);
  transition: transform 0.4s var(--ease);
}
.services-accordion__item.is-active .services-accordion__chevron { transform: rotate(180deg); }
.services-accordion__body {
  position: relative;
  height: 0;
  border-radius: 20px;
  /* Height is set to an explicit px value by JS (initServiceAccordion in
     main.js) rather than driven by max-height or grid-template-rows —
     both of those looked fine at rest but didn't reliably interpolate
     smoothly frame-by-frame in testing (the box would jump most of the way
     there within a frame or two, well before the declared duration
     elapsed). An explicit px-to-px height transition is the one accordion
     technique that reliably animates smoothly across browsers. */
  transition: height 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* old Edge/IE */
}
.services-accordion__body::-webkit-scrollbar { display: none; } /* Chrome/Safari/Edge */
.services-accordion__item.is-active .services-accordion__body { margin-bottom: 24px; }
.services-accordion__bg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  filter: brightness(0.6);
  box-shadow: inset 0 0 0 2000px rgba(20, 20, 20, 0.55);
}
.services-accordion__body-clip {
  position: relative;
  display: flex;
  align-items: center;
  align-items: safe center;
  justify-content: center;
  min-height: 0;
  min-width: 0;
  width: 100%;
}
.services-accordion__body-inner {
  position: relative;
  padding: 48px 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 24px;
  max-width: 640px;
  margin: 0 auto;
}
.services-accordion__body-inner .lede { font-size: 18px; line-height: 1.6; max-width: none; color: var(--white); }
.services-accordion__body-inner .btn { font-size: 12px; padding: 9px 14px; gap: 6px; }
.services-accordion__body-inner .btn svg { width: 12px; height: 12px; }
.services-accordion__body-inner .btn:hover { background: var(--brand-red); border-color: var(--brand-red); color: var(--white); }
.services-accordion__features {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  list-style: none;
  padding: 0;
  margin: 0;
}
.services-accordion__features li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--white);
  text-align: left;
}
.services-accordion__features li::before {
  content: '';
  flex-shrink: 0;
  width: 9px; height: 9px;
  border-radius: 2px;
  background: var(--maroon);
}

/* ---------------------------------- Open Roles (Careers) ---------------------------------- */

.roles-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 28px;
  text-align: left;
}
/* display:grid above otherwise wins the cascade over the browser's own
   [hidden] rule (same specificity, this stylesheet loads later) and the
   postings stay visible even with the attribute set. */
.roles-grid[hidden] { display: none; }
.role-card {
  background: var(--cream);
  border: 1px solid var(--hairline-dark);
  border-radius: 16px;
  padding: 40px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.role-card__dept {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--maroon);
}
.role-card h4 { font-size: 26px; text-transform: none; letter-spacing: 0; color: var(--ink); line-height: 1.2; }
.role-card__location { font-size: 16px; color: rgba(var(--ink-rgb), 0.65); }
.role-card__tags { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
.role-card__tag {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  /* A bright brand-red outline in both themes. Light mode: white chip with
     near-black text; dark mode (below): dark chip with white text. */
  color: #141414;
  border: 1px solid #d0304f;
  background: #ffffff;
  border-radius: 6px;
  padding: 6px 12px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .role-card__tag { color: #ffffff; background: #1c1e22; }
}
:root[data-theme="dark"] .role-card__tag { color: #ffffff; background: #1c1e22; }
/* The tags + View Role button sit together at the bottom of each card:
   margin-top:auto on the card's tag row pushes both down, so tags and
   buttons line up across a row even when titles or locations wrap to
   different heights (the grid stretches cards in a row to match).
   Scoped to the card; the same tag row in the job popup is unaffected. */
.role-card > .role-card__tags { margin-top: auto; }
.role-card__actions { display: flex; gap: 12px; }
.role-card__apply { align-self: flex-start; }

/* ---------------------------------- Leadership ---------------------------------- */

.leadership-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
}
.leader-card img {
  width: 100%; aspect-ratio: 1/1; object-fit: cover; border-radius: 16px; margin-bottom: 16px;
}
.leader-card h4 { font-size: 17px; text-transform: none; letter-spacing: 0; }
.leader-card p { font-size: 13px; color: var(--maroon); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 4px; }

.leader-card__meta {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.leader-card__linkedin {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 1px solid var(--hairline);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  transition: all 0.35s var(--ease);
}
.leader-card__linkedin:hover { background: var(--maroon); border-color: var(--maroon); color: var(--white); }
.leader-card__linkedin svg { width: 15px; height: 15px; }

/* ---------------------------------- Text mask hero (About) ---------------------------------- */

.text-mask-hero {
  /* Same height as the photo banners on the other pages (72vh on desktop,
     300px on phones), with the heading centered vertically in it. */
  min-height: 72vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 180px var(--gutter) 60px;
  max-width: 1400px;
  margin: 0 auto;
  overflow: hidden;
}
@media (max-width: 900px) {
  .text-mask-hero { min-height: 300px; padding-top: 110px; padding-bottom: 30px; }
}
.text-mask-hero__inner {
  animation: heroTextIn 1.1s var(--ease) 0.2s both;
}
.text-mask-hero h1 {
  font-size: clamp(36px, 7.2vw, 104px);
  line-height: 1.05;
  background-image: url('../assets/images/about-hero-texture.jpg');
  background-size: cover;
  background-position-x: center;
  background-position-y: 50%;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
/* The texture image is dark, so in dark mode it reads almost invisible
   against the (now also dark) page — a translucent white film brightens it
   back up to the same visible-through-the-letters look light mode gets. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .text-mask-hero h1 {
    background-image: linear-gradient(rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.55)), url('../assets/images/about-hero-texture.jpg');
    background-size: cover, cover;
    /* The white film must repeat: main.js shifts background-position-y on
       scroll to pin the texture to the viewport, and that shift applies to
       every layer — a non-repeating film slides down with it and leaves the
       top of the heading uncovered (dark letters on a dark page). */
    background-repeat: repeat, no-repeat;
    background-position-x: center, center;
    background-position-y: 50%, 50%;
  }
}
:root[data-theme="dark"] .text-mask-hero h1 {
  background-image: linear-gradient(rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.55)), url('../assets/images/about-hero-texture.jpg');
  background-size: cover, cover;
  background-repeat: repeat, no-repeat;
  background-position-x: center, center;
  background-position-y: 50%, 50%;
}
/* Keep "Logic Technology, Inc" from breaking mid-phrase — below 600px the
   shrunk-down font can't fit it on one line even after the vw tuning above,
   so let it wrap naturally there like it always has. */
@media (min-width: 600px) {
  .text-mask-hero h1 { white-space: nowrap; }
}

.text-mask-hero__line2 { display: block; text-align: left; }

.text-mask-hero__eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 40px;
  text-align: center;
}
.text-mask-hero__eyebrow svg { width: 14px; height: 14px; }

/* ---------------------------------- Cookie consent ---------------------------------- */

.cookie-banner {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 300;
  background: var(--surface-dark);
  box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.2);
  transform: translateY(100%);
  transition: transform 0.4s var(--ease);
}
.cookie-banner.is-visible { transform: translateY(0); }
.cookie-banner__inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: 24px var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}
.cookie-banner p { font-size: 14px; line-height: 1.6; color: var(--white-75); max-width: 640px; margin: 0; }
.cookie-banner__actions { display: flex; align-items: center; gap: 20px; flex-shrink: 0; }
.cookie-banner__actions .btn--maroon { background: var(--maroon); border-color: var(--maroon); color: var(--white); }
.cookie-banner__actions .btn--maroon:hover { background: var(--white); border-color: var(--white); color: var(--surface-dark); }
.cookie-banner__manage {
  font-family: inherit;
  background: none;
  border: none;
  padding: 0;
  font-size: 13px;
  text-decoration: underline;
  color: var(--white-75);
  cursor: pointer;
}
.cookie-banner__manage:hover { color: var(--white); }

.cookie-modal {
  position: fixed;
  inset: 0;
  z-index: 310;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6vh 20px;
  overflow-y: auto;
}
.cookie-modal[hidden] { display: none; }
.cookie-modal__backdrop {
  position: fixed;
  inset: 0;
  background: rgba(var(--black-rgb), 0.6);
  backdrop-filter: blur(4px);
}
.cookie-modal__dialog {
  position: relative;
  background: var(--cream);
  border-radius: 16px;
  width: 100%;
  max-width: 560px;
  padding: 48px;
  text-align: left;
}
.cookie-modal__dialog h3 { font-size: 22px; margin-bottom: 12px; }
.cookie-modal__dialog > p { font-size: 14px; color: rgba(var(--ink-rgb), 0.7); margin-bottom: 28px; }
.cookie-modal__close {
  position: absolute;
  top: 18px;
  right: 18px;
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.cookie-modal__close svg { width: 16px; height: 16px; }
.cookie-modal__close:hover { background: var(--surface-dark); border-color: var(--surface-dark); color: var(--white); }
.cookie-modal__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 18px 0;
  border-top: 1px solid var(--hairline);
}
.cookie-modal__row:last-of-type { border-bottom: 1px solid var(--hairline); margin-bottom: 28px; }
.cookie-modal__row h4 { font-size: 15px; text-transform: none; letter-spacing: 0; color: var(--ink); margin-bottom: 4px; }
.cookie-modal__row p { font-size: 13px; color: rgba(var(--ink-rgb), 0.6); }

.cookie-switch { position: relative; display: inline-block; width: 44px; height: 24px; flex-shrink: 0; }
.cookie-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.cookie-switch__track {
  position: absolute; inset: 0;
  background: rgba(var(--ink-rgb), 0.2);
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.35s var(--ease);
}
.cookie-switch__track::before {
  content: '';
  position: absolute;
  left: 3px; top: 3px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--white);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  transition: transform 0.35s var(--ease);
}
.cookie-switch input:checked + .cookie-switch__track { background: var(--maroon); }
.cookie-switch input:checked + .cookie-switch__track::before { transform: translateX(20px); }
.cookie-switch--disabled { opacity: 0.6; }
.cookie-switch--disabled .cookie-switch__track { cursor: not-allowed; }

/* ---------------------------------- Theme toggle ---------------------------------- */

.theme-toggle {
  position: fixed;
  bottom: 24px;
  left: 24px;
  z-index: 320;
  /* Deliberately low-key: small, no shadow, and mostly faded out until
     hovered or focused, so it's there for anyone looking for it without
     competing with the page. */
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--cream);
  border: 1px solid var(--hairline);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  cursor: pointer;
  opacity: 0.35;
  transition: opacity 0.35s var(--ease), background 0.4s var(--ease), border-color 0.4s var(--ease), transform 0.4s var(--ease), bottom 0.4s var(--ease);
}
.theme-toggle:hover,
.theme-toggle:focus-visible { opacity: 1; transform: scale(1.06); }
/* The cookie banner sits in this same corner while it's up — shift the
   toggle above it instead of letting the two overlap. */
body.has-cookie-banner .theme-toggle { bottom: 120px; }
@media (max-width: 900px) {
  body.has-cookie-banner .theme-toggle { bottom: 270px; }
  /* On the homepage the hero's tab bar becomes a 2-row grid at this width
     and lands right in the toggle's corner — same fix, different offender. */
  body.has-hero-tabs .theme-toggle { bottom: 150px; }
  body.has-hero-tabs.has-cookie-banner .theme-toggle { bottom: 390px; }
}
.theme-toggle__icon {
  width: 16px;
  height: 16px;
  position: absolute;
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease);
}
.theme-toggle__icon--moon { opacity: 0; transform: scale(0.5) rotate(-30deg); }
.theme-toggle__icon--sun { opacity: 1; transform: scale(1) rotate(0deg); }
.theme-toggle.is-dark .theme-toggle__icon--moon { opacity: 1; transform: scale(1) rotate(0deg); }
.theme-toggle.is-dark .theme-toggle__icon--sun { opacity: 0; transform: scale(0.5) rotate(30deg); }

/* ---------------------------------- Responsive ---------------------------------- */

@media (max-width: 900px) {
  .main-nav__links, .main-nav .btn { display: none; }
  .nav-toggle { display: block; }
  /* --mobile-nav-offset is the header's real measured height (see
     initMobileNav in main.js) — it changes between scrolled/unscrolled
     states, so a hardcoded px value here would drift out of sync and leave
     a gap or overlap. Falls back to 64px if JS hasn't set it yet.
     Sized with vh rather than inset/bottom:0 because .site-header has
     backdrop-filter, which makes it the containing block for fixed
     descendants — "bottom: 0" would resolve against the header's own small
     box instead of the real viewport; vh bypasses that. */
  .main-nav.is-open::before {
    content: '';
    position: fixed;
    top: var(--mobile-nav-offset, 64px);
    left: 0;
    right: 0;
    height: calc(100vh - var(--mobile-nav-offset, 64px));
    background: rgba(0, 0, 0, 0.5);
    z-index: 89;
  }
  .main-nav.is-open .main-nav__links {
    display: flex;
    flex-direction: column;
    position: fixed;
    top: var(--mobile-nav-offset, 64px);
    left: 0;
    right: 0;
    max-height: calc(100vh - var(--mobile-nav-offset, 64px));
    background: var(--black);
    padding: 24px var(--gutter);
    gap: 4px;
    z-index: 90;
    overflow-y: auto;
  }
  /* Padded to a proper touch-target height (was a 30px text-only hit area
     with gap doing the visual spacing) without changing the link spacing
     the menu was designed around. */
  .main-nav.is-open .main-nav__links a { padding: 12px 0; }
  .main-nav.is-open .btn { display: inline-flex; margin: 0 var(--gutter); }

  /* The open mobile panel is always a solid dark fill regardless of theme
     or scroll state, but the link-color rules above assume a light bar
     once the header is scrolled/light — without this override that makes
     the links render near-black-on-near-black and vanish. */
  .site-header .main-nav.is-open .main-nav__links a {
    color: var(--white-75);
  }
  .site-header .main-nav.is-open .main-nav__links a:hover,
  .site-header .main-nav.is-open .main-nav__links a.is-active {
    color: var(--white);
  }

  .hero-dark__tabs { grid-template-columns: repeat(2, 1fr); }
  .two-col, .values-block { grid-template-columns: 1fr; }
  .services-grid { grid-template-columns: 1fr; }
  /* Single-column cards no longer need the padding/height sized for a
     wide two-up card — that left mostly empty space around the short
     number+title+arrow content and made the list feel very sparse. */
  .service-card { padding: 28px; min-height: 0; gap: 24px; }
  /* Fixed desktop card widths (460px / 380px) both overflow a phone
     viewport with nothing peeking in from the next card, so the row
     doesn't read as a horizontal scroller. Narrower cards here leave a
     visible sliver of the next one as that affordance. */
  .testimonial-card { flex-basis: 84vw; }
  .history-card { flex-basis: 78vw; padding-right: 28px; }
  .stats-strip {
    grid-template-columns: repeat(2, 1fr);
    /* At this min-height the 2x2 grid's two rows otherwise stretch to
       evenly split the full height, leaving dead space above row 1 (on
       top of the photo) that this same gap on row 2 hides by just being
       part of the visible photo band. space-between keeps that middle
       photo reveal but pins row 1 flush to the top edge instead. */
    align-content: space-between;
    /* Both panels in a row share one height — otherwise a label that wraps
       to two lines ("World Class Engineers") makes its panel taller than
       its neighbour's, and with the default bottom alignment the two
       tops no longer line up. Stretch keeps each pair the same height, and
       top-aligned content keeps the two numbers level whichever label wraps. */
    align-items: stretch;
  }
  .stat {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
  }
  .stat:nth-child(2) { border-right: none; }
  .leadership-grid { grid-template-columns: repeat(2, 1fr); }
  .form-row { grid-template-columns: 1fr; }
  .site-footer__top { flex-direction: column; align-items: center; text-align: center; }
  .footer-cols { gap: 40px; width: 100%; justify-content: center; text-align: center; }
  .site-footer__bottom { flex-direction: column; text-align: center; }
  .cookie-banner__inner { flex-direction: column; align-items: flex-start; }
  .cookie-banner__actions { width: 100%; flex-wrap: wrap; }
  .cookie-banner__manage { flex-basis: 100%; }
  .cookie-banner__actions .btn { flex: 1; justify-content: center; }
}
