/* =========================================================
   On-Time Logistics Company — main stylesheet
   Colors: corporate blue + white, per brand direction.
   Fonts: Space Grotesk (headings), Work Sans (body).
   ========================================================= */

:root {
  --blue: oklch(52% 0.19 258);
  --blue-dark: oklch(38% 0.16 258);
  --cyan: oklch(58% 0.14 210);
  --gold: oklch(80% 0.15 85);
  --gold-dark: oklch(72% 0.15 78);
  --navy: oklch(24% 0.07 258);
  --navy-light: oklch(32% 0.08 258);
  --ink: oklch(22% 0.03 260);
  --muted: oklch(46% 0.02 260);
  --bg: oklch(98.5% 0.004 90);
  --card: oklch(96.5% 0.012 260);
  --line: oklch(90% 0.012 260);
  --white: oklch(100% 0 0);
}

* {
  box-sizing: border-box;
}

html {
  /* One-page site now (per Lasha) — nav links are #anchors, so this
     makes clicking About Us/Services/Contact glide down instead of
     jumping instantly. */
  scroll-behavior: smooth;
}

/* Corporate-navy grid pattern, used as the page's base canvas everywhere
   nothing else covers it (behind Services/Calculator/Contact, the
   header, and the gap between Hero and About). Two thin repeating lines
   (one vertical, one horizontal) on the navy base — subtle graph-paper
   texture rather than a loud pattern. Per Lasha: restored site-wide
   after a brief experiment confining it to just the header/divider/
   cards read as "the site is broken" rather than calmer — the grid
   belongs everywhere, showing through behind the photos wherever they
   fade to transparent (see .hero/.about-hero/.section-divider below).
   Line color is Lasha's own hex pick (#0B2A53), solid rather than the
   translucent oklch tint this used to be — same pattern in .site-header
   just below, kept identical so the header and page grid tile
   seamlessly into one another. */
body {
  margin: 0;
  font-family: 'Work Sans', system-ui, sans-serif;
  color: var(--ink);
  background-color: var(--navy);
  background-image:
    linear-gradient(#0B2A53 1px, transparent 1px),
    linear-gradient(90deg, #0B2A53 1px, transparent 1px);
  background-size: 48px 48px;
  /* Belt-and-suspenders against horizontal overflow (found and fixed one
     real cause — a stray absolutely-positioned input stretching to
     1300+px — but this stops any FUTURE regression like it from ever
     showing as a scrollable strip of empty background past the edge of
     the page, instead of it needing to be tracked down again). Also lets
     a single long, unbreakable word wrap instead of forcing its own
     overflow — relevant once the Georgian translation goes in, since
     Georgian compounds run long with no natural break point. */
  overflow-x: hidden;
  overflow-wrap: break-word;
}

/* Sticky header is 76px tall — without this, jumping to an #anchor lands
   the section right under it, with its top few pixels hidden behind the
   header. Applies to every anchor-able section (About/Services/Contact). */
main section[id] {
  scroll-margin-top: 92px;
}

h1, h2, h3 {
  font-family: 'Space Grotesk', 'Work Sans', system-ui, sans-serif;
  margin: 0;
  letter-spacing: -0.01em;
}

p {
  margin: 0;
}

a {
  color: var(--blue);
  text-decoration: none;
}

a:hover {
  color: var(--blue-dark);
}

.container {
  max-width: 1400px;
  margin: 0 auto;
  padding: 0 32px;
}

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

.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: 'Work Sans', sans-serif;
  font-weight: 600;
  font-size: 16px;
  padding: 14px 26px;
  border-radius: 10px;
  white-space: nowrap;
  /* Some of these are <a> tags, some are <button type="submit">. Without
     this, <button> keeps the browser's default 1px border, which made the
     button-based CTAs (Calculate, Request a quote) show a visible ring
     that the anchor-based ones (Start Now) never had. .btn-outline and
     .btn-outline-gold set their own border further down and still win. */
  border: none;
  cursor: pointer;
}

.btn-primary {
  background: var(--blue);
  color: var(--white);
}

.btn-primary:hover {
  background: var(--blue-dark);
  color: var(--white);
}

.btn-small {
  padding: 11px 20px;
  font-size: 14px;
}

.btn-light {
  background: var(--white);
  color: var(--ink);
}

.btn-accent {
  background: var(--gold);
  color: var(--ink);
  border-radius: 999px;
  font-weight: 700;
}

.btn-accent:hover {
  background: var(--gold-dark);
  color: var(--ink);
}

.btn-outline-gold {
  background: transparent;
  color: var(--gold);
  border: 1px solid var(--gold);
  border-radius: 999px;
  font-weight: 600;
}

.btn-outline-gold:hover {
  background: var(--gold);
  color: var(--ink);
}

/* Same pill shape as .btn-accent, but in the site's cyan accent — for
   the .services-cta "Talk to a specialist" button, so that CTA doesn't
   read as yet another gold button competing with the ones elsewhere. */
.btn-cyan {
  /* Lasha's exact pick: rgba(11, 200, 233, 1) = #0BC8E9 — brighter/more
     saturated than the sitewide var(--cyan), used only for these two
     CTA buttons rather than changed globally. */
  background: #0bc8e9;
  color: var(--ink);
  border-radius: 999px;
  font-weight: 700;
}

.btn-cyan:hover {
  background: #3ad4ee;
  color: var(--ink);
}

.btn-link {
  font-weight: 600;
  font-size: 15px;
  padding: 12px 4px;
  border-bottom: 2px solid var(--line);
  border-radius: 0;
}

.btn-link:hover {
  border-color: var(--blue);
  color: var(--blue);
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--blue);
}

/* ---------- Header ----------
   Just the logo + nav row. (The old dispatch/booking strip and, later,
   the floating contact box have both been removed per Lasha — contact
   info will live in #contact, linked from the "Contact" nav item, once
   that flow is finalized.) */

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  /* Per Lasha: header now carries the same grid-pattern canvas as the
     rest of the page (was solid navy) — both start their pattern at the
     very top of the document (y:0), so the tiling lines up seamlessly
     with the grid revealed through .hero's new top fade just below it,
     instead of a hard-edged solid bar sitting on top of the photo. */
  background-color: var(--navy);
  background-image:
    linear-gradient(#0B2A53 1px, transparent 1px),
    linear-gradient(90deg, #0B2A53 1px, transparent 1px);
  background-size: 48px 48px;
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 76px;
  /* Was the shared, centered .container (max-width 1400px, margin: 0
     auto) — per Lasha, that left a visible gap before the logo on wide
     screens instead of hugging the true left edge. Same left/right inset
     as the rest of the page now, so the logo and the nav/search/GE|EN
     group line up with Hero/Services/Calculator/Contact's edges too. */
  padding-left: clamp(20px, 2.5vw, 56px);
  padding-right: clamp(20px, 2.5vw, 56px);
}

/* Groups nav + search + language switch together on the right, so
   .header-inner only has to split logo vs. everything-else. */
.header-right {
  display: flex;
  align-items: center;
  gap: 40px;
}

.logo {
  display: flex;
  align-items: center;
  gap: 10px;
}

.logo-mark {
  display: inline-block;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: conic-gradient(from 210deg, var(--blue), var(--cyan) 40%, var(--blue) 100%);
}

.logo-mark-small {
  width: 20px;
  height: 20px;
}

.logo-text {
  display: flex;
  flex-direction: column;
  line-height: 1.05;
}

.logo-title {
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.logo-subtitle {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--muted);
}

.logo-img {
  display: block;
  height: 48px;
  width: auto;
}

.logo-img-small {
  height: 22px;
}

.main-nav {
  display: flex;
  align-items: center;
  /* Slightly tighter now that each link carries its own box (padding
     already adds visual separation, so the links don't need as much raw
     gap between them as plain text links did). */
  gap: 12px;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* Per Lasha: nav links now match the site's "boxed" language everywhere
   else (Hero/About/Services cards) — thin, translucent boxes with a
   soft shadow, same family as .nav-search below so the whole right side
   of the header reads as one consistent system. Lifts slightly on hover
   as the one piece of feedback (these do navigate, unlike .nav-search,
   which stays static — see its own comment). */
.main-nav a {
  display: inline-flex;
  align-items: center;
  color: oklch(88% 0.02 260);
  padding: 9px 16px;
  /* Per Lasha: the old near-transparent fill (4% white) let the header's
     grid-pattern lines show straight through the boxes — darkened to a
     solid-reading navy (plus a blur, same recipe as the page's other
     translucent cards) so the boxes read as opaque pills, not windows
     onto the grid behind them. */
  background: oklch(22% 0.05 258 / 0.8);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid oklch(100% 0 0 / 0.14);
  border-radius: 10px;
  box-shadow: 0 6px 16px oklch(10% 0.05 258 / 0.3);
  transition: transform 0.25s ease, background-color 0.25s ease,
    border-color 0.25s ease, box-shadow 0.25s ease, color 0.2s ease;
}

.main-nav a:hover {
  color: var(--white);
  transform: translateY(-3px);
  background: oklch(28% 0.06 258 / 0.88);
  border-color: oklch(100% 0 0 / 0.26);
  box-shadow: 0 10px 22px oklch(10% 0.05 258 / 0.4);
}

@media (prefers-reduced-motion: reduce) {
  .main-nav a:hover {
    transform: none;
  }
}

.main-nav a.nav-disabled {
  color: oklch(55% 0.03 260);
  cursor: default;
}

.main-nav a.nav-disabled:hover {
  color: oklch(55% 0.03 260);
  transform: none;
  background: oklch(22% 0.05 258 / 0.8);
  border-color: oklch(100% 0 0 / 0.14);
  box-shadow: 0 6px 16px oklch(10% 0.05 258 / 0.3);
}

/* ---------- Header utility ----------
   Used to hold the search box (removed per Lasha — visual only, no
   search backend, just a non-functional box) and, before that, the
   GE/EN language toggle (also removed — see index.html's
   header-utility for why). Kept as an empty wrapper in the markup in
   case something real lands here later; harmless with nothing inside
   it. */
.header-utility {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* ---------- Hero ----------
   New hero-truck.jpg (highway/trees shot) has the truck sitting in the
   right ~65% of the frame, with genuinely open trees/sky/road on the
   left third — that's where the copy lives now. background-size:cover
   never crops horizontally here (the photo is wider than tall relative
   to the hero), so that left-empty-third holds regardless of screen
   width; only the top/bottom get cropped as the hero gets taller or
   shorter. The gradient runs left-to-right (not top-to-bottom like the
   old photo) so it darkens the open trees/road for text legibility but
   fades out well before the truck itself, leaving the truck untouched. */

.hero {
  position: relative;
  /* Per Lasha: on wide screens (his own 24" monitor included) the fixed
     600px height was noticeably shorter than the photos' native 2.33:1
     shape, so background-size:cover was cropping a good chunk off the
     top/bottom — tires and asphalt were getting cut off. aspect-ratio
     ties the box's height to its width in the SAME ratio as the actual
     photo files (all four are exactly 1568x672), so at most screen
     widths the full photo shows with no vertical cropping at all — no
     more, no less than the image actually has.
     min-height keeps mobile/narrow screens at the same 600px they had
     before (below ~1400px wide, aspect-ratio alone would make the hero
     too short for the text card) — unchanged there, so this only ever
     helps, never hurts.
     max-height stops it from growing indefinitely on ultra-wide
     monitors, where matching the ratio exactly would make Hero
     enormous (browsers clamp the aspect-ratio height against these two
     automatically). */
  /* Explicit width:100% — without it, Chromium's aspect-ratio + max-height
     combination can solve width FROM the clamped height instead of the
     other way around once max-height engages (seen on ultra-wide test
     screens: the hero visibly stopped short of the right edge instead of
     spanning it). Pinning width removes that ambiguity. */
  width: 100%;
  aspect-ratio: 1568 / 672;
  min-height: 600px;
  max-height: 820px;
  display: flex;
  /* Bottom-anchored, but raised off the true bottom edge and pulled
     further toward the left edge per Lasha — with the card now boxed
     (see .hero-copy), it was sitting too close to the truck and too
     close to the bottom of the frame. This flex container hugs its one
     normal-flow child (.hero-copy) exactly, so padding-top/padding-bottom
     directly control the card's on-screen position: less top padding
     raises it, more bottom padding pushes it further from the bottom
     edge/dots. */
  align-items: flex-end;
  padding-top: 20px;
  padding-bottom: 100px;
  /* Fixed left inset (not the shared centered .container) so the text
     always hugs the true left edge, on any screen width. */
  padding-left: clamp(20px, 2.5vw, 56px);
  /* Slides move via transform: translateX() (see .hero-slide below) and
     must never spill outside the hero box while off-screen. */
  overflow: hidden;
}

/* ---------- Hero photo carousel ----------
   .hero-media is the whole photo layer, sized to fill .hero. It holds:
   one .hero-slide per photo (only ever one on screen at a time — see
   js/script.js for how it swaps them), plus .hero-gradient, the same
   left-to-right darkening this section always had, now painted once on
   top of ALL slides instead of baked into a single background-image.
   The two-sided top/bottom fade (into the header above and
   .section-divider below) lives here too, not on .hero itself, so it
   only ever fades the PHOTO — .hero-copy and .hero-dots stay fully
   opaque regardless of scroll position. */
.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

/* Wraps ONLY the photo (slides + darkening gradient) — the top/bottom
   mask-image fade below is scoped to this layer alone, not to the whole
   of .hero-media, specifically so it never touches .hero-dots (a sibling
   of this wrapper, not a child of it — see index.html). Dots briefly
   lived directly inside the masked layer and got faded to invisible
   along with the photo, since bottom:20px falls inside the mask's last
   56px transparent zone. */
.hero-photo-layer {
  position: absolute;
  inset: 0;
  overflow: hidden;
  /* Two-sided fade, per Lasha: feathers in from transparent over the
     first 48px (right under the sticky header, which shares this same
     grid pattern — see .site-header — so the photo emerges out of the
     header's canvas instead of starting on a hard line under it), AND
     feathers to transparent over the last 56px, letting the
     grid-pattern body background show through instead of ending on a
     hard edge — the "gentle transition" into .section-divider and
     .about-hero below. */
  mask-image: linear-gradient(to bottom, transparent 0, black 48px, black calc(100% - 56px), transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, black 48px, black calc(100% - 56px), transparent 100%);
}

.hero-slide {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center center;
  /* Waiting off-screen to the right by default — js/script.js slides the
     active one to 0 and the one it replaces to -100%, which is what
     produces the right-to-left motion. Every slide not currently
     involved in a transition sits here, invisible, until its turn. */
  transform: translateX(100%);
  transition: transform 1000ms cubic-bezier(0.65, 0, 0.35, 1);
}

.hero-slide.is-active {
  transform: translateX(0);
  z-index: 2;
}

.hero-gradient {
  position: absolute;
  inset: 0;
  /* Above every .hero-slide (they only ever reach z-index: 2) so the
     text-legibility darkening is constant no matter which photo is
     showing. */
  z-index: 5;
  /* Reverted a brief experiment that painted the grid as a visible film
     over the photo itself, fading with scroll depth — per Lasha, that
     read as broken, not intentional. Grid stays off the visible photo;
     it belongs only on the body canvas showing through behind it (see
     body, above), same as before. */
  background-image: linear-gradient(90deg, oklch(15% 0.06 258 / 0.72) 0%, oklch(15% 0.06 258 / 0.4) 22%, transparent 34%);
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .hero-slide {
    transition: none;
  }
}

.hero-copy {
  position: relative;
  z-index: 1;
  /* Kept narrow on purpose: the open (tree/sky) strip in the photo is
     only about a third of the frame's width, and that fraction doesn't
     change with window width since the photo isn't cropped horizontally.
     A wider block would start running into the truck's cab on ordinary
     laptop screens (not just Lasha's ultra-wide monitor). */
  max-width: 420px;
  /* Per Lasha: headline + subtext + stats now live together in one
     translucent "card" (same frosted recipe .hero-stats used to carry on
     its own — see below) instead of just the stats having a backdrop.
     The card sits outside .hero-media, so it stays put in the same spot
     while the photo behind it keeps auto-advancing — only the picture
     moves, never this box. */
  background: oklch(15% 0.05 258 / 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid oklch(100% 0 0 / 0.1);
  border-radius: 18px;
  padding: 28px 32px;
  box-shadow: 0 18px 40px oklch(10% 0.05 258 / 0.35);
  transition: transform 0.5s ease;
}

/* Subtle "breathing" pulse on hover, per Lasha — a gentle cue that the
   card is interactive/alive, not a static caption. Runs only while the
   cursor is actually over the card, and only in one place (never moves
   position), so it never fights the carousel underneath it. */
@keyframes hero-copy-pulse {
  0%, 100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.018);
  }
}

.hero-copy:hover {
  animation: hero-copy-pulse 1.8s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .hero-copy:hover {
    animation: none;
  }
}

.hero-copy .eyebrow-light::before,
.about-copy .eyebrow-light::before {
  content: "";
  display: block;
  width: 56px;
  height: 3px;
  background: var(--cyan);
  margin-bottom: 14px;
}

.eyebrow-light {
  color: oklch(85% 0.05 210);
}

.hero-subtext {
  font-size: 16px;
  line-height: 1.6;
  color: oklch(92% 0.01 260);
  margin-top: 20px;
  max-width: 38ch;
}

.hero h1 {
  font-family: 'Oswald', 'Space Grotesk', system-ui, sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  /* Sized to fit the ~420px-wide open strip in the new photo without
     wrapping mid-word on ordinary (non-ultra-wide) screens — see the
     .hero-copy comment for why the column itself stays narrow. */
  font-size: 46px;
  line-height: 1.12;
  letter-spacing: 0.005em;
  margin-top: 0;
  color: var(--white);
  text-shadow: 0 2px 20px oklch(15% 0.05 258 / 0.45);
}

/* ---------- Hero stat strip ----------
   Moved from bottom-right-of-photo (absolute) to the same left column as
   the headline, right under the subtext — per Lasha's markup. It's a
   normal block now (no more position:absolute), so it just stacks under
   .hero-subtext in document order. */
.hero-stats {
  display: flex;
  gap: 24px;
  margin-top: 26px;
  /* Own backdrop removed — it now lives one level up on .hero-copy, which
     wraps the headline + subtext + this stat row into a single card (per
     Lasha). Kept as its own block so the divider lines between stats
     still work exactly as before. */
}

.hero-stat {
  padding-left: 18px;
  border-left: 1px solid oklch(100% 0 0 / 0.3);
}

.hero-stat:first-child {
  padding-left: 0;
  border-left: none;
}

.hero-stat-number {
  display: block;
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 700;
  font-size: 24px;
  color: var(--white);
}

.hero-stat-label {
  display: block;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: oklch(80% 0.02 260);
  margin-top: 4px;
  line-height: 1.4;
}

/* Dot row for the hero photo carousel — one dot per slide, sitting
   inside .hero's own padding-bottom (empty space below .hero-stats), so
   it never overlaps the headline/stats column. drop-shadow keeps the
   dots readable regardless of which photo/how bright it is behind
   them. */
.hero-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 20px;
  z-index: 1;
  display: flex;
  justify-content: center;
  gap: 10px;
  filter: drop-shadow(0 1px 4px oklch(15% 0.05 258 / 0.55));
}

.hero-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: oklch(100% 0 0 / 0.4);
  border: none;
  padding: 0;
  cursor: pointer;
  transition: background 0.25s ease, transform 0.25s ease;
}

.hero-dot:hover {
  background: oklch(100% 0 0 / 0.7);
}

.hero-dot.is-active {
  background: var(--white);
  transform: scale(1.25);
}

/* Generic placeholder box — used wherever a real photo is still pending
   (e.g. inside the services/routes sections later on). */
.image-placeholder {
  width: 100%;
  height: 100%;
  min-height: 320px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 24px;
  background:
    repeating-linear-gradient(45deg, var(--line) 0, var(--line) 1px, transparent 1px, transparent 14px);
  border: 1px dashed var(--line);
  border-radius: 20px;
  color: var(--muted);
  font-size: 14px;
  font-weight: 500;
}

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

.services {
  /* Per Lasha: trimmed ~18% off this section's own top/bottom padding
     (100px -> 82px, same reduction across .calculator/.process/
     .partners/.contact below) — the gap between two boxed sections is
     the sum of both their paddings, so a big desktop screen was leaving
     noticeably more dead space between boxes than felt right. */
  padding-top: 82px;
  padding-bottom: 82px;
  /* Same left inset as .hero/.about-hero (not the shared centered
     .container) so .services-box lines up on exactly the same left edge
     as .hero-copy/.about-copy when scrolling — per Lasha, "What We Do"
     was visibly offset from the boxes above it. Mirrored on the right so
     .services-box reads as a centered-ish panel rather than one hugging
     only the left edge. */
  padding-left: clamp(20px, 2.5vw, 56px);
  padding-right: clamp(20px, 2.5vw, 56px);
}

/* One big transparent card wrapping the heading + the whole services
   grid, per Lasha — explicitly the same plain frosted-glass recipe as
   .hero-copy/.about-copy (NOT the finer grid-textured look the individual
   .service-card items below use — he was clear this outer box should
   have no texture of its own, "უბრალოდ გამჭვირვალე ბოქსი"). */
.services-box {
  position: relative;
  /* Full width edge-to-edge (no max-width cap), per Lasha — the box now
     fills exactly from the left inset to the right inset set on
     .services below, same as Hero/About's photo layer, instead of
     capping out and leaving a blank strip on wide/ultra-wide screens.
     See .services-grid below for how the card grid avoids an awkward
     5th/6th column now that there's more width to fill. */
  background: oklch(15% 0.05 258 / 0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid oklch(100% 0 0 / 0.1);
  border-radius: 22px;
  padding: 48px clamp(24px, 4vw, 56px) 56px;
  box-shadow: 0 18px 40px oklch(10% 0.05 258 / 0.35);
}

.services h2 {
  font-family: 'Oswald', 'Space Grotesk', system-ui, sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  font-size: 32px;
  /* No eyebrow above it anymore ("What We Do" IS the heading now, per
     Lasha) — was 14px to clear the eyebrow line above; 0 now that it's
     the first element in the section (now the first element inside
     .services-box). */
  margin-top: 0;
  max-width: 56ch;
  /* Section no longer has a light background (dark grid canvas now sits
     behind it per Lasha's request), so the heading needs an explicit
     light color instead of inheriting var(--ink). */
  color: var(--white);
}

.services-grid {
  display: grid;
  /* Fixed column count, not auto-fit — now that .services-box is full
     width edge-to-edge, auto-fit would keep adding columns as the screen
     gets wider and orphan a short last row. 10 cards now (was 8, until
     Air Shipments + Warehousing were added per Lasha) — 5 is the base/
     desktop count so two full rows of 5 land evenly; the breakpoint
     below switches to 2 (5 rows of 2), then 1 on mobile — all divisors
     of 10. Individual .service-card styling itself is untouched. */
  grid-template-columns: repeat(5, 1fr);
  gap: 28px;
  margin-top: 44px;
  /* Extra breathing room after the LAST row, on top of .services-box's
     own bottom padding and .services' own section padding — per Lasha:
     the fixed .quick-nav dock sits ~80px above the very bottom of the
     viewport, and without this the last row's cards had barely any
     runway before Process began, so a normal scroll gesture could
     "settle" with that row's text still trapped behind the dock,
     needing an extra deliberate scroll to read it. This gives scroll
     momentum enough empty space to carry past the dock's band before
     the section visually ends. Desktop only (see the mobile override
     below) — mobile's dock is smaller and Lasha specifically asked for
     TIGHTER section spacing there for a continuous-scroll feel, so this
     shouldn't fight that fix. */
  margin-bottom: 40px;
}

/* Closing CTA strip under the 8 service cards, per Lasha — a soft cyan-
   tinted band (not a plain card, so it reads as a distinct "final word"
   rather than a 9th grid item) with a pill button, same shape language
   as .btn-accent's gold pill but in the site's cyan accent instead of
   gold, so it doesn't compete with the gold CTAs used elsewhere. */
.services-cta {
  margin-top: 32px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 18px;
  padding: 26px 32px;
  border-radius: 16px;
  /* Matched to .service-card's own plain-blue recipe per Lasha — was a
     cyan-tinted gradient, read as a different color family from the 8
     cards above it instead of the same box style with a button inside. */
  background-color: oklch(30% 0.07 258 / 0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid oklch(55% 0.08 258 / 0.35);
}

.services-cta p {
  margin: 0;
  color: var(--white);
  font-size: 17px;
  font-weight: 500;
}

/* Ultra-wide monitors (Lasha's own setup included): with .services-box
   now spanning the full width, 5 columns (2 rows) would leave each row
   quite short and wide — one single row of all 10 cards uses that extra
   width instead of leaving a second row half-empty-looking. */
@media (min-width: 2200px) {
  .services-grid {
    grid-template-columns: repeat(10, 1fr);
  }
}

/* Cards were solid white; per Lasha, switched back to the site's navy
   palette — semi-transparent (glass) with backdrop-filter blur. (Briefly
   carried a faint grid-texture background-image at a finer scale than
   the site-wide grid pattern — per Lasha, removed again: plain blue,
   no pattern.) The transform/transition here is the base state for the
   cursor-tilt effect below (js/script.js sets --rx/--ry on mousemove) —
   perspective() + the two rotate axes give the "tilts slightly as the
   cursor moves over it" effect Lasha asked for. */
.service-card {
  position: relative;
  /* Grid items default to min-width: auto, which floors a card's width
     at its content's min-content size (e.g. the longest unbreakable
     word in a title like "Container Transport from Poti & Batumi").
     In the 5-column desktop layout that floor could exceed 1fr's share
     of the row at some widths, blowing out .services-grid past its
     container and pushing the WHOLE PAGE into horizontal overflow (a
     strip of empty background to the right of everything, however far
     down the page you were). This lets the card shrink and wrap its
     text normally instead. */
  min-width: 0;
  /* Per Lasha: dropped the faint grid-texture background-image these
     cards used to carry (a finer copy of the site-wide grid pattern) —
     just plain blue now, no pattern. */
  background-color: oklch(30% 0.07 258 / 0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid oklch(55% 0.08 258 / 0.35);
  border-radius: 16px;
  padding: 34px 30px;
  box-shadow: 0 16px 36px oklch(10% 0.06 258 / 0.28);
  transform: perspective(800px) rotateX(var(--ry, 0deg)) rotateY(var(--rx, 0deg));
  transition: transform 0.4s ease, border-color 0.3s ease;
  will-change: transform;
}

/* Added by js/script.js while the cursor is moving over the card, so the
   tilt tracks the cursor instantly; removed on mouseleave so the card
   eases back to flat with the slower 0.4s transition above instead of
   snapping back. */
.service-card.is-tilting {
  transition: transform 0.05s linear;
}

.service-card:hover {
  border-color: oklch(65% 0.1 210 / 0.55);
}

/* Icon + title now sit side by side on one row (was icon above title) —
   per Lasha, referencing an icon-in-a-circle layout. align-items:
   flex-start keeps the circle pinned to the top when a longer title
   (e.g. "Container Transport from Poti & Batumi") wraps to two lines,
   instead of the circle stretching or re-centering. */
.service-card-head {
  display: flex;
  align-items: flex-start;
  gap: 14px;
}

.service-icon-circle {
  flex-shrink: 0;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: oklch(50% 0.1 210 / 0.22);
  border: 1px solid oklch(65% 0.1 210 / 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Was var(--blue) — too close in value to the new dark card background.
     Lightened so it still pops against navy instead of white. */
  color: oklch(80% 0.1 210);
}

.service-card h3 {
  font-size: 18px;
  margin-top: 0;
  line-height: 1.3;
  /* Small nudge down so the title's cap-height optically lines up with
     the icon circle next to it, now that it's a row instead of stacked. */
  padding-top: 4px;
  /* Card background is dark navy now, not white — needs an explicit
     light color instead of inheriting var(--ink). */
  color: var(--white);
}

.service-card p {
  font-size: 15px;
  line-height: 1.6;
  /* Was var(--muted), a dark gray meant for the old white card — lightened
     to match the same muted-light tone used elsewhere on dark backgrounds
     (.section-subtext, .contact-copy p). */
  color: oklch(78% 0.02 260);
  margin-top: 16px;
}

/* ---------- Cargo Calculator ----------
   Per Lasha, inspired by weforward.ge — same navy-glass card language as
   .service-card (semi-transparent + fine grid texture + blur), but built
   as a form instead of a static card. Deliberately volume/weight only,
   no price output (see the HTML comment on the section for why). */

.calculator {
  /* Per Lasha: ~18% less top/bottom padding (88px -> 72px), same as
     .services/.process/.partners/.contact — see the comment on
     .services above. */
  padding-top: 72px;
  padding-bottom: 72px;
  /* Same left/right inset as .hero/.services below, per Lasha — was the
     centered, capped .container before, which is why this section sat in
     the middle of the screen instead of lining up with the sections
     above and below it. */
  padding-left: clamp(20px, 2.5vw, 56px);
  padding-right: clamp(20px, 2.5vw, 56px);
}

/* Replaces the old .container wrapper — plain full-width block, no
   max-width cap, so .calculator-card fills edge-to-edge like
   .services-box does. */
.calculator-inner {
  width: 100%;
}

.calculator h2 {
  font-family: 'Oswald', 'Space Grotesk', system-ui, sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  font-size: 32px;
  margin-top: 14px;
  max-width: 44ch;
  color: var(--white);
}

/* Reusable light, muted intro paragraph under a section heading — was
   introduced for the (now-removed) Routes section; kept generic and
   reused here under the Calculator heading. */
.section-subtext {
  font-size: 16px;
  color: oklch(78% 0.02 260);
  margin-top: 12px;
  max-width: 52ch;
}

/* ---------- How It Works ----------
   New per Lasha — sits between Services and the Calculator. Same
   translucent "ideal" card recipe as .services-box/.calculator-card/
   .contact-box (see those for the shared background/border/blur values),
   with a 4-up row of plain numbered steps instead of icon cards, so it
   reads as a quick, distinct beat rather than a repeat of Services. */
.process {
  /* Per Lasha: ~18% less top/bottom padding (88px -> 72px) — see the
     comment on .services above. */
  padding-top: 72px;
  padding-bottom: 72px;
  padding-left: clamp(20px, 2.5vw, 56px);
  padding-right: clamp(20px, 2.5vw, 56px);
}

.process-box {
  background: oklch(15% 0.05 258 / 0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid oklch(100% 0 0 / 0.1);
  border-radius: 20px;
  padding: 40px;
  box-shadow: 0 18px 40px oklch(10% 0.05 258 / 0.35);
}

.process h2 {
  font-family: 'Oswald', 'Space Grotesk', system-ui, sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  font-size: 32px;
  margin-top: 14px;
  max-width: 44ch;
  color: var(--white);
}

/* Wraps the eyebrow/heading/subtext against the new "Start Now" button,
   per Lasha — same idea as .services-cta: a WhatsApp shortcut for anyone
   who already knows they want to ship and doesn't need to read all 4
   steps first. align-items: center (not flex-start) so the button sits
   roughly level with the subtext, not pinned to the very top next to
   the eyebrow. */
.process-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.process-start-btn {
  flex-shrink: 0;
}

/* Connected 01-04 number track above the cards — see the HTML comment
   above .process-track. Shares .process-grid's exact column/gap recipe
   so the circles line up above each card. */
.process-track {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 28px;
  margin-top: 36px;
}

.process-track-step {
  display: flex;
  align-items: center;
}

.process-circle {
  flex-shrink: 0;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Oswald', 'Space Grotesk', system-ui, sans-serif;
  font-weight: 700;
  font-size: 17px;
  color: var(--cyan);
  background: oklch(58% 0.14 210 / 0.14);
  border: 1px solid oklch(58% 0.14 210 / 0.45);
}

.process-line {
  flex: 1 1 auto;
  height: 1px;
  margin-left: 14px;
  background: linear-gradient(to right, oklch(58% 0.14 210 / 0.45), oklch(58% 0.14 210 / 0.05));
}

.process-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 28px;
  margin-top: 18px;
}

.process-step {
  /* Per Lasha: match the individual .service-card boxes in "What We Do"
     (grid-textured navy card) instead of the plain left-rule layout this
     started with — same background/border/blur/shadow recipe as
     .service-card below, just without its cursor-tilt transform/JS hook,
     since that wasn't asked for here. */
  position: relative;
  /* Per Lasha: dropped the faint grid-texture background-image (see
     .service-card above, same recipe originally) — just plain blue. */
  background-color: oklch(30% 0.07 258 / 0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid oklch(55% 0.08 258 / 0.35);
  border-radius: 16px;
  padding: 30px 26px;
  box-shadow: 0 16px 36px oklch(10% 0.06 258 / 0.28);
  transition: border-color 0.3s ease;
}

.process-step:hover {
  border-color: oklch(65% 0.1 210 / 0.55);
}

.process-step-badge {
  display: inline-block;
  padding: 5px 12px;
  border-radius: 999px;
  background: oklch(58% 0.14 210 / 0.14);
  color: var(--cyan);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.process-step h3 {
  font-size: 19px;
  margin-top: 14px;
  line-height: 1.3;
  color: var(--white);
}

.process-step p {
  font-size: 14.5px;
  line-height: 1.6;
  color: oklch(78% 0.02 260);
  margin-top: 10px;
}

@media (max-width: 1100px) {
  /* The connected track only makes sense as a straight 4-in-a-row line
     above a 4-column grid — once .process-grid wraps to 2 or 1 columns
     below, four circles across the top would no longer sit above their
     matching card. Each card still carries its own timing badge, so the
     "same day / 1-2 days / ..." info isn't lost, just the connector. */
  .process-track {
    display: none;
  }

  .process-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 32px;
    margin-top: 40px;
  }
}

@media (max-width: 640px) {
  .process-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .process-box {
    padding: 28px 22px;
  }
}

/* ---------- Scroll-reveal ----------
   New per Lasha — section boxes (.services-box, .process-box,
   .calculator-card, .contact-box, .partners-box) fade and rise into
   place the first time they scroll into view, instead of just appearing.
   The class is added directly in the HTML; js/script.js toggles
   .is-visible via IntersectionObserver, once per element. Skipped
   entirely under prefers-reduced-motion — see that override below, which
   simply shows everything at full opacity with no motion. Deliberately
   NOT applied to individual .service-card items: those already use
   `transform` for the cursor-tilt effect (see .service-card above), and
   a second transform here would fight it. */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.7s ease, transform 0.7s ease;
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

.calculator-card {
  /* Per Lasha: the eyebrow/heading/subtext used to sit outside this box —
     now they're the box's first children too (see index.html), matching
     how .services-box holds "What We Do" and its grid together. No
     margin-top needed any more (that used to separate the box from the
     heading above it); .calculator's own padding-top handles the
     section's top spacing now, same as .services. */
  /* Matched to .services-box's plain frosted recipe per Lasha ("this box
     is ideal") — was the finer grid-textured card look (same recipe the
     individual .service-card items still use); now the outer container
     is the same dark-transparent blue everywhere, no texture of its own. */
  background: oklch(15% 0.05 258 / 0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid oklch(100% 0 0 / 0.1);
  border-radius: 20px;
  padding: 40px;
  box-shadow: 0 18px 40px oklch(10% 0.05 258 / 0.35);
}

/* Redesigned per Lasha — split into a working form on the left and a
   permanent "quote summary" card on the right, instead of a form with a
   few thin result lines that only showed up after Calculate (and left a
   large dead gap above the buttons on wide screens). */
.calculator-grid {
  display: grid;
  /* Was a fixed 300px summary column, which left all the extra width
     from going full-bleed sitting only in the form fields (input boxes
     stretching very wide on a large screen while the summary stayed
     small and fixed). A 2:1 fr split keeps both parts growing together
     in proportion as the card widens. */
  grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr);
  gap: 44px;
  /* Per Lasha: was "start", which left .calculator-form sitting at its
     own (shorter) natural height while .calculator-summary — a bordered
     card that got taller once the trust-points list was added — stretched
     further down, so the two columns visibly ended at different heights.
     "stretch" (the grid default) makes both columns the same height;
     .calculator-form's own align-content below then pins its Calculate/
     Reset row to the bottom of that now-taller box, so both columns
     finish flush with each other. */
  align-items: stretch;
  /* Per Lasha: the eyebrow/heading/subtext moved from sitting above this
     grid to being the first row inside .calculator-form itself, so that
     .calculator-summary (stretched to match the left column's full
     height) starts level with that text instead of just with the form
     fields below it — see .calculator-form-intro. No margin-top needed
     here any more; .calculator-card's own padding handles the top
     spacing now. */
}

.calculator-form {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 20px;
  /* Keeps the field rows pinned to the top at their normal size and lets
     any extra height (from the stretch above) collect as one gap right
     before .calc-actions, which margin-top: auto then claims — pushing
     the Calculate/Reset row down to align with the bottom of
     .calculator-summary instead of leaving dead space beneath it. */
  align-content: start;
}

.calculator-form-intro {
  grid-column: 1 / -1;
  /* Adds to .calculator-form's own 20px row gap so the total space
     before the first field row matches the old 44px gap this text used
     to sit above (back when it lived outside the grid). */
  margin-bottom: 24px;
}

.calc-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* Same fix as .contact-form-field, same reason — see the comment
     there. Guards the Packing Type <select> (its longest option is
     "Block Pallet (120 × 100 cm)") from forcing this grid item, and
     everything nested inside it, wider than the viewport on mobile. */
  min-width: 0;
}

.calc-field--wide {
  grid-column: span 2;
}

.calc-field label {
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: oklch(78% 0.02 260);
}

.calc-field select,
.calc-field input {
  font-family: 'Work Sans', sans-serif;
  font-size: 15px;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid oklch(55% 0.08 258 / 0.4);
  background-color: oklch(24% 0.07 258 / 0.6);
  color: var(--white);
  /* Explicit sizing rather than relying on grid "stretch" — see the
     comment on .contact-form-field input/select/textarea for why. */
  width: 100%;
  box-sizing: border-box;
}

.calc-field select:focus,
.calc-field input:focus {
  outline: none;
  border-color: var(--cyan);
}

.calc-actions {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 20px;
  /* auto claims whatever extra height .calculator-form ends up with once
     .calculator-grid stretches it to match .calculator-summary — pushing
     this row down flush with the bottom instead of leaving a gap under
     it. Harmless at/below the 1100px breakpoint, where .calculator-grid
     drops to a single column and .calculator-form no longer shares a row
     with .calculator-summary to stretch against, so there's no extra
     height to claim and this just resolves to its normal position. */
  margin-top: auto;
}

.btn-primary svg {
  transition: transform 0.2s ease;
}

.btn-primary:hover svg {
  transform: translateX(3px);
}

/* Plain-text Reset — a loud outlined button next to Calculate implied two
   equally-weighted actions, when Reset is really just a quiet "start
   over" link. */
.btn-text-reset {
  background: none;
  border: none;
  font-family: 'Work Sans', sans-serif;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: oklch(78% 0.02 260);
  cursor: pointer;
  padding: 8px 4px;
  text-decoration: underline;
  text-decoration-color: transparent;
  transition: color 0.2s ease, text-decoration-color 0.2s ease;
}

.btn-text-reset:hover {
  color: var(--gold);
  text-decoration-color: currentColor;
}

/* ---------- Shipment summary card ---------- */

.calculator-summary {
  background: oklch(20% 0.06 258 / 0.65);
  border: 1px solid oklch(65% 0.13 210 / 0.35);
  border-radius: 18px;
  padding: 26px 24px;
  display: flex;
  flex-direction: column;
  box-shadow: 0 14px 30px oklch(10% 0.06 258 / 0.3);
}

.calculator-summary-head {
  display: flex;
  align-items: center;
  gap: 14px;
}

.calculator-summary-badge {
  flex-shrink: 0;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: oklch(58% 0.14 210 / 0.16);
  color: var(--cyan);
}

.calculator-summary-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--cyan);
}

.calculator-summary-head h3 {
  font-family: 'Oswald', 'Space Grotesk', system-ui, sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  font-size: 17px;
  color: var(--white);
  margin-top: 2px;
}

.calculator-summary-placeholder {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid oklch(100% 0 0 / 0.1);
  font-size: 14px;
  line-height: 1.6;
  color: oklch(75% 0.02 260);
}

.calculator-summary-placeholder strong {
  color: oklch(88% 0.02 260);
}

/* New per Lasha: 3 quick reassurance points, filling the empty space the
   summary card used to leave below the placeholder text (the form column
   is taller than the placeholder alone). Hidden together with
   #calculatorPlaceholder once results are shown — see js/script.js. */
.calculator-summary-trust {
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Same fix as .calculator-results[hidden] below: the display:flex above
   sits at the same cascade specificity as the browser's built-in
   [hidden]{display:none} and would otherwise win, defeating
   trustPoints.hidden in js/script.js. Restated explicitly so the
   attribute always wins. */
.calculator-summary-trust[hidden] {
  display: none;
}

.calculator-summary-trust li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13.5px;
  color: oklch(80% 0.02 260);
}

.calculator-summary-trust svg {
  flex-shrink: 0;
  color: var(--cyan);
}

/* Revealed by js/script.js after the form is submitted (hidden by
   default via the HTML [hidden] attribute; the placeholder paragraph
   above takes its place until then). */
.calculator-results {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid oklch(100% 0 0 / 0.1);
  display: flex;
  flex-direction: column;
  gap: 18px;
}

/* The class rule above sets display:flex at the same specificity as the
   browser's built-in [hidden]{display:none}, and being later in the
   cascade it would otherwise win and defeat resultsBox.hidden in
   js/script.js. Restated explicitly so the attribute always wins. */
.calculator-results[hidden] {
  display: none;
}

.calc-result {
  display: flex;
  align-items: center;
  gap: 14px;
}

.calc-result-icon {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: oklch(100% 0 0 / 0.06);
  color: var(--gold);
}

.calc-result-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.calc-result-value {
  font-family: 'Space Grotesk', sans-serif;
  font-weight: 700;
  font-size: 22px;
  color: var(--white);
}

.calculator-summary-note {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid oklch(100% 0 0 / 0.1);
  font-size: 13px;
  color: oklch(75% 0.02 260);
}

.calculator-summary-note a {
  color: var(--cyan);
  font-weight: 600;
}

.calculator-summary-note a:hover {
  color: var(--gold);
}

.calc-result-label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: oklch(78% 0.02 260);
}

/* ---------- Partners ----------
   Per Lasha, inspired by weforward.ge's partner strip, but as a moving
   carousel of separate boxes rather than one static row, and logos shown
   in full color from the start (no grayscale/hover-to-color step like the
   first version). Sits on the same navy grid canvas as the rest of the
   page, but each logo gets its own white card — most of these brand
   marks are drawn for a white background and their colors (navy, red,
   pink, green...) would either clash with or disappear into the navy
   canvas without one. */

.partners {
  /* Per Lasha: ~18% less top/bottom padding (88px -> 72px) — see the
     comment on .services above. */
  padding-top: 72px;
  padding-bottom: 72px;
}

/* Per Lasha's reference video: one side-by-side box — copy+stats on the
   left, two opposite-scrolling logo rows on the right — replacing the
   old copy-on-top / single full-width row layout. Same plain translucent
   box recipe as .services-box/.calculator-card/.contact-box so it still
   reads as one more of the site's consistent boxed sections. Uses margin
   (not padding) for its left/right inset so it lines up on the same
   edges as every other section's box, while each .partners-row inside
   still runs its own logos edge to edge within that box for the
   scrolling strip to look continuous. */
.partners-box {
  display: flex;
  align-items: center;
  gap: 48px;
  margin-left: clamp(20px, 2.5vw, 56px);
  margin-right: clamp(20px, 2.5vw, 56px);
  background: oklch(15% 0.05 258 / 0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid oklch(100% 0 0 / 0.1);
  border-radius: 22px;
  padding: 40px clamp(24px, 4vw, 56px);
  box-shadow: 0 18px 40px oklch(10% 0.05 258 / 0.35);
}

.partners-copy {
  flex: 0 0 auto;
  max-width: 400px;
}

.partners h2 {
  font-family: 'Oswald', 'Space Grotesk', system-ui, sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  font-size: 32px;
  margin-top: 14px;
  max-width: 44ch;
  color: var(--white);
}

/* New per Lasha's reference: a small stat trio under the copy (12+
   Shipping Lines / 40+ Ports Served / 98% On-Time Delivery) — same
   number-over-label pattern as the hero's own stat trio, just smaller,
   since this box is narrower. MOCKUP NOTE: these three values are
   placeholder copy carried over from the reference video, not confirmed
   real numbers yet — see the HTML comment above this section. */
.partners-stats {
  display: flex;
  gap: 28px;
  margin-top: 28px;
}

.partners-stat {
  display: flex;
  flex-direction: column;
}

.partners-stat-value {
  font-family: 'Oswald', 'Space Grotesk', system-ui, sans-serif;
  font-weight: 700;
  font-size: 26px;
  color: var(--cyan);
}

.partners-stat-label {
  margin-top: 4px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: oklch(78% 0.02 260);
}

.partners-marquee-wrap {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* The clipping viewport for one logo row. mask-image fades both edges to
   transparent so logo boxes fade out/in at the sides instead of being
   sliced off by a hard edge — including the left edge where this row
   meets .partners-copy. */
.partners-row {
  overflow: hidden;
  mask-image: linear-gradient(to right, transparent 0, black 48px, black calc(100% - 48px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 48px, black calc(100% - 48px), transparent 100%);
}

/* Holds one row's 6 logo boxes twice (see the HTML comment on the
   Partners section for why) laid out in one long row via width:
   max-content, then scrolled left by exactly half its own width — since
   both halves are identical, that's the point where it's showing the
   same thing it started with, so the loop repeats invisibly. */
.partners-track {
  display: flex;
  gap: 20px;
  width: max-content;
  animation: partners-scroll 28s linear infinite;
}

/* Bottom row: same seamless-loop animation, just played back to front —
   -50% to 0 instead of 0 to -50% — which reads as scrolling right
   instead of left, so the two rows move in opposite directions like the
   reference video, without needing a second keyframe. */
.partners-track-reverse {
  animation-direction: reverse;
}

/* Pausing on hover/focus lets a visitor actually read a logo they stop
   on, instead of it sliding away mid-glance. */
.partners-marquee-wrap:hover .partners-track,
.partners-marquee-wrap:focus-within .partners-track {
  animation-play-state: paused;
}

@keyframes partners-scroll {
  from {
    transform: translateX(0);
  }
  to {
    /* Exactly half of .partners-track's total width, since it holds the
       logo list twice — see the comment above. */
    transform: translateX(-50%);
  }
}

.partner-logo {
  flex-shrink: 0;
  width: 180px;
  background: var(--white);
  border-radius: 14px;
  height: 92px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px 22px;
  box-shadow: 0 10px 24px oklch(15% 0.05 258 / 0.28);
}

.partner-logo img {
  max-width: 100%;
  max-height: 40px;
  width: auto;
  height: auto;
  object-fit: contain;
}

/* Respect the OS-level "reduce motion" setting — the logos still show
   (as one full static row each, since the track just holds still),
   nothing scrolls for anyone who's asked their system to avoid this kind
   of continuous motion. */
@media (prefers-reduced-motion: reduce) {
  .partners-track {
    animation: none;
  }
}

@media (max-width: 860px) {
  /* Narrow viewports stack copy above the two logo rows instead of
     side by side — there isn't room for a fixed-width copy column next
     to two scrolling rows once the box goes this narrow. */
  .partners-box {
    flex-direction: column;
    align-items: stretch;
    gap: 28px;
  }

  .partners-copy {
    max-width: none;
  }
}

/* ---------- Contact ---------- */

.contact {
  /* Per Lasha: ~18% less top/bottom padding (88px -> 72px) — see the
     comment on .services above. */
  padding-top: 72px;
  padding-bottom: 72px;
  /* Same left/right inset as the rest of the page now, per Lasha — was
     the centered, capped .container before. */
  padding-left: clamp(20px, 2.5vw, 56px);
  padding-right: clamp(20px, 2.5vw, 56px);
}

.contact-box {
  /* Matched to .services-box/.calculator-card's plain frosted recipe per
     Lasha ("this box is ideal") — was a solid var(--navy-light) fill;
     now the same dark-transparent blue + blur as the rest of the site's
     outer boxes. */
  background: oklch(15% 0.05 258 / 0.5);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid oklch(100% 0 0 / 0.1);
  box-shadow: 0 18px 40px oklch(10% 0.05 258 / 0.35);
  border-radius: 24px;
  padding: 48px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  /* stretch (not center) so .contact-map fills the same height as the
     copy column instead of sitting short and centered next to it. */
  align-items: stretch;
}

.contact-copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.contact-copy h2 {
  font-family: 'Oswald', 'Space Grotesk', system-ui, sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  font-size: 30px;
  color: var(--white);
}

.contact-copy p {
  font-size: 16px;
  color: oklch(78% 0.02 260);
  margin-top: 12px;
  max-width: 46ch;
  line-height: 1.6;
}

/* New per Lasha's reference: WhatsApp (primary, wide) + Email (secondary,
   narrower) side by side above the form. */
.contact-cta-row {
  margin-top: 26px;
  display: flex;
  gap: 12px;
}

.contact-cta-whatsapp {
  flex: 1 1 auto;
  justify-content: center;
}

.contact-cta-email {
  flex: 0 0 auto;
}

/* Plain dark/bordered secondary button — same pill shape as .btn-cyan,
   just outlined instead of filled, for the less-prominent Email option
   next to the big WhatsApp button. */
.btn-outline {
  background: transparent;
  color: var(--white);
  border: 1px solid oklch(55% 0.08 258 / 0.5);
  border-radius: 999px;
  font-weight: 600;
}

.btn-outline:hover {
  border-color: var(--cyan);
  color: var(--cyan);
}

/* "or fill the short form" — a plain hairline + small centered label
   above the form, echoing the reference without a background-matching
   "line cut by text" trick (this box's background is semi-transparent,
   so that trick can't get a clean matching fill behind the text). */
.contact-divider {
  margin-top: 22px;
  padding-top: 20px;
  border-top: 1px solid oklch(35% 0.03 260);
  text-align: center;
  font-size: 13px;
  color: oklch(65% 0.02 260);
}

.contact-form {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.contact-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.contact-form-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* Grid/flex items default to a minimum size based on their content's
     own "natural" width (min-content) — for a <select>, most mobile
     browsers/in-app webviews (Messenger's included, per Lasha's
     screenshot) measure that against its LONGEST option text (here,
     "Refrigerated / Temperature-Controlled"), which is wider than a
     390px phone screen. Without this, that one field can force its
     whole grid track — and everything nested inside it — wider than
     the viewport, so the input/select boxes below bleed out past
     .contact-box's edges instead of staying inside it. min-width: 0
     is the standard fix: it lets the field shrink to fit its column
     instead of demanding room for its widest content. */
  min-width: 0;
}

.contact-form-field label {
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: oklch(78% 0.02 260);
}

.contact-form-field-optional {
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: oklch(60% 0.02 260);
}

/* Pill-style single-select for Shipment Type, replacing a <select>
   dropdown per Lasha's reference — real radio inputs under the hood
   (visually hidden, not display:none, so they stay keyboard/
   screen-reader operable) so the chosen value still posts to Formspree
   like every other field here. */
.shipment-type-group {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.shipment-type-pill {
  cursor: pointer;
}

/* Qualified with .contact-form-field (this pill's actual ancestor in the
   markup) rather than just ".shipment-type-pill input", so this beats
   .contact-form-field input's later, equal-specificity "width: 100%"
   rule regardless of source order. Without that, the plain-input rule
   won the cascade and stretched this invisible radio to 100% of its
   absolutely-positioned containing block — over 1300px wide — which
   pushed the whole page into horizontal overflow (a big empty strip of
   background to the right of everything, on every screen size). */
.contact-form-field .shipment-type-pill input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.shipment-type-pill span {
  display: inline-flex;
  padding: 10px 18px;
  border-radius: 999px;
  border: 1px solid oklch(55% 0.08 258 / 0.4);
  background-color: oklch(24% 0.07 258 / 0.6);
  color: oklch(85% 0.02 260);
  font-size: 14px;
  font-weight: 600;
  transition: border-color 0.2s ease, color 0.2s ease, background-color 0.2s ease;
}

/* Per Lasha: this checked state (plus the map card's cyan accents
   below) use his exact rgba(11,200,233,1) pick — same reasoning as
   .btn-cyan above — rather than the sitewide (dimmer) var(--cyan), for
   a consistently bright accent across this whole redesigned section. */
.shipment-type-pill input:checked + span {
  border-color: #0bc8e9;
  color: #0bc8e9;
  background-color: rgba(11, 200, 233, 0.16);
}

.shipment-type-pill input:focus-visible + span {
  outline: 2px solid #0bc8e9;
  outline-offset: 2px;
}

.contact-form-field input,
.contact-form-field select,
.contact-form-field textarea {
  font-family: 'Work Sans', sans-serif;
  font-size: 15px;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid oklch(55% 0.08 258 / 0.4);
  background-color: oklch(24% 0.07 258 / 0.6);
  color: var(--white);
  resize: vertical;
  /* Explicit 100% + border-box (border-box is already the sitewide
     default — see the top of this file — repeated here so this rule
     is correct on its own) rather than relying on flex/grid "stretch"
     to size these: some mobile webviews don't stretch a bare <select>
     or <input> to its container reliably, which is what let them
     escape .contact-box's padding in the first place. */
  width: 100%;
  box-sizing: border-box;
}

.contact-form-field input:focus,
.contact-form-field select:focus,
.contact-form-field textarea:focus {
  outline: none;
  border-color: var(--cyan);
}

.contact-form-submit-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 4px;
}

.contact-form-submit {
  flex-shrink: 0;
}

.contact-form-submit svg {
  transition: transform 0.2s ease;
}

.contact-form-submit:hover svg {
  transform: translateX(3px);
}

/* Feedback shown after a real submit attempt to the Formspree endpoint
   (see js/script.js) — success in the site's cyan accent, error in a
   soft warm red, both quiet text rather than a loud banner since this
   sits right under a button the visitor just pressed. */
.contact-form-status {
  margin-top: 4px;
  font-size: 13.5px;
  line-height: 1.5;
}

.contact-form-status--success {
  color: var(--cyan);
}

.contact-form-status--error {
  color: oklch(72% 0.15 30);
}

.contact-form-status--error a {
  color: inherit;
  text-decoration: underline;
}

.contact-directions {
  display: inline-block;
  color: #0bc8e9;
  font-weight: 600;
  font-size: 13px;
  text-decoration: none;
}

.contact-directions:hover {
  text-decoration: underline;
}

/* Real live Google Maps embed again, per Lasha ("more user-friendly for
   visitors" than the stylized decorative version this briefly became —
   see the git history for that version if it's ever wanted back). Same
   plain maps.google.com/maps?...&output=embed URL as before, no API key
   needed. The CSS filter below is the standard no-API-key "fake dark
   mode" trick for an embedded Google Map: inverting the whole image and
   then rotating hue by 180° flips light roads/background dark while
   putting most colors roughly back where they started, so the map
   actually sits in the site's dark palette instead of showing as a
   bright rectangle. It's an approximation (a few colors — e.g. Google's
   own red pin — come out shifted, not identical to their original hue)
   but reads far better here than an unfiltered light-mode map. The
   info card below still overlays on top; the decorative HQ pin from the
   stylized version is gone since the real map now carries its own real
   marker at the real location. (The separate "Open in Maps" overlay
   button that used to sit top-left was removed as redundant — the map
   itself already opens Google Maps.) */
.contact-map {
  position: relative;
  min-height: 280px;
  border-radius: 18px;
  overflow: hidden;
  border: 1px solid oklch(45% 0.08 258 / 0.5);
  box-shadow: 0 14px 32px oklch(10% 0.06 258 / 0.4);
  background-color: oklch(12% 0.045 258);
}

.contact-map iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  filter: invert(90%) hue-rotate(180deg) contrast(90%);
}

.contact-map-card {
  position: absolute;
  left: 20px;
  right: 20px;
  bottom: 20px;
  background: oklch(12% 0.05 258 / 0.85);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid oklch(55% 0.08 258 / 0.35);
  border-radius: 14px;
  padding: 20px 22px;
}

.contact-map-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.contact-map-card-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: oklch(70% 0.02 260);
}

.contact-map-card-address {
  margin: 8px 0 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--white);
  line-height: 1.4;
}

.contact-map-card-hours {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid oklch(35% 0.03 260);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 13px;
  color: oklch(78% 0.02 260);
}

.contact-map-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 600;
}

.contact-map-status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
}

/* Per Lasha: plain green while open, plain red once closed — clearer at
   a glance than reusing the site's own cyan/gold accents here, which
   don't inherently read as "good"/"bad" status colors. */
.contact-map-status.is-open {
  color: #22c55e;
}

.contact-map-status.is-closed {
  color: #ef4444;
}

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

.site-footer {
  /* Was var(--line), a light gray divider meant for a light page — reads
     as a stark bright line on the new dark canvas, so switched to a
     translucent navy-tinted divider instead. */
  border-top: 1px solid oklch(45% 0.06 258 / 0.5);
  /* .quick-nav floats fixed over the bottom-center of the viewport, so
     at maximum scroll it would otherwise sit directly on top of the
     footer's social icons, making them unclickable. This reserves
     enough clear space below the footer's real content that the dock
     never overlaps it, even at the very bottom of the page. */
  padding-bottom: 96px;
}

.footer-inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 26px 32px;
  flex-wrap: wrap;
  gap: 12px;
}

.footer-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  /* Was var(--muted) — too dark to read on the new dark canvas. */
  color: oklch(68% 0.02 260);
}

.footer-domain {
  font-size: 13px;
  color: oklch(68% 0.02 260);
}

/* Absolutely centered (left: 50% + translateX(-50%)) rather than just
   "the middle item in a space-between row" — that would drift off-center
   depending on how wide .footer-brand/.footer-domain happen to be next
   to it (exactly what happened before: it sat visibly to the right of
   .quick-nav below it, per Lasha). This centering math is identical to
   .quick-nav's (also left: 50% + translateX(-50%), just fixed instead of
   absolute), so the icons row (and now the email/phone line under it)
   land on the same vertical line. Holds .footer-social AND
   .footer-contact-line stacked, so both center as one block. */
.footer-center {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.footer-social {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Email + phone, added under the social icons per Lasha. Same muted tone
   as .footer-brand/.footer-domain, with the links picking up the site's
   usual cyan on hover so they still read as clickable. */
.footer-contact-line {
  display: flex;
  align-items: center;
  /* Three items now (email + two phone numbers): wrap between items on
     narrow screens instead of breaking a number across two lines. */
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 10px;
  font-size: 13px;
  color: oklch(68% 0.02 260);
}

.footer-contact-line a {
  color: inherit;
  white-space: nowrap;
}

.footer-contact-line a:hover {
  color: var(--cyan);
}

.footer-contact-divider {
  color: oklch(45% 0.03 260);
}

.footer-social-link {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid oklch(45% 0.06 258 / 0.5);
  color: oklch(78% 0.02 260);
  transition: color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}

.footer-social-link:hover,
.footer-social-link:focus-visible {
  color: var(--white);
  border-color: var(--cyan);
  transform: translateY(-2px);
}

/* ---------- Floating quick-nav dock ----------
   Pill-shaped icon nav fixed to the bottom-center of the viewport (see
   index.html for why — per Lasha's weforward.ge reference). Centered,
   not right-aligned, so it never competes with .floating-contacts in
   the bottom-right corner. .is-active (toggled by js/script.js as the
   visitor scrolls) highlights whichever section is currently in view. */
.quick-nav {
  position: fixed;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%);
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--navy-light);
  border: 1px solid oklch(45% 0.08 258 / 0.5);
  border-radius: 999px;
  padding: 8px;
  box-shadow: 0 14px 32px oklch(10% 0.06 258 / 0.4);
  /* "bottom" is animated too now — js/script.js nudges this dock UP
     (by setting an inline style.bottom) while the hero's own slideshow
     dots (.hero-dots) are on screen and would otherwise sit under it,
     instead of the dock disappearing (see the comment in script.js —
     per Lasha, it should always stay visible). */
  transition: opacity 0.3s ease, transform 0.3s ease, bottom 0.3s ease;
}

@media (prefers-reduced-motion: reduce) {
  .quick-nav {
    transition: none;
  }
}

.quick-nav-link {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: oklch(78% 0.02 260);
  transition: background 0.2s ease, color 0.2s ease;
}

.quick-nav-link:hover {
  color: var(--white);
}

.quick-nav-link.is-active {
  background: var(--cyan);
  color: var(--white);
}

/* ---------- Floating contact buttons ----------
   WhatsApp + email, fixed to the bottom-right corner of the viewport so
   they follow the visitor down the page (see index.html for why — per
   Lasha). z-index: 50 comfortably clears the sticky header (10) and
   everything under it. Brand colors on purpose here (WhatsApp green,
   Outlook blue) — the one place on the site that isn't navy/gold,
   because instant recognizability matters more than palette consistency
   for a click-to-contact button. */
.floating-contacts {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 50;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.floating-contact-btn {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8px 20px oklch(15% 0.05 258 / 0.35);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.floating-contact-btn:hover,
.floating-contact-btn:focus-visible {
  transform: translateY(-3px) scale(1.06);
  box-shadow: 0 12px 26px oklch(15% 0.05 258 / 0.45);
}

.floating-whatsapp {
  background: #25d366;
}

.floating-email {
  background: #0078d4;
}

/* Divider between the two stacked photo sections (Hero + About).
   Rejected three times now (gold bar, navy bar + shadow, backdrop-filter
   blur) for looking too heavy/rough. This is the replacement approach,
   per Lasha's most recent request: no visible bar/stripe element at all.
   Instead:
     1. The grid-pattern canvas (see body, above) runs underneath the
        entire page, including this gap.
     2. .hero and .about-hero each get a mask-image that fades their own
        photo to transparent right at the edge that touches this gap
        (see below), so the grid canvas shows through and the photos
        feather into it instead of ending on a hard line.
   This element is now just a plain spacer that reveals a strip of that
   grid canvas between the two feathered photos — no bar, no blur, no
   box-shadow. Kept short (20px, was 56px) per Lasha — the fades on
   .hero/.about-hero already do the visual blending, so this only needs
   to be a thin seam, not a wide gap. */
.section-divider {
  height: 20px;
}

/* ---------- About section ----------
   Used to be a separate about.html page; now it's just another section
   on the one-page site, between Hero and Services (per Lasha). A simple
   photo hero, vertically centered (not bottom-anchored like the main
   Hero — there are no stats/buttons competing for space here, just the
   eyebrow + heading + paragraph). Same gradient-over-photo legibility
   trick as the main Hero. */
.about-hero {
  position: relative;
  min-height: 420px;
  display: flex;
  /* Bottom-anchored with the same left inset as .hero-copy above, per
     Lasha — the two boxes now line up on the same left edge instead of
     each section using its own padding. padding-top can't go as low as
     Hero's (20px) though: unlike Hero (where .hero-copy is a sibling of
     the masked photo layer), .about-copy is a direct child of this
     section, so the top/bottom mask-image fade below would fade the box
     itself if it started inside that 56px zone — padding-top stays at
     least that tall to keep the card fully outside the fade. */
  align-items: flex-end;
  padding-top: 56px;
  padding-bottom: 100px;
  padding-left: clamp(20px, 2.5vw, 56px);
  padding-right: 64px;
  background-image:
    linear-gradient(100deg, oklch(15% 0.06 258 / 0.82) 8%, oklch(15% 0.06 258 / 0.55) 40%, oklch(15% 0.06 258 / 0.18) 72%),
    url("../images/about-fleet.jpg");
  background-size: cover;
  background-position: center center;
  /* Two-sided fade now, per Lasha: feathers in from transparent over the
     first 56px (picking up from the Hero/About gap above, mirroring
     .hero's fade), AND fades out to transparent over the last 56px, so
     the bottom edge blends into the grid canvas the same way before
     Services starts, instead of ending on a hard line. Bottom-anchored
     with 56px/100px top/bottom padding (see above) — both fades stay
     within that padding and never touch the .about-copy card. */
  mask-image: linear-gradient(to bottom, transparent 0, black 56px, black calc(100% - 56px), transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, black 56px, black calc(100% - 56px), transparent 100%);
}

.about-copy {
  position: relative;
  /* Matched to .hero-copy's max-width (was 640px) per Lasha — at medium
     viewport widths 640 stopped meaningfully capping the box while
     Hero's 420 still did, so the two boxes drifted to visibly different
     sizes scrolling from one to the other. Same cap now, same padding/
     radius already shared below, so they read as one consistent size. */
  max-width: 420px;
  /* Same translucent-card treatment as .hero-copy on the Hero above, per
     Lasha — the eyebrow + heading + paragraph now sit in their own
     frosted box over the photo instead of bare text, and get the same
     gentle hover pulse. */
  background: oklch(15% 0.05 258 / 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid oklch(100% 0 0 / 0.1);
  border-radius: 18px;
  padding: 28px 32px;
  box-shadow: 0 18px 40px oklch(10% 0.05 258 / 0.35);
  transition: transform 0.5s ease;
}

.about-copy:hover {
  animation: hero-copy-pulse 1.8s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .about-copy:hover {
    animation: none;
  }
}

.about-hero h1 {
  font-family: 'Oswald', 'Space Grotesk', system-ui, sans-serif;
  font-weight: 700;
  text-transform: uppercase;
  font-size: 42px;
  line-height: 1.1;
  color: var(--white);
  margin-top: 0;
  text-shadow: 0 2px 20px oklch(15% 0.05 258 / 0.45);
}

.about-hero p {
  font-size: 17px;
  line-height: 1.7;
  color: oklch(94% 0.01 260);
  margin-top: 22px;
  max-width: 56ch;
}

/* =========================================================
   Responsive
   ========================================================= */

/* Calculator gets its own, earlier breakpoint: the 300px summary card
   next to a 4-column dimension row needs more room than the 860px
   breakpoint below gives it, well before the rest of the page needs to
   respond. */
@media (max-width: 1100px) {
  .calculator-grid {
    grid-template-columns: 1fr;
    gap: 32px;
  }

  .calculator-form {
    grid-template-columns: repeat(2, 1fr);
  }

  .calc-field--wide {
    grid-column: span 1;
  }

  .calculator-summary {
    max-width: 420px;
  }

  /* Tablet range: 2 columns (still a divisor of 10, so the last row of
     the services grid is always full — see .services-grid above). */
  .services-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 860px) {
  /* Per Lasha: the overlay layout (photo behind, text card floating on
     top, box forced to a fixed 600px so the card had room to sit) meant
     background-size:cover had to crop the photo hard to fill that tall,
     narrow box — at a 390px-wide phone the box was 600px tall but the
     photo's own shape (1568:672) is only ~167px tall at that width, so
     cover chopped off most of the frame to fill the rest.
     Below this breakpoint the hero stops being an overlay: .hero-media
     becomes a normal in-flow block sized to the photo's EXACT aspect
     ratio (so cover never needs to crop anything — the box and the
     image are the same shape, same as how the desktop aspect-ratio
     trick avoids cropping there too), and .hero-copy drops below it as
     its own block, same as the boxed cards everywhere else on the
     page. The photo shows complete, same as on desktop — it's just
     stacked above the text now instead of sitting behind it. */
  .hero {
    display: block;
    aspect-ratio: auto;
    min-height: 0;
    max-height: none;
    padding: 0;
    overflow: visible;
  }

  .hero-media {
    position: relative;
    inset: auto;
    width: 100%;
    aspect-ratio: 1568 / 672;
  }

  .hero-photo-layer {
    /* Much shorter band than the old fixed 600px box, so the desktop
       48px/56px fade would eat away most of it — scaled down to suit.
       (Scoped to this inner photo-only layer, not .hero-media, so it
       never fades .hero-dots — see the comment on .hero-photo-layer.) */
    mask-image: linear-gradient(to bottom, transparent 0, black 14px, black calc(100% - 14px), transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, black 14px, black calc(100% - 14px), transparent 100%);
  }

  .hero-dots {
    bottom: 10px;
  }

  .hero-copy {
    max-width: none;
    margin: 18px 16px 28px;
    padding: 22px 22px;
    border-radius: 14px;
  }

  .hero-stats {
    display: none;
  }

  /* This left-to-right darkening exists only so the overlaid .hero-copy
     text stays legible against the photo on desktop. Below this
     breakpoint .hero-copy has already dropped below the photo (see the
     comment above), so the gradient no longer has anything to darken
     FOR — left switched on, it just left a dark smudge over the left
     third of the photo on every phone, for no reason (spotted by
     Lasha on the new hero-slide-4 photo, where it showed up clearly
     against the bright sky/building). */
  .hero-gradient {
    display: none;
  }

  /* Per Lasha: on mobile, every section's own top/bottom padding (tuned
     for how spacious that feels on a wide desktop screen) stacks with
     the next section's matching padding into a dead gap between one
     box's bottom edge and the next box's top edge — on a 390px-wide
     phone that reads as the page being broken into disconnected screens
     instead of one continuous scroll. Roughly halved from desktop here
     so sections still breathe but the scroll feels like one page; each
     trimmed another ~18% (was 48px) alongside the desktop reduction
     above, same reasoning. */
  .services {
    padding-top: 40px;
    padding-bottom: 40px;
  }

  .process {
    padding-top: 40px;
    padding-bottom: 40px;
  }

  .calculator {
    padding-top: 40px;
    padding-bottom: 40px;
  }

  .partners {
    padding-top: 40px;
    padding-bottom: 40px;
  }

  .contact {
    padding-top: 40px;
    padding-bottom: 40px;
  }

  .services-box {
    padding: 32px 22px 40px;
    border-radius: 16px;
  }

  .process-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 18px;
  }

  .process-start-btn {
    width: 100%;
    justify-content: center;
  }

  /* Cancels the desktop-only extra runway added to .services-grid above
     — mobile stacks all 8 cards single-column (very tall already) and
     just had its section gaps tightened for a continuous-scroll feel,
     so this shouldn't add height back. */
  .services-grid {
    margin-bottom: 0;
  }

  .services-grid {
    grid-template-columns: 1fr;
  }

  .services-cta {
    flex-direction: column;
    align-items: flex-start;
    margin-top: 24px;
    padding: 22px;
  }

  .services-cta .btn {
    width: 100%;
    justify-content: center;
  }

  .calculator-card {
    padding: 28px 24px;
  }

  .calculator-form {
    grid-template-columns: 1fr;
  }

  .calc-actions {
    justify-content: space-between;
  }

  .calculator-summary {
    max-width: none;
    padding: 22px 20px;
  }

  .partners-box {
    padding: 28px 22px;
    border-radius: 16px;
  }

  .floating-contacts {
    right: 14px;
    bottom: 14px;
    gap: 10px;
  }

  .floating-contact-btn {
    width: 48px;
    height: 48px;
  }

  .quick-nav {
    bottom: 14px;
    gap: 2px;
    padding: 6px;
  }

  .quick-nav-link {
    width: 38px;
    height: 38px;
  }

  .quick-nav-link svg {
    width: 17px;
    height: 17px;
  }

  .site-footer {
    padding-bottom: 84px;
  }

  /* .footer-center's absolute centering (see the rule itself) works
     against .footer-inner's flex row on desktop, but on a narrow screen
     .footer-brand's text is wide enough to collide with it (it doesn't
     participate in flex spacing once it's taken out of flow). Simplest
     fix: stack all rows and let the social icons + contact line sit in
     normal document flow between them, centered by the column layout
     instead of by absolute positioning. */
  .footer-inner {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }

  .footer-center {
    position: static;
    transform: none;
  }

  /* Smaller boxes + a shorter loop distance so the animation's speed
     (still 28s per lap) doesn't feel sluggish on a narrower strip. */
  .partner-logo {
    width: 130px;
    height: 76px;
    padding: 12px 16px;
  }

  .partner-logo img {
    max-height: 30px;
  }

  .partners-row {
    mask-image: linear-gradient(to right, transparent 0, black 32px, black calc(100% - 32px), transparent 100%);
    -webkit-mask-image: linear-gradient(to right, transparent 0, black 32px, black calc(100% - 32px), transparent 100%);
  }

  .partners-stats {
    gap: 20px;
  }

  .main-nav {
    display: none;
  }

  .header-utility {
    display: none;
  }

  .hero h1 {
    font-size: 38px;
    line-height: 1.12;
  }

  .about-hero {
    min-height: 320px;
    padding: 32px 24px;
    /* Padding shrank to 32px on mobile — match both fade bands to it so
       they stay inside the empty padding and don't reach into the text. */
    mask-image: linear-gradient(to bottom, transparent 0, black 32px, black calc(100% - 32px), transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, black 32px, black calc(100% - 32px), transparent 100%);
  }

  .about-hero h1 {
    font-size: 32px;
  }

  .contact-box {
    grid-template-columns: 1fr;
    padding: 32px 24px;
  }

  .contact-cta-row {
    flex-direction: column;
  }

  .contact-map {
    min-height: 300px;
  }

  /* Shorter map card on mobile fits proportionally less height, so the
     pin (vertically centered on the whole card by percentage) needs to
     sit higher here or its point overlaps the info card below it. */
  .contact-map-pin {
    top: 34%;
  }

  .contact-map-card {
    padding: 16px 18px;
  }

  .contact-form-row {
    grid-template-columns: 1fr;
  }

  .contact-form-submit-row {
    flex-direction: column;
    align-items: flex-start;
  }
}
