/* ---------------------------------------------------------------------------
   Homepage sections - light corporate theme
   --------------------------------------------------------------------------- */

/* Marker for wording that has not been supplied yet. */
.aps-todo {
  display: inline-block;
  padding: 1px 8px;
  border: 1px dashed var(--color-gold);
  border-radius: var(--radius-sm);
  background: var(--color-gold-soft);
  color: #8a6410;
  font-size: 0.72rem;
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  vertical-align: middle;
}

/* ==========================================================================
   SECTION RHYTHM
   --------------------------------------------------------------------------
   Every homepage section declares its own band with an explicit modifier.
   This replaced an :nth-of-type(even) rule, which tied the colours to a
   section's *position* - inserting or reordering a section silently shifted
   every band below it. Now the markup says what it is.

     --white   plain page background (no pseudo element at all)
     --gray    #F5F6F8 full-bleed tint
     --navy    #2F578B full-bleed anchor band, light text, wave edges
     --photo   photograph under a navy wash (Fields of Activity)

   All of them paint through the same full-bleed ::before, because the content
   sits in a max-width container and the colour has to reach the viewport edge.
   ========================================================================== */
.aps-section--gray::before,
.aps-section--navy::before,
.aps-section--photo::before {
  content: '';
  position: absolute;
  inset-block: 0;
  inset-inline-start: 50%;
  width: 100vw;
  transform: translateX(-50%);
  z-index: -1;
}
html[dir="rtl"] .aps-section--gray::before,
html[dir="rtl"] .aps-section--navy::before,
html[dir="rtl"] .aps-section--photo::before {
  transform: translateX(50%);
}

/* --white needs no rule: the body is already #FFFFFF. The class exists so the
   rhythm is legible in the template rather than implied by absence. */
.aps-section--gray::before { background-color: var(--color-surface); }

/* --------------------------------------------------------------------------
   Navy anchor band (Projects).
   The dark stop in the rhythm. Text goes white, the accent goes gold - orange
   on navy measures about 1.7:1 and is unusable here, gold clears 4:1.
   -------------------------------------------------------------------------- */
.aps-section--navy {
  /* The two wave edges are filled with the colour of the NEIGHBOURING section,
     so the band looks cut into the page rather than pasted on top of it.
     Top = the section above (Services, white). Bottom = the section below
     (Partners, gray). Change these two fills if the running order changes. */
  --aps-wave-top: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 48' preserveAspectRatio='none'%3E%3Cpath d='M0,0 H1440 V14 C1140,42 900,6 620,22 C420,33 200,36 0,26 Z' fill='%23FFFFFF'/%3E%3C/svg%3E");
  --aps-wave-bottom: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 48' preserveAspectRatio='none'%3E%3Cpath d='M0,48 H1440 V34 C1140,6 900,42 620,26 C420,15 200,12 0,22 Z' fill='%23F5F6F8'/%3E%3C/svg%3E");
}
.aps-section--navy::before {
  background-color: var(--color-navy);
  background-image: var(--aps-wave-top), var(--aps-wave-bottom);
  background-repeat: no-repeat, no-repeat;
  background-position: top center, bottom center;
  /* 42px against 96px of section padding, so the waves never reach the text. */
  background-size: 100% 42px, 100% 42px;
}
/* The waves are symmetrical about the vertical axis, so RTL needs nothing. */

.aps-section--navy .aps-title__text   { color: #fff; }
.aps-section--navy .aps-title__accent { color: var(--color-gold); }
.aps-section--navy .aps-title__rule   { background: var(--color-gold); }

/* Cards here are a translucent lift out of the navy rather than solid white -
   solid white would repeat the Fields band and flatten the rhythm. */
.aps-section--navy .aps-card {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.22);
  box-shadow: none;
  /* Inherited body text is #1F2937, which measures 2.4:1 here. Every string in
     a project card is styled explicitly below, but this makes the *default*
     safe so anything added later cannot land unreadable. */
  color: #fff;
}
.aps-section--navy .aps-card:hover {
  background: rgba(255, 255, 255, 0.12);
  border-color: var(--color-gold);
  box-shadow: 0 18px 40px rgba(12, 26, 46, 0.35);
}
/* Gold as a non-text accent: 3.5:1 on the card, which clears the 3:1 bar for
   graphics but not the 4.5:1 bar for small text - so the text stays white. */
.aps-section--navy .aps-project { position: relative; overflow: hidden; }
.aps-section--navy .aps-project::before {
  content: '';
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: 3px;
  background: var(--color-gold);
  opacity: .85;
}
.aps-section--navy .aps-project__title { color: #fff; }
.aps-section--navy .aps-project__ref   { color: rgba(255, 255, 255, 0.82); }
.aps-section--navy .aps-project__ref .aps-num { color: #fff; }
.aps-section--navy .aps-project__meta dt { color: rgba(255, 255, 255, 0.82); }
.aps-section--navy .aps-project__meta dd { color: #fff; }

/* --------------------------------------------------------------------------
   Corner accent. A single soft radial bloom in a corner of a white section,
   just enough to stop two white bands reading as one. Deliberately not the
   hard geometric wedges the old Elementor build used.
   inset-inline-end mirrors itself, so RTL is already correct.
   -------------------------------------------------------------------------- */
.aps-section--accent-gold::after,
.aps-section--accent-orange::after {
  content: '';
  position: absolute;
  width: min(460px, 36vw);
  aspect-ratio: 1;
  pointer-events: none;
  z-index: -1;
}
.aps-section--accent-gold::after {
  inset-block-start: 0;
  inset-inline-end: 0;
  background: radial-gradient(circle at 72% 28%,
              rgba(251, 178, 47, 0.20), rgba(251, 178, 47, 0) 68%);
}
.aps-section--accent-orange::after {
  inset-block-end: 0;
  inset-inline-start: 0;
  background: radial-gradient(circle at 28% 72%,
              rgba(239, 87, 54, 0.14), rgba(239, 87, 54, 0) 68%);
}

/* On the gray band the "why us" chips were surface-on-surface and vanished. */
.aps-section--gray .aps-why__list li {
  background: #fff;
  border-color: var(--color-border);
}

/* --------------------------------------------------------------------------
   Photo-backed band. Same full-bleed pseudo element as the tints above, but
   the fill is a navy wash laid over a photograph handed in from PHP as
   --aps-photo. The wash is what makes this safe: the source is a warm dusk
   silhouette, and a *light* wash over it would turn the rig into grey mush,
   so the photo is pulled into the brand navy instead. White cards then sit on
   the highest-contrast surface the palette offers.
   -------------------------------------------------------------------------- */
.aps-section--photo {
  /* Weighted to the top on purpose. The section title is the only text that
     touches the photo, and it sits in the first quarter - so the wash is
     heaviest there and thins out lower down, where nothing but opaque white
     cards sits and the dusk rig is free to show through. */
  --aps-photo-wash: linear-gradient(
      180deg,
      rgba(36, 70, 111, 0.94) 0%,
      rgba(36, 70, 111, 0.90) 28%,
      rgba(47, 87, 139, 0.74) 62%,
      rgba(36, 70, 111, 0.86) 100%);
}
/* The section below Fields of Activity is Who We Are (gray), so the closing
   wave is filled with #F5F6F8. Same rule as the navy band: change this fill if
   the running order changes. The shape is symmetrical, so RTL needs nothing. */
.aps-section--photo {
  --aps-wave-bottom: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 48' preserveAspectRatio='none'%3E%3Cpath d='M0,48 H1440 V34 C1140,6 900,42 620,26 C420,15 200,12 0,22 Z' fill='%23F5F6F8'/%3E%3C/svg%3E");
}
.aps-section--photo::before {
  /* Placement comes from the shared band rule above. The wave is listed first
     so it paints over the photograph rather than under it. */
  background-image: var(--aps-wave-bottom), var(--aps-photo-wash), var(--aps-photo);
  background-size: 100% 42px, cover, cover;
  /* The band is much wider than 2.4:1, so `cover` crops the photo vertically
     and a centred position cut the horizon off entirely - the band was pure
     sky. Anchored to the bottom instead, so the rig base, the tanks and the
     site lighting are what fills it. This photo's horizon sits at 89.6% of its
     own height, so this is as much ground as it can give without swapping the
     picture. The gradient layer stays centred - it covers the box either way. */
  /* One entry per layer, in the same order: wave, wash, photo. */
  background-position: bottom center, center center, center bottom;
  background-repeat: no-repeat, no-repeat, no-repeat;
}

/* Phones get the 1200px source; the 2400px crop is ~180KB of wasted bytes. */
@media (max-width: 780px) {
  .aps-section--photo::before {
    background-image: var(--aps-wave-bottom), var(--aps-photo-wash),
                      var(--aps-photo-sm, var(--aps-photo));
  }
}

/* Only the section title sits directly on the photo, so only it has to flip.
   Gold rather than orange for the accent: orange on navy measures about
   1.7:1, gold clears 3:1 at this type size. */
.aps-section--photo .aps-title__text   { color: #fff; }
.aps-section--photo .aps-title__accent { color: var(--color-gold); }
.aps-section--photo .aps-title__rule   { background: var(--color-gold); }

/* Cards keep their white surface - the text inside them is untouched. They
   only need a deeper shadow to still read as lifted off a dark band. */
.aps-section--photo .aps-card {
  border-color: rgba(255, 255, 255, 0.18);
  box-shadow: 0 18px 40px rgba(12, 26, 46, 0.32);
}
.aps-section--photo .aps-card:hover {
  border-color: var(--color-orange);
  box-shadow: 0 26px 56px rgba(12, 26, 46, 0.40);
}

.aps-sub {
  margin: var(--space-8) 0 var(--space-5);
  color: var(--color-navy);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.aps-sub::before {
  content: '';
  display: inline-block;
  width: 22px;
  height: 2px;
  margin-inline-end: var(--space-3);
  border-radius: 1px;
  background: var(--color-orange);
  vertical-align: middle;
}

.aps-grid { display: grid; gap: var(--space-5); }
.aps-grid--2 { grid-template-columns: repeat(2, 1fr); }
.aps-grid--3 { grid-template-columns: repeat(3, 1fr); }
.aps-grid--5 { grid-template-columns: repeat(5, 1fr); }

/* ------------------------------- 1. hero -------------------------------- */
.aps-hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: min(82vh, 820px);
  margin-top: calc(var(--header-h) * -1);
  padding-block: calc(var(--header-h) + var(--space-8)) var(--space-8);
  overflow: hidden;
  background: var(--color-surface);
}
@media (max-width: 900px) {
  .aps-hero {
    margin-top: calc(var(--header-h-mobile) * -1);
    padding-block: calc(var(--header-h-mobile) + var(--space-7)) var(--space-7);
  }
}

/* --- slider track: stacked slides, cross-faded --- */
.aps-slider__track { position: absolute; inset: 0; z-index: 0; }

.aps-slide {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 600ms var(--ease), visibility 600ms var(--ease);
  overflow: hidden;
}
.aps-slide.is-active { opacity: 1; visibility: visible; }

.aps-slide img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 72% center;
  /* The set mixes dusk frames with a flat overcast one. A little extra
     contrast keeps the bright frame from dissolving under the light scrim
     without crushing the dark ones. */
  filter: saturate(1.08) contrast(1.12) brightness(0.97);
  /* Ken Burns: parked at 1.04 and eased back to 1 while the slide is up. */
  transform: scale(1.04);
  transform-origin: 65% 50%;
  will-change: transform;
}
.aps-slide.is-active img {
  transform: scale(1);
  transition: transform 7s linear;
}
html[dir="rtl"] .aps-slide img { object-position: 28% center; transform-origin: 35% 50%; }

@media (prefers-reduced-motion: reduce) {
  .aps-slide,
  .aps-slide.is-active img { transition: none; }
  .aps-slide img { transform: none; }
}

/* A navy-tinted wash over the text side. Tinted with the brand navy but kept
   LIGHT on purpose: the slide titles are navy and orange, and a dark navy
   panel would swallow them. */
.aps-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    /* Reaches full strength only where the words sit, then clears by ~58%
       so the photograph is still a photograph. */
    linear-gradient(to right,
      rgba(236, 241, 248, 0.95) 0%,
      rgba(236, 241, 248, 0.84) 24%,
      rgba(238, 243, 250, 0.34) 44%,
      rgba(240, 244, 250, 0.04) 58%,
      rgba(240, 244, 250, 0.00) 100%),
    linear-gradient(to bottom,
      rgba(255, 255, 255, 0.34) 0%,
      rgba(255, 255, 255, 0.00) 26%,
      rgba(255, 255, 255, 0.00) 60%,
      rgba(255, 255, 255, 0.58) 100%),
    radial-gradient(85% 80% at 100% 100%,
      rgba(47, 87, 139, 0.24) 0%, rgba(47, 87, 139, 0) 60%);
}
html[dir="rtl"] .aps-hero__scrim {
  background:
    linear-gradient(to left,
      rgba(236, 241, 248, 0.95) 0%,
      rgba(236, 241, 248, 0.84) 24%,
      rgba(238, 243, 250, 0.34) 44%,
      rgba(240, 244, 250, 0.04) 58%,
      rgba(240, 244, 250, 0.00) 100%),
    linear-gradient(to bottom,
      rgba(255, 255, 255, 0.34) 0%,
      rgba(255, 255, 255, 0.00) 26%,
      rgba(255, 255, 255, 0.00) 60%,
      rgba(255, 255, 255, 0.58) 100%),
    radial-gradient(85% 80% at 0% 100%,
      rgba(47, 87, 139, 0.24) 0%, rgba(47, 87, 139, 0) 60%);
}

.aps-hero__inner { position: relative; z-index: 2; }

/* The rotating headline. All titles are stacked; only one is visible, so the
   text swaps in step with the photo without the block changing height. */
.aps-hero__titles {
  position: relative;
  display: block;
  min-height: calc(var(--fs-3xl) * var(--lh-display));
  max-width: 19ch;
  margin: 0 0 var(--space-4);
  color: var(--color-navy);
  font-size: var(--fs-3xl);
  font-weight: var(--fw-display);
  letter-spacing: var(--ls-display);
  line-height: var(--lh-display);
}
.aps-hero__title {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity 600ms var(--ease),
              transform 600ms var(--ease),
              visibility 600ms var(--ease);
  white-space: nowrap;
}
.aps-hero__title.is-active { opacity: 1; visibility: visible; transform: none; }

/* On narrow screens the titles come out of the stack and flow normally: an
   absolutely positioned stack has to reserve room for the tallest title, which
   left a dead gap under the short ones. */
@media (max-width: 640px) {
  .aps-hero__titles { min-height: 0; }
  .aps-hero__title {
    position: static;
    display: none;
    white-space: normal;
    transform: none;
  }
  .aps-hero__title.is-active { display: block; }
}

/* Per-slide subtitle. Same stacked-and-swapped trick as the title, so it
   changes in step with the photo without the block resizing. The reserved
   height is two lines, which every supplied subtitle fits at desktop width. */
.aps-hero__subs {
  position: relative;
  min-height: calc(var(--fs-md) * var(--lh-normal) * 2);
  margin-bottom: var(--space-3);
}
.aps-hero__sub {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  max-width: 44ch;
  margin: 0;
  color: var(--color-navy-dark);
  font-size: var(--fs-md);
  font-weight: var(--fw-medium);
  line-height: var(--lh-normal);
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity 600ms var(--ease),
              transform 600ms var(--ease),
              visibility 600ms var(--ease);
}
.aps-hero__sub.is-active { opacity: 1; visibility: visible; transform: none; }

/* Same reasoning as the titles: below 640px an absolute stack reserves room
   for the tallest subtitle and leaves a dead gap under the short ones. */
@media (max-width: 640px) {
  .aps-hero__subs { min-height: 0; }
  .aps-hero__sub {
    position: static;
    display: none;
    transform: none;
  }
  .aps-hero__sub.is-active { display: block; }
}

/* .aps-hero__tagline was here. The global tagline is no longer rendered - each
   slide carries its own subtitle - so the rules went with it. */

/* --- controls --- */
.aps-slider__nav {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-top: var(--space-6);
}
.aps-slider__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px; height: 46px;
  padding: 0;
  border: 1.5px solid var(--color-navy);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.75);
  color: var(--color-navy);
  cursor: pointer;
  transition: background var(--t-base) var(--ease),
              color var(--t-base) var(--ease),
              border-color var(--t-base) var(--ease),
              transform var(--t-base) var(--ease);
}
.aps-slider__arrow:hover {
  background: var(--color-navy);
  border-color: var(--color-navy);
  color: #fff;
  transform: translateY(-2px);
}
html[dir="rtl"] .aps-slider__arrow svg { transform: scaleX(-1); }

.aps-slider__dots { display: flex; align-items: center; gap: var(--space-2); }
.aps-slider__dot {
  width: 10px; height: 10px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--color-navy-line);
  cursor: pointer;
  transition: background var(--t-base) var(--ease), width var(--t-base) var(--ease);
}
.aps-slider__dot:hover { background: var(--color-navy); }
.aps-slider__dot.is-active {
  width: 26px;
  border-radius: 5px;
  background: var(--color-orange);
}

.aps-hero__cue {
  position: absolute;
  z-index: 2;
  inset-block-end: var(--space-5);
  inset-inline-start: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  color: var(--color-navy);
  font-size: 0.68rem;
  font-weight: var(--fw-medium);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
html[dir="rtl"] .aps-hero__cue { transform: translateX(50%); }
.aps-hero__cue svg { animation: aps-bob 2.4s var(--ease) infinite; }
.aps-hero__cue:hover { color: var(--color-orange); }
@keyframes aps-bob {
  0%, 100% { transform: translateY(0); opacity: .6; }
  50%      { transform: translateY(5px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .aps-hero__cue svg { animation: none; }
  .aps-hero__media img { transform: none; }
}

/* On narrow screens the photo sits right behind the words - give them a panel. */
/* The photo sits right behind the words on a phone, so the text gets its own
   panel - kept translucent so the rig is still visible around and through it. */
@media (max-width: 760px) {
  .aps-hero__inner {
    padding: var(--space-5);
    border-radius: var(--radius-lg);
    background: rgba(255, 255, 255, 0.80);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    box-shadow: var(--shadow-md);
  }
  .aps-hero__title,
  .aps-hero__titles { max-width: none; }
  .aps-hero__sub { font-size: var(--fs-base); }
  .aps-slider__nav { margin-top: var(--space-5); }
}

/* ----------------------------- 2. overview ------------------------------ */
.aps-overview {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: var(--space-7);
  align-items: center;
}
.aps-overview__text p {
  color: var(--color-text);
  font-size: var(--fs-md);
  line-height: var(--lh-loose);
}
.aps-overview__media img {
  width: 100%;
  border-radius: var(--radius-lg);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-md);
}

/* --------------------------- 3. fields of activity ---------------------- */
.aps-field { text-align: start; }
.aps-field__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 62px; height: 62px;
  margin-bottom: var(--space-5);
  border-radius: var(--radius-lg);
  /* Solid navy, not a tint: an 8% wash on white is invisible at a glance. */
  background: var(--color-navy);
  color: #fff;
  box-shadow: var(--shadow-sm);
  transition: background var(--t-slow) var(--ease),
              transform var(--t-slow) var(--ease);
}
.aps-card:hover .aps-field__icon {
  background: var(--color-orange);
  transform: translateY(-2px);
}
.aps-field__title {
  margin-bottom: var(--space-3);
  color: var(--color-navy);
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
}
.aps-field__desc { color: var(--color-text-mut); font-size: var(--fs-sm); margin: 0; }

/* ----------------------------- 4. who we are ---------------------------- */
.aps-vm__label {
  margin-bottom: var(--space-3);
  color: var(--color-navy);
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
}
.aps-vm__label::after {
  content: '';
  display: block;
  width: 34px;
  height: 3px;
  margin-top: var(--space-2);
  border-radius: 2px;
  background: var(--color-orange);
}
.aps-vm p { color: var(--color-text); font-size: var(--fs-sm); line-height: var(--lh-loose); margin: 0; }

.aps-value { position: relative; padding-top: var(--space-7); }
.aps-value__num {
  position: absolute;
  inset-block-start: var(--space-4);
  inset-inline-start: var(--space-6);
  color: var(--color-orange-ink);   /* 13px - small text, needs 4.5:1 */
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
}
.aps-value__title {
  margin-bottom: var(--space-2);
  color: var(--color-navy);
  font-size: var(--fs-base);
  font-weight: var(--fw-semibold);
  line-height: 1.35;
}
.aps-value__desc { color: var(--color-text-mut); font-size: var(--fs-xs); margin: 0; }

.aps-why { margin-top: var(--space-6); }
.aps-why__label {
  margin-bottom: var(--space-5);
  color: var(--color-navy);
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
}
.aps-why__list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-3) var(--space-6);
  margin: 0; padding: 0;
  list-style: none;
}
.aps-why__list li {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-text);
  font-size: var(--fs-sm);
}
.aps-why__tick {
  color: #fff;
  background: var(--color-orange);
  width: 18px; height: 18px;
  min-width: 18px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  margin-top: 2px;
}

/* ------------------------------ 5. services ----------------------------- */
.aps-service { display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.aps-service__media { display: block; aspect-ratio: 16 / 10; overflow: hidden; background: var(--color-surface); }
.aps-service__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--t-slower) var(--ease);
}
.aps-service:hover .aps-service__media img { transform: scale(1.05); }
.aps-service__title {
  margin: var(--space-5) var(--space-5) var(--space-2);
  color: var(--color-navy);
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
}
.aps-service__desc {
  margin: 0 var(--space-5) var(--space-4);
  color: var(--color-text-mut);
  font-size: var(--fs-sm);
  flex: 1;
}
.aps-service__more {
  margin: 0 var(--space-5) var(--space-5);
  color: var(--color-orange-ink);   /* 15px - small text, needs 4.5:1 */
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
}

/* ------------------------------ 6. projects ----------------------------- */
.aps-project__title {
  margin-bottom: var(--space-2);
  color: var(--color-navy);
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
}
.aps-project__ref {
  margin-bottom: var(--space-4);
  color: var(--color-text-muted);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}
/* 13px. Today this only renders inside the navy band, where it is overridden to
   white - so this is defensive, for if projects ever sit on a light surface. */
.aps-project__ref .aps-num { color: var(--color-orange-ink); margin-inline-start: 6px; font-weight: var(--fw-semibold); }
.aps-project__meta {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-2) var(--space-4);
  margin: 0;
  font-size: var(--fs-sm);
}
.aps-project__meta dt {
  color: var(--color-text-muted);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  white-space: nowrap;
}
.aps-project__meta dd { margin: 0; color: var(--color-text); }

/* ------------------------------ 7. partners ----------------------------- */
.aps-partners {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-4);
  align-items: center;
}
.aps-partners__item {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 104px;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: #fff;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--t-slow) var(--ease),
              box-shadow var(--t-slow) var(--ease),
              transform var(--t-slow) var(--ease);
}
.aps-partners__item img {
  max-height: 60px;
  max-width: 100%;
  width: auto;
  object-fit: contain;
  /* Full desaturation plus low opacity erases pale logos on a white tile.
     Half-grey at near-full opacity keeps the wall calm but legible. */
  filter: grayscale(0.55) contrast(1.08);
  opacity: .92;
  transition: filter var(--t-slow) var(--ease), opacity var(--t-slow) var(--ease);
}
.aps-partners__item:hover {
  border-color: var(--color-orange);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}
.aps-partners__item:hover img { filter: none; opacity: 1; }

/* ------------------------------- 8. contact ----------------------------- */
.aps-contact { display: grid; grid-template-columns: 1.1fr 1fr; gap: var(--space-6); align-items: start; }
.aps-contact__details { display: grid; gap: var(--space-4); }
.aps-contact__row { display: flex; gap: var(--space-5); align-items: baseline; }
.aps-contact__label {
  min-width: 8rem;
  color: var(--color-navy);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}
.aps-contact__value { color: var(--color-text); display: flex; flex-direction: column; gap: 2px; }

/* ------------------------------ responsive ------------------------------ */
@media (max-width: 1100px) {
  .aps-grid--5 { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 900px) {
  .aps-grid--2,
  .aps-grid--3 { grid-template-columns: repeat(2, 1fr); }
  .aps-grid--5 { grid-template-columns: repeat(2, 1fr); }
  .aps-overview { grid-template-columns: 1fr; }
  .aps-contact  { grid-template-columns: 1fr; }
  .aps-why__list { grid-template-columns: 1fr; }
  .aps-section { padding-block: var(--space-8); }
}
@media (max-width: 620px) {
  .aps-grid--2,
  .aps-grid--3,
  .aps-grid--5 { grid-template-columns: 1fr; }
  .aps-hero { min-height: 74vh; }
  .aps-contact__row { flex-direction: column; gap: var(--space-1); }
  .aps-contact__label { min-width: 0; }
}
