/* ==========================================================================
   Ali Al-Nassar & Partners Company - Senior Designer Audit & Upgrades
   Features: 3D Ambient Canvas, Scroll Reveal, Parallax & Interactive Timeline
   ========================================================================== */

/* Fonts are loaded from a <link> in index.html, not @import.
   An @import here blocks rendering until the stylesheet itself has parsed and
   then fetches the fonts serially — the link tag downloads them in parallel. */

:root, [data-theme="light"] {
  --bg-primary: #f8fafc;
  --bg-secondary: #ffffff;
  --bg-tertiary: #f1f5f9;
  --bg-card: #ffffff;
  --bg-glass: rgba(255, 255, 255, 0.94);
  
  --text-primary: #0f172a;
  --text-secondary: #334155;
  --text-muted: #64748b;
  
  --brand-blue: #1d5db7;
  --brand-blue-hover: #164993;
  --accent-gold: #d97706;
  --accent-gold-hover: #b45309;
  --accent-emerald: #059669;
  
  --border-color: rgba(15, 23, 42, 0.09);
  --border-active: rgba(29, 93, 183, 0.5);
  
  --shadow-sm: 0 4px 12px rgba(15, 23, 42, 0.04);
  --shadow-md: 0 10px 30px rgba(15, 23, 42, 0.08);
  --shadow-lg: 0 20px 45px rgba(15, 23, 42, 0.12);
  --shadow-glow: 0 6px 25px rgba(29, 93, 183, 0.25);

  --radius-sm: 10px;
  --radius-md: 16px;
  --radius-lg: 24px;
  --radius-full: 9999px;

  --transition-fast: 0.2s ease;
  --transition-normal: 0.35s cubic-bezier(0.4, 0, 0.2, 1);
  --transition-bounce: 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);

  --font-heading: 'Outfit', sans-serif;
  --font-body: 'Inter', sans-serif;

  --header-height: 90px;
  --content-max: 1240px;
}

[data-theme="dark"] {
  --bg-primary: #0b1120;
  --bg-secondary: #0f172a;
  --bg-tertiary: #1e293b;
  --bg-card: rgba(30, 41, 59, 0.85);
  --bg-glass: rgba(15, 23, 42, 0.88);
  
  --text-primary: #f8fafc;
  --text-secondary: #94a3b8;
  --text-muted: #64748b;
  
  --brand-blue: #3b82f6;
  --brand-blue-hover: #2563eb;
  --accent-gold: #f59e0b;
  --accent-gold-hover: #d97706;
  
  --border-color: rgba(255, 255, 255, 0.1);
  --border-active: rgba(59, 130, 246, 0.5);
  
  --shadow-sm: 0 4px 12px rgba(0, 0, 0, 0.2);
  --shadow-md: 0 10px 30px rgba(0, 0, 0, 0.3);
  --shadow-lg: 0 20px 45px rgba(0, 0, 0, 0.4);
  --shadow-glow: 0 0 25px rgba(59, 130, 246, 0.25);
}

/* Reset & Base Styles */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
  font-size: 16px;
}

body {
  font-family: var(--font-body);
  background-color: var(--bg-primary);
  color: var(--text-primary);
  line-height: 1.6;
  /* clip, not hidden: overflow-x:hidden makes body a scroll container, which
     silently kills position:sticky for every descendant. clip contains the
     same horizontal overflow without becoming one. */
  overflow-x: clip;
  position: relative;
  transition: background-color var(--transition-normal), color var(--transition-normal);
}

a {
  color: inherit;
  text-decoration: none;
  transition: color var(--transition-fast);
}

ul {
  list-style: none;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

button {
  font-family: inherit;
  cursor: pointer;
  border: none;
  outline: none;
  background: none;
}

/* Typography Utility */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  font-weight: 700;
  line-height: 1.2;
  color: var(--text-primary);
}

.text-gold { color: var(--accent-gold); }
.text-blue { color: var(--brand-blue); }
.text-muted { color: var(--text-muted); }

.section-tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 18px;
  border-radius: var(--radius-full);
  background: rgba(29, 93, 183, 0.1);
  border: 1px solid rgba(29, 93, 183, 0.25);
  color: var(--brand-blue);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  margin-bottom: 14px;
}

.section-title {
  font-size: 2.6rem;
  margin-bottom: 16px;
  letter-spacing: -0.02em;
}

@media (max-width: 768px) {
  .section-title { font-size: 2.1rem; }
}

.section-subtitle {
  font-size: 1.12rem;
  color: var(--text-secondary);
  max-width: 680px;
  margin: 0 auto;
}

.container {
  width: 100%;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 0 24px;
}

/* ==========================================================================
   Senior Design Animations: Scroll Reveal & 3D Tilt
   ========================================================================== */
.reveal {
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 0.8s cubic-bezier(0.2, 0.8, 0.2, 1), transform 0.8s cubic-bezier(0.2, 0.8, 0.2, 1);
  will-change: opacity, transform;
}

/* These slide in horizontally, so before they trigger they sit 40px outside
   the viewport. html clips on the x axis to stop that scrolling the page —
   clip rather than hidden so position:sticky keeps working. */
html { overflow-x: clip; }

.reveal-left {
  opacity: 0;
  transform: translateX(-40px);
  transition: opacity 0.8s cubic-bezier(0.2, 0.8, 0.2, 1), transform 0.8s cubic-bezier(0.2, 0.8, 0.2, 1);
}

.reveal-right {
  opacity: 0;
  transform: translateX(40px);
  transition: opacity 0.8s cubic-bezier(0.2, 0.8, 0.2, 1), transform 0.8s cubic-bezier(0.2, 0.8, 0.2, 1);
}

.reveal.active, .reveal-left.active, .reveal-right.active {
  opacity: 1;
  transform: translate(0, 0);
}

/* 3D Dynamic Card Tilt Effect */
.card-tilt {
  transition: transform var(--transition-normal), box-shadow var(--transition-normal);
  transform-style: preserve-3d;
  perspective: 1000px;
}

.card-tilt:hover {
  transform: translateY(-8px) rotateX(3deg) rotateY(-3deg);
  box-shadow: var(--shadow-lg);
  border-color: var(--border-active);
}

/* ==========================================================================
   Header & Navigation
   ========================================================================== */
.header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--header-height);
  z-index: 1000;
  background: var(--bg-glass);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--border-color);
  transition: all var(--transition-normal);
}

.header.scrolled {
  height: 75px;
  box-shadow: var(--shadow-md);
}

.navbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;
}

.logo-container {
  display: flex;
  align-items: center;
}

/* Full legal name beside the wordmark. Hidden below 1200px, where the nav
   alone needs the whole bar. Above it the nav gap closes to 20px (see
   .nav-links) which frees ~85px — enough for this to sit alongside. */
.logo-lockup { display: none; }

@media (min-width: 1200px) {
  /* Never let the bar squeeze the lockup — it would spill over the nav. */
  .logo-container { gap: 13px; flex-shrink: 0; }
  .logo-lockup { flex-shrink: 0; }

  .logo-lockup {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding-inline-start: 13px;
    border-inline-start: 1px solid var(--border-color);
    text-transform: uppercase;
    white-space: nowrap;
  }

  .logo-lockup-name {
    font-family: var(--font-heading);
    font-size: 0.64rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    color: var(--text-primary);
  }

  .logo-lockup-meta {
    font-size: 0.53rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: var(--text-muted);
  }

  /* Arabic script joins, so letter-spacing breaks the glyphs apart and
     uppercase means nothing. Strip both. */
  [dir="rtl"] .logo-lockup { text-transform: none; }
  [dir="rtl"] .logo-lockup-name,
  [dir="rtl"] .logo-lockup-meta { letter-spacing: 0; }
  [dir="rtl"] .logo-lockup-name { font-size: 0.78rem; }
  [dir="rtl"] .logo-lockup-meta { font-size: 0.66rem; }
}
/* Wordmark only — 4.49:1, so these heights are much lower than the old
   full lockup or the logo would run ~250px wide in the header. */
.official-logo {
  height: 34px;
  width: auto;
  object-fit: contain;
  transition: height var(--transition-normal);
}

.header.scrolled .official-logo {
  height: 28px;
}

.official-logo-footer {
  height: 42px;
  width: auto;
  object-fit: contain;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 32px;
}

/* Eight nav items plus the logo, the name lockup and the action buttons share
   one bar. At a 32px nav gap that leaves 1px between groups from 1360px up; at
   20px it leaves ~47px. So the tighter gap runs all the way to 1600px, where
   the content column widens to 1440 and the pressure comes off. */
@media (max-width: 1599px) {
  .nav-links { gap: 18px; }
  .nav-link { font-size: 0.9rem; }
}

.nav-link {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-secondary);
  position: relative;
  padding: 8px 0;
}

.nav-link:hover {
  color: var(--brand-blue);
}

/* Active section pill — set by scroll-spy JS */
.nav-link.active {
  color: var(--brand-blue);
  background: rgba(29, 93, 183, 0.1);
  padding: 6px 14px;
  border-radius: var(--radius-full);
  font-weight: 700;
  margin: 0 -14px;   /* compensate padding so spacing stays even */
}

/* Hover underline bar */
.nav-link::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 0%;
  height: 3px;
  background: var(--brand-blue);
  transition: width var(--transition-fast);
  border-radius: 2px;
}

.nav-link:hover::after {
  width: 100%;
}

/* No underline when pill is showing */
.nav-link.active::after {
  width: 0;
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 16px;
}

.theme-toggle-btn {
  width: 42px;
  height: 42px;
  border-radius: var(--radius-full);
  background: var(--bg-tertiary);
  color: var(--text-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border-color);
  font-size: 1.1rem;
  transition: all var(--transition-fast);
}

.theme-toggle-btn:hover {
  background: rgba(29, 93, 183, 0.15);
  color: var(--brand-blue);
  border-color: var(--border-active);
}

.mobile-nav-toggle {
  display: none;
  font-size: 1.5rem;
  color: var(--text-primary);
}

@media (max-width: 992px) {
  .nav-links {
    position: fixed;
    top: var(--header-height);
    right: -100%;
    width: 280px;
    height: calc(100vh - var(--header-height));
    background: var(--bg-secondary);
    flex-direction: column;
    align-items: flex-start;
    padding: 32px;
    gap: 24px;
    box-shadow: var(--shadow-lg);
    transition: right var(--transition-normal);
    border-left: 1px solid var(--border-color);
  }

  .nav-links.open {
    right: 0;
  }

  .mobile-nav-toggle {
    display: block;
  }
}

/* ==========================================================================
   Hero Section with Parallax Depth
   ========================================================================== */
.hero {
  position: relative;
  min-height: 90vh;
  padding-top: calc(var(--header-height) + 30px);
  padding-bottom: 40px;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: radial-gradient(circle at 90% 10%, rgba(29, 93, 183, 0.08) 0%, transparent 45%),
              radial-gradient(circle at 10% 90%, rgba(217, 119, 6, 0.08) 0%, transparent 45%),
              linear-gradient(180deg, var(--bg-secondary) 0%, var(--bg-primary) 100%);
}

.hero-bg {
  position: absolute;
  top: 0;
  right: 0;
  width: 55%;
  height: 100%;
  background: url('images/hero-refinery.jpg?v=20260914') center/cover no-repeat;
  opacity: 0.15;
  mask-image: linear-gradient(to left, rgba(0,0,0,1) 40%, rgba(0,0,0,0) 100%);
  -webkit-mask-image: linear-gradient(to left, rgba(0,0,0,1) 40%, rgba(0,0,0,0) 100%);
  z-index: 1;
  transition: transform 0.1s ease-out;
}

.hero-content {
  position: relative;
  z-index: 2;
  max-width: 720px;
}

.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 20px;
  border-radius: var(--radius-full);
  background: rgba(29, 93, 183, 0.1);
  border: 1px solid rgba(29, 93, 183, 0.25);
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--brand-blue);
  margin-bottom: 24px;
}

.hero-title {
  font-size: 3.8rem;
  font-weight: 800;
  line-height: 1.12;
  margin-bottom: 24px;
  letter-spacing: -0.03em;
  color: var(--text-primary);
}

/* Gradient headline text.
   Applied to .grad for the un-split fallback, and again to the individual word
   spans once app.js splits the heading. The second rule is required, not
   decorative: .sw-i sets transform + will-change, which promotes each word to
   its own compositing layer, and an ancestor's background-clip:text cannot clip
   to glyphs in a promoted descendant. Without it the words inherit
   text-fill-color:transparent with nothing painting behind them — invisible. */
.hero-title .grad,
.hero-title .grad .sw-i {
  background: linear-gradient(120deg, var(--brand-blue), #38bdf8 45%, #1e40af);
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: gradShift 9s ease-in-out infinite;
}

@keyframes gradShift {
  0%, 100% { background-position: 0% 50%; }
  50%      { background-position: 100% 50%; }
}

.hero-description {
  font-size: 1.2rem;
  color: var(--text-secondary);
  margin-bottom: 40px;
  line-height: 1.7;
}

.hero-actions {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 28px;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 34px;
  border-radius: var(--radius-full);
  font-weight: 700;
  font-size: 1rem;
  transition: all var(--transition-normal);
}

.btn-primary {
  background: linear-gradient(135deg, var(--brand-blue), var(--brand-blue-hover));
  color: #ffffff;
  box-shadow: var(--shadow-glow);
}

.btn-primary:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 25px rgba(29, 93, 183, 0.4);
}

.btn-outline {
  background: var(--bg-card);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  box-shadow: var(--shadow-sm);
}

.btn-outline:hover {
  border-color: var(--brand-blue);
  color: var(--brand-blue);
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

/* Stats Bar */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  padding: 32px;
  background: var(--bg-card);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-color);
  box-shadow: var(--shadow-md);
}

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

.stat-number {
  font-family: var(--font-heading);
  font-size: 2.4rem;
  font-weight: 800;
  color: var(--brand-blue);
  line-height: 1;
  margin-bottom: 6px;
}

.stat-label {
  font-size: 0.88rem;
  color: var(--text-secondary);
  font-weight: 600;
}

@media (max-width: 992px) {
  .hero-title { font-size: 2.8rem; }
  .hero-bg { opacity: 0.1; width: 100%; }
  .stats-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 576px) {
  .hero-title { font-size: 2.2rem; }
  .stats-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   About Section
   ========================================================================== */
.about {
  padding: 60px 0;
  background: var(--bg-secondary);
  position: relative;
}

.about-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  /* stretch, not center: centring left the photo floating against the taller
     text column, starting below the eyebrow and stopping above the cards.
     Stretched, the two columns square up top and bottom. */
  align-items: stretch;
}

.about-image-wrapper {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--border-color);
}

.about-image-wrapper img {
  width: 100%;
  height: 100%;
  min-height: 480px;
  object-fit: cover;
  transition: transform 0.5s ease;
}

/* Inner-image drift is driven by app.js (initPhotoParallax) instead */

.about-experience-badge {
  position: absolute;
  z-index: 2;
  bottom: 24px;
  left: 24px;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(16px);
  border: 1px solid var(--border-active);
  padding: 20px 24px;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  display: flex;
  align-items: center;
  gap: 16px;
}

.exp-years {
  font-family: var(--font-heading);
  font-size: 2.8rem;
  font-weight: 800;
  color: var(--brand-blue);
  line-height: 1;
}

.exp-text {
  font-size: 0.9rem;
  font-weight: 700;
  color: #0f172a;
  line-height: 1.3;
}

.about-highlights {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin-top: 32px;
}

.highlight-card {
  padding: 20px;
  background: var(--bg-tertiary);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
}

.highlight-icon {
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  background: rgba(29, 93, 183, 0.12);
  color: var(--brand-blue);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  margin-bottom: 12px;
}

.highlight-title {
  font-size: 1.05rem;
  font-weight: 700;
  margin-bottom: 6px;
}

.highlight-desc {
  font-size: 0.88rem;
  color: var(--text-secondary);
}

@media (max-width: 992px) {
  .about-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Company Progress — Milestone Grid, One Screen
   --------------------------------------------------------------------------
   All sixteen milestones sit inside a single viewport height: no page scroll
   to reach the end of the timeline, and no horizontal track to drag. The
   section is one screen tall and lays itself out as a flex column — the
   header takes what it needs, the grid takes the rest and splits it into
   equal rows. Inside a card the heading is the fixed part and the photo is
   the flexible one, so the photo absorbs whatever height is left over at any
   viewport rather than every breakpoint needing its own pixel height.

   It replaces a full-bleed horizontal track that showed about five cards at a
   time behind a drag or a pair of arrows, and a phone fallback that stacked
   all sixteen into a column several screens tall.
   ========================================================================== */
.timeline-section {
  background: var(--bg-primary);
  position: relative;
  overflow: hidden;
  padding: clamp(20px, 4vh, 48px) 0 clamp(18px, 3.5vh, 40px);
  /* A ceiling, not a height. One screen minus the fixed header: html sets
     scroll-padding-top to the same amount, so a jump to #timeline lands the
     section top just under the header and its last row on the last visible
     pixel — nothing to scroll. Where the milestones need less than that the
     section simply ends, rather than stretching the cards apart to fill a
     screen. svh is the viewport with a phone's browser chrome showing, so it
     still fits while the URL bar is expanded; vh is the fallback.

     The 480px floor is for windows too short to hold the timeline at any
     readable size: there the page scrolls a little instead of crushing it. */
  height: auto;
  max-height: max(480px, calc(100vh - var(--header-height) - 24px));
  max-height: max(480px, calc(100svh - var(--header-height) - 24px));
  display: flex;
  flex-direction: column;
}

.timeline-section > .container { flex: 0 0 auto; }

.timeline-section .section-header { margin-bottom: 0; }

/* Grid wrapper. --tl-cols and the two gaps are the only knobs the breakpoints
   at the foot of this block touch; everything else follows the cell.

   Fourteen columns is one column per milestone: the whole timeline on a single
   rail. The side padding is wide because a card is two columns across and
   overhangs its own cell — see the alternating block below. Viewports under
   1100px cannot hold fourteen columns and drop to a stacked grid there. */
.timeline-grid {
  --tl-cols: 14;
  /* Every 8px here costs about 7px of card width and buys 8px of daylight
     between neighbours. At 8px the cards nearly touched — 14px apart. It
     scales with the viewport rather than sitting fixed: a fixed gap takes the
     same bite out of a 1100px screen as a 1920px one, and there the cards can
     least afford it. */
  --tl-gap: clamp(16px, 1.5vw, 28px);
  --tl-row-gap: 22px;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: var(--content-max);
  margin: clamp(14px, 3vh, 40px) auto 0;
  padding: 0 clamp(40px, 4.5vw, 80px);
  /* clips the half-gap rail stubs overhanging the first and last column */
  overflow: hidden;
}

/* minmax(0, 1fr) rows: every row is an equal share of the height left after
   the header, and none of them can be pushed taller by its own content. */
.timeline-grid-track {
  /* the travelling tick measures itself against this box — without it the tick
     resolves against the whole section, header included */
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(var(--tl-cols), minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: var(--tl-row-gap) var(--tl-gap);
  padding-top: 8px;
}

/* Marker stack, top to bottom: dot on the rail, stem, year chip, card. */
.timeline-node {
  /* --tl-i is the node's index, set by app.js; --tl-t is when its part of the
     entrance below starts. */
  --tl-t: calc(var(--tl-i, 0) * 0.06s);
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  min-height: 0;
}

.timeline-node-dot  { order: 1; }
.timeline-node-stem { order: 2; }
.timeline-year      { order: 3; }
.timeline-node-card { order: 4; }

/* Rail segment. It reaches half a column gap to either side so neighbours in
   the same row join into one line; a row that ends early just stops there.
   It is ::after because ::before is the alternating layout's spacer. */
.timeline-node::after {
  content: '';
  position: absolute;
  top: 6px;
  left: calc(var(--tl-gap) / -2);
  right: calc(var(--tl-gap) / -2);
  height: 2px;
  background: rgba(29, 93, 183, 0.3);
  z-index: 0;
}

.timeline-year {
  height: 28px;
  display: inline-flex;
  align-items: center;
  padding: 0 12px;
  border-radius: var(--radius-full);
  background: rgba(29, 93, 183, 0.1);
  border: 1px solid rgba(29, 93, 183, 0.2);
  color: var(--brand-blue);
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: 0.86rem;
  letter-spacing: 0.5px;
  flex-shrink: 0;
}

.timeline-node-stem {
  width: 2px;
  height: 12px;
  background: linear-gradient(180deg, var(--brand-blue), rgba(29, 93, 183, 0.35));
  flex-shrink: 0;
}

/* Dot sits on the rail, with a concentric ring around it */
.timeline-node-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--brand-blue);
  border: 3px solid var(--bg-primary);
  box-shadow: 0 0 0 4px rgba(29, 93, 183, 0.22), 0 0 14px rgba(29, 93, 183, 0.45);
  flex-shrink: 0;
  position: relative;
  z-index: 3;
  transition: transform var(--transition-bounce), box-shadow var(--transition-fast);
}

.timeline-node-card {
  /* 0 1: take the height the photo asks for, but give it back on a screen too
     short to grant it. Stretching to fill the cell is what put a band of empty
     card above and below every landscape photo. */
  flex: 0 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  margin-top: 10px;
  background: var(--bg-card);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
  padding: 0;
  box-shadow: var(--shadow-sm);
  width: 100%;
  transition: transform var(--transition-normal), border-color var(--transition-normal),
              box-shadow var(--transition-normal);
  position: relative;
}

/* Floating preview of a milestone photo, raised on hover (tap on touch).
   pointer-events:none so it never steals the hover from the card beneath. */
.ms-preview {
  position: fixed;
  z-index: 1500;
  left: 0;
  top: 0;
  /* The division photo already renders about 576px wide, so a 470px popup
     would have been smaller than the thing it is meant to enlarge. */
  max-width: min(760px, 92vw);
  padding: 8px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: 14px;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: scale(0.97);
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
  pointer-events: none;
}

.ms-preview.is-on {
  opacity: 1;
  visibility: visible;
  transform: scale(1);
}

.ms-preview img {
  display: block;
  max-width: 100%;
  max-height: 62vh;
  width: auto;
  height: auto;
  border-radius: 8px;
}

/* Cards now carry a picture and a heading — no body copy. */
/* The photo is the card's elastic part: flex-basis 0 with grow means it takes
   whatever height the heading leaves, at any column count or screen height,
   and object-fit crops rather than distorts whatever shape that comes out. */
.timeline-node-card img {
  display: block;
  position: relative;
  z-index: 1;
  /* 4/3 is the middle of the fifteen milestone shapes, so the frame the photo
     is fitted into is close to the photo for most of them and the leftover
     falls outside the card rather than inside it. */
  flex: 0 1 auto;
  aspect-ratio: 4 / 3;
  min-height: 0;
  width: 100%;
  height: auto;
  /* Fill the frame edge to edge — no letterbox bars around the photo. */
  object-fit: cover;
  border-radius: 0;
  margin-bottom: 0;
  background: var(--bg-secondary);
}

/* Milestones show whole rather than cropped to fill: several of them are
   documents — a certificate, an approval letter, a storefront panorama — where
   a cover crop hides the half that carries the meaning. Their shapes run from
   a 0.68 portrait certificate to a 2.4 wide logo, so containing them always
   leaves bars; each card fills its own with a blurred copy of its photo, and
   so still reads as a photo rather than a picture on a grey plate.

   --ms-img is set by app.js from the img's own src — CSS cannot read a child's
   attribute, and repeating fifteen file names here would be a second place to
   update. Without scripting the bars fall back to a flat neutral. */
.timeline-node-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--bg-secondary) var(--ms-img, none) center / cover no-repeat;
  filter: blur(16px) brightness(0.92);
  transform: scale(1.2);
}

/* Three lines is the longest any milestone heading runs at the narrowest
   column, and capping it stops one long heading squeezing a photo to nothing. */
.timeline-node-card h4 {
  flex: 0 0 auto;
  font-size: clamp(0.72rem, 0.64rem + 0.28vw, 0.92rem);
  margin-bottom: 0;
  padding: 8px 10px 10px;
  line-height: 1.28;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.timeline-node-card p { /* no longer used — headings only */
  display: none;
}

.timeline-node-card p.legacy {
  color: var(--text-secondary);
  font-size: 0.82rem;
  line-height: 1.55;
}

/* The spotlight the travelling tick hands each card as it arrives. It rides on
   the card's ::after rather than the card itself, for two reasons: the card
   already carries the entrance animation, and its own box-shadow belongs to
   the hover state — animating that would leave hover with nothing to change.

   Same 9.8s cycle as the tick, offset by the node's index, so a card lights the
   moment the tick lands on its dot and fades as the tick moves on. The card
   clips its overflow to hold the photo, so the ring is inset rather than
   drawn around the outside. */
.timeline-grid-track.stagger.in .timeline-node-card::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 2px rgba(56, 189, 248, 0.85);
  background: radial-gradient(130% 100% at 50% 0%,
    rgba(56, 189, 248, 0.3), rgba(56, 189, 248, 0.07) 65%, transparent);
  opacity: 0;
  animation: tlSpot 9.8s linear infinite;
  animation-delay: calc(1.7s + var(--tl-i, 0) * 0.7s);
}

/* 7% of 9.8s is one step: lit for exactly as long as the tick stands on it,
   then a slower release so the trail reads as movement rather than a blink. */
@keyframes tlSpot {
  0%   { opacity: 0; }
  2%   { opacity: 1; }
  7%   { opacity: 1; }
  17%  { opacity: 0; }
  100% { opacity: 0; }
}

/* The pulse each landing gives, shared by the horizontal and vertical ticks.
   Its duration is one step, so the two animations stay in phase for as long as
   they run. */
@keyframes tlTickBeat {
  0%   { scale: 1.55; opacity: 1; }
  55%  { scale: 1;    opacity: 0.5; }
  100% { scale: 1;    opacity: 0.32; }
}

/* --- Fitting sixteen cards into one screen ---------------------------------
   Two variables trade against each other: fewer columns read better across
   but cost a row, and every extra row is height the photos lose. The counts
   below are the widest cards each viewport can hold in few enough rows to
   stay on one screen. */
@media (max-width: 1099px) {
  .timeline-grid {
    --tl-cols: 6;
    --tl-gap: 16px;
    padding: 0 24px;
  }
}

/* Four rows leave no height for a dot, a stem and a chip stacked above each
   card, so the marker collapses: the rail goes and the year rides on the
   photo, giving the whole row back to the card. */
@media (max-width: 899px) {
  /* No ceiling below this width. Held to one screen, four rows of cards plus
     the rail squeeze every photo into a letterboxed sliver, and on a short
     phone the last milestone was being chopped off the foot outright. Both are
     worse than the page scrolling a little to show the section whole. The
     subtitle goes to keep that scroll as short as it can be. */
  .timeline-section { max-height: none; }

  .timeline-section .section-subtitle { display: none; }

  .timeline-grid {
    --tl-cols: 4;
    --tl-gap: 14px;
    --tl-row-gap: 18px;
  }

  /* The stem and the year chip above the card cost more height than four rows
     can spare, so the year moves onto the photo and the stem goes. The rail
     and its dot stay: without them the cards float with nothing joining them,
     which is the one thing every other width in this section avoids. */
  .timeline-node-stem { display: none; }

  .timeline-node-card { margin-top: 10px; }

  .timeline-year {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 4;
    height: 22px;
    padding: 0 9px;
    font-size: 0.74rem;
    background: rgba(255, 255, 255, 0.92);
    border-color: rgba(29, 93, 183, 0.28);
    /* the node now opens with the dot, so the badge clears it */
    margin-top: 24px;
  }
}

/* Phones: two columns hung off a spine down the middle --------------------
   A stacked card cannot be read in the ~55px a row gets at fourteen
   milestones, so the photo sits beside the heading as a thumbnail.

   The years ride on the line itself, one per milestone, and the line is
   measured against them — there is no separate dot at this size, the chip is
   the marker. The two columns are offset half a row against each other so the
   chips come down the line one at a time; level rows would stack two of them
   on the same point. The row height is fixed here rather than driven by
   content precisely so that half-row offset is exact. */
@media (max-width: 599px) {
  /* Seven rows of two need every pixel; the heading block is where they come
     from. */
  .timeline-section .section-subtitle,
  .timeline-section .section-tag { display: none; }

  .timeline-section .section-title {
    font-size: 1.45rem;
    margin-bottom: 0;
  }

  .timeline-grid {
    --tl-cols: 2;
    /* no year label above the tile any more, so the row can be shorter and the
       thumbnail inside it larger */
    --tl-row: clamp(50px, 6.2vh, 58px);
    --tl-gap: 44px;        /* the gutter, wide enough to seat a year chip */
    --tl-row-gap: 10px;
    --tl-drop: calc(var(--tl-row) / 2 + var(--tl-row-gap) / 2);
    padding: 0 14px;
    /* the chips sit out in the gutter, so nothing may be clipped here */
    overflow: visible;
  }

  .timeline-grid-track {
    grid-auto-rows: var(--tl-row);
    padding-bottom: var(--tl-drop);
  }

  /* The spine, drawn from the first year chip to the last so it never
     overshoots one end or leaves the other stranded off the line.

     Offsets are measured from the track's border box: 8px of padding-top plus
     half a row puts the head on the first chip's centre. At the foot the last
     chip sits half a row up from the bottom padding edge — the half-row the
     right column drops by cancels against the padding-bottom that makes room
     for it. (That cancelling assumes an even number of milestones, so the last
     one is in the offset column.) */
  .timeline-grid-track::after {
    content: '';
    position: absolute;
    top: calc(8px + var(--tl-row) / 2);
    bottom: calc(var(--tl-row) / 2);
    left: 50%;
    width: 2px;
    margin-left: -1px;
    background: rgba(29, 93, 183, 0.28);
    transform-origin: top center;
  }

  /* The right column hangs half a row lower, so the chips come down the spine
     one at a time instead of in pairs.

     Offset with `top`, not `translate`: this is layout, not animation, and the
     reduced-motion block clears `translate` on every .stagger child to cancel
     the entrance. That reset would flatten the two columns back level and put
     seven pairs of chips on the same point of the line. */
  .timeline-node:nth-child(even) { top: var(--tl-drop); }

  /* The spine replaces the per-row rail segments of the wider layouts, and the
     year chip replaces the dot on it — two markers on one point would only
     collide. */
  .timeline-node::after,
  .timeline-node-dot,
  .timeline-node-stem { display: none; }

  .timeline-node { align-items: stretch; }

  /* The year rides the line, level with the middle of its own card. Half the
     gutter carries it from the node edge out to the line, and the 50%
     translate centres it there. It is filled with the section background so
     the line does not run through the digits. */
  .timeline-year {
    position: absolute;
    top: 50%;
    z-index: 3;
    height: auto;
    padding: 2px 6px;
    background: var(--bg-primary);
    border: 0;
    border-radius: var(--radius-full);
    font-size: 0.6rem;
    line-height: 1.1;
    white-space: nowrap;
    margin: 0;
  }

  /* left:auto / right:auto matter: the wider layout pins this chip to the
     card's top-left corner, and a leftover edge from that would anchor it
     back inside the card instead of out on the line. */
  .timeline-node:nth-child(odd) .timeline-year {
    left: auto;
    right: calc(var(--tl-gap) / -2);
    transform: translate(50%, -50%);
  }

  .timeline-node:nth-child(even) .timeline-year {
    right: auto;
    left: calc(var(--tl-gap) / -2);
    transform: translate(-50%, -50%);
  }

  /* The row is a fixed height here, so the tile fills it rather than hugging
     its photo the way it does where the row follows its content. */
  .timeline-node-card {
    flex: 1 1 auto;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    margin-top: 0;
    padding: 5px;
  }

  /* No blurred plate at this size — there is nothing to letterbox behind a
     square that small. */
  .timeline-node-card::before { display: none; }

  /* Square thumbnail as tall as the tile, so it tracks the row height instead
     of being a fixed size that overflows a short row or floats in a tall one. */
  .timeline-node-card img {
    flex: 0 0 auto;
    align-self: stretch;
    width: auto;
    height: auto;
    aspect-ratio: 1;
    border-radius: 6px;
    margin-bottom: 0;
  }

  .timeline-node-card h4 {
    flex: 1 1 auto;
    padding: 0;
    font-size: 0.62rem;
    line-height: 1.22;
  }

  /* The same tick, walking down the spine instead of across a rail. The chips
     are evenly spaced by --tl-drop, so one step is exactly that. */
  .timeline-grid-track.stagger.in::before {
    content: '';
    position: absolute;
    top: calc(8px + var(--tl-row) / 2);
    left: 50%;
    width: 26px;
    height: 26px;
    margin: -13px 0 0 -13px;
    z-index: 1;
    pointer-events: none;
    background: radial-gradient(circle 11px at 50% 50%,
      rgba(56, 189, 248, 0.9), rgba(56, 189, 248, 0));
    animation: tlTickDown 9.8s steps(14, jump-none) 1.7s infinite,
               tlTickBeat 0.7s ease-out 1.7s infinite;
  }

  @keyframes tlTickDown {
    to { translate: 0 calc(var(--tl-drop) * 13); }
  }

  /* The spine draws down the screen while the dots arrive on it. */
  .timeline-grid-track.stagger::after { scale: 1 0; }

  .timeline-grid-track.stagger.in::after {
    animation: tlSpine 0.95s ease-out both;
  }

  @keyframes tlSpine {
    to { scale: 1 1; }
  }
}

/* The narrowest phones: the chips shrink rather than the gutter, so the
   longest of them ("Today") still clears the cards on either side. */
@media (max-width: 380px) {
  .timeline-grid { padding: 0 10px; }

  .timeline-year {
    padding: 2px 5px;
    font-size: 0.55rem;
  }
}
/* --- One rail, milestones alternating above and below it ------------------
   All sixteen on a single line. A column per milestone is only ~65px wide, far
   too narrow for a card — but alternating means a card never shares vertical
   space with its neighbour, so it can be two columns across and overhang the
   cells on either side. Adjacent cards on the same side of the rail sit two
   columns apart, which is what leaves room for that.

   One row also means one card's height per side rather than two, so the cards
   here are the tallest of any layout in this section. Below 1100px sixteen
   columns stop fitting and the stacked grid above takes over. */
@media (min-width: 1100px) {
  /* The row is as tall as a node needs rather than a share of the screen. */
  .timeline-grid-track { grid-auto-rows: auto; }

  /* The spacer that fills the empty half opposite each card. It is a copy of
     the card's box plus the marker stack that follows it, less the dot's own
     height — that last subtraction is what lands the up and the down dots on
     the same line and the line itself at exactly 50% of the node. In a
     column-reverse column the spacer falls on the other side, mirroring the
     whole stack without touching the markup, so only the margin changes sides.

     It is measured against the far level for every node, near ones included:
     the dot sits at spacer + margin, so holding that sum constant is what
     keeps all fourteen dots on one line while the cards stand at two
     different heights. */
  .timeline-node::before {
    content: '';
    flex: 0 0 auto;
    width: 100%;
    aspect-ratio: 4 / 3;
    margin-bottom: calc(32px + var(--tl-stem-far));
  }

  .timeline-node:nth-child(odd)::before {
    margin-bottom: 0;
    margin-top: calc(32px + var(--tl-stem-far));
  }

  .timeline-node:nth-child(odd) { flex-direction: column-reverse; }

  /* The rail runs through the middle of the node, not along its top. */
  .timeline-node::after { top: 50%; }

  /* The stem fades from the card towards the dot, so it flips with the column. */
  .timeline-node:nth-child(odd) .timeline-node-stem { transform: scaleY(-1); }

  /* The year sits against the rail and the stem runs on from it out to the
     card, rather than the stem being a short tick with the year floating
     mid-stack. That is what opens a gap between the line and the cards, with a
     drawn connector across it. */
  .timeline-node-dot  { order: 1; }
  .timeline-year      { order: 2; }
  .timeline-node-stem { order: 3; }
  .timeline-node-card { order: 4; }

  /* Chips alternate sides of the rail with their cards, so neighbouring years
     never meet even where they are wider than their own column. */
  .timeline-year {
    height: 26px;
    padding: 0 10px;
    font-size: 0.78rem;
  }

  /* Read the run above the line and the pattern is plain: 1970 sits at the
     near level, 1992 steps out to the far one, 2001 comes back to near, 2004
     goes far. Those are milestones 1, 3, 5, 7 — so odd nodes alternate near,
     far, near, far, which is 4n+1 near and 4n+3 far. The even nodes below the
     line take the opposite phase and alternate the same way. */
  .timeline-node-stem { height: var(--tl-stem-near); }

  .timeline-node:nth-child(4n + 2) .timeline-node-stem,
  .timeline-node:nth-child(4n + 3) .timeline-node-stem {
    height: var(--tl-stem-far);
  }

  /* A tick that walks the rail and stops on each milestone. steps() rather
     than a smooth glide is the whole point: it lands, holds, and jumps, which
     is what reads as a clock instead of a scanner.

     The marker is exactly one column pitch wide — (100% + gap) / 14 — so a
     single 100% translate carries it from one milestone to the next, and 14
     stops cover all of them. The negative margin takes off the half gap that
     pitch adds ahead of the first dot. */
  .timeline-grid-track.stagger.in::before {
    content: '';
    position: absolute;
    top: calc(50% + 4px);      /* the rail, allowing for the track's padding */
    left: 0;
    width: calc((100% + var(--tl-gap)) / 14);
    margin-left: calc(var(--tl-gap) / -2);
    height: 26px;
    margin-top: -13px;
    z-index: 1;
    pointer-events: none;
    background: radial-gradient(circle 12px at 50% 50%,
      rgba(56, 189, 248, 0.9), rgba(56, 189, 248, 0));
    /* one step per 0.7s, and the beat runs at that same 0.7s so every pulse
       falls on a landing. It starts after the entrance has finished. */
    animation: tlTickAcross 9.8s steps(14, jump-none) 1.7s infinite,
               tlTickBeat 0.7s ease-out 1.7s infinite;
  }

  @keyframes tlTickAcross {
    to { translate: 1300% 0; }
  }

  /* Two columns wide, centred on its own — align-items: center lets it
     overhang both neighbours evenly. max-height keeps a tall window from
     stretching the card past the shape its photo can fill; the slack falls on
     the outer edge, so the cards stay hugged to the rail. */
  .timeline-node-card {
    width: calc(200% + var(--tl-gap) - 6px);
    aspect-ratio: 4 / 3;
    padding: 0;
  }

  .timeline-node:nth-child(odd)  .timeline-node-card { margin: 0 0 6px; }
  .timeline-node:nth-child(even) .timeline-node-card { margin: 6px 0 0; }

  /* The photo fills the card from behind, which leaves the heading as the only
     thing in the flex column — so it can stay in normal flow, where
     -webkit-line-clamp actually shortens the box instead of only drawing an
     ellipsis under it. */
  .timeline-node-card img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin-bottom: 0;
    border-radius: 0;
  }

  /* Three lines over the foot of the photo. The gradient reaches full strength
     behind the text, so a pale photo — a certificate, a logo on white — still
     carries white type. */
  .timeline-node-card h4 {
    position: relative;
    z-index: 2;
    margin-top: auto;
    /* The bottom gap is a transparent border, not padding: overflow clips at
       the padding box, so with padding here a clamped fourth line bleeds its
       top few pixels into the gap. A border sits outside that box, and the
       gradient still paints across it. */
    padding: 16px 10px 0;
    border-bottom: 8px solid transparent;
    color: #ffffff;
    background: linear-gradient(to top,
      rgba(8, 15, 30, 0.9),
      rgba(8, 15, 30, 0.62) 55%,
      rgba(8, 15, 30, 0));
    font-size: 0.76rem;
    line-height: 1.22;
    -webkit-line-clamp: 3;
  }
}

/* A short viewport is as tight as a narrow one. The heading block is the only
   part that can give height back without shrinking a card, and a 768px-tall
   laptop needs it as much as a phone does. */
@media (max-height: 900px) {
  .timeline-section .section-subtitle { display: none; }
  .timeline-section .section-title { font-size: clamp(1.5rem, 3vw, 2.2rem); }
}

/* ==========================================================================
   The milestone strip travels, like the manufacturers marquee
   --------------------------------------------------------------------------
   Same mechanics as .logo-marquee above: the track carries two identical sets
   and translates exactly half its own width, so the copies land where the
   originals began and the loop has no seam. The spacing rides on each node
   rather than on a flex gap — a gap sits only *between* items, so 28 nodes
   would carry 27 of them and half the track would fall one gap short. That is
   the same reason .marquee-group carries a trailing padding equal to its gap.

   app.js adds and removes the second set as the layout crosses 1100px: below
   that these nodes are a stacked grid or a vertical spine, where a second set
   would simply be fourteen more rows.

   The cards keep the size and the above/below alternation they already had —
   only the fitting-fourteen-across constraint is lifted, which is what lets
   the gaps breathe.
   ========================================================================== */
@media (min-width: 1100px) {
  /* The section fills the screen here rather than ending where its content
     does. The strip keeps its own height and is centred in what is left after
     the heading, so the milestones stay the size they are and the slack falls
     evenly above and below them. */
  .timeline-section {
    height: calc(100vh - var(--header-height) - 24px);
    height: calc(100svh - var(--header-height) - 24px);
  }

  .timeline-grid {
    justify-content: center;
  }

  .timeline-grid-track {
    flex: 0 0 auto;
  }

  .timeline-grid {
    /* Point-to-point distance is the card width plus this gap, so the gap on
       its own only moves it so far — most of the span is the card. Both come
       down together to close the milestones up. */
    --tl-node-w: clamp(146px, 9.75vw, 190px);
    --tl-gap: 12px;
    max-width: none;
    padding: 0;
    /* the same edge fade the manufacturers strip uses, so cards arrive and
       leave rather than popping at a hard edge */
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
    mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  }

  .timeline-grid {
    /* How far a card stands off the line. Two distances, not one: the cards
       step far, near, near, far as you go along, so they stagger instead of
       forming two flat rows. Both scale with the viewport height, which is
       what the one-screen rule constrains — a fixed 74px reads well at 1000px
       tall and overflows a 700px one. */
    --tl-stem-far: clamp(21px, 4.2vh, 52px);
    --tl-stem-near: calc(var(--tl-stem-far) * 0.4);
  }

  .timeline-grid-track {
    display: flex;
    width: max-content;
    gap: 0;
    padding-top: 8px;
    /* starts once the entrance has finished drawing the rail */
    animation: tlMarquee 64s linear 1.6s infinite;
  }

  /* stop for anyone reading it, exactly as the marquee does */
  .timeline-grid:hover .timeline-grid-track {
    animation-play-state: paused;
  }

  @keyframes tlMarquee {
    to { translate: -50% 0; }
  }

  .timeline-node {
    flex: 0 0 var(--tl-node-w);
    height: auto;
    margin-right: var(--tl-gap);
  }

  /* one node wide now, not two: nothing has to overhang its neighbours once
     the strip is no longer being squeezed into the viewport */
  .timeline-node-card,
  .timeline-node::before {
    width: 100%;
  }

  /* Two milestones are documents rather than scenes — a certificate and an
     approval letter. The heading rides over the foot of the photo, which is
     fine for a yard or a warehouse but cuts the bottom third off a document
     and leaves only its middle readable. For those two the picture is held
     above the heading instead of behind it: whole, if smaller.

     The inset is the tallest the heading can get — its padding and border plus
     three lines, which is where the line-clamp stops it. */
  /* The heading over a document is a slim bar rather than the tall gradient a
     photo gets: every pixel it gives back is a pixel the document grows by,
     and there is no photo underneath for it to blend into. */
  .timeline-node-card.is-doc h4 {
    padding-top: 8px;
    border-bottom-width: 5px;
    -webkit-line-clamp: 2;
  }

  /* A certificate is portrait and the card is landscape, so fitting the whole
     page inside left it small with white either side. It fills the card
     instead, anchored to the top — the masthead and title are the half worth
     showing at this size, and the whole page is still one hover away. */
  .timeline-node-card.is-doc img {
    bottom: 0;
    height: 100%;
    aspect-ratio: auto;
    object-fit: cover;
    object-position: center top;
  }

  /* The travelling tick was pinned to fourteen columns fitted across the
     viewport. The strip itself is the movement now; the spotlight stays,
     since its timing never depended on where a card sat. */
  .timeline-grid-track.stagger.in::before {
    display: none;
  }
}

/* A moving strip cannot be read by anyone who has asked motion to stop, and
   there is no room to show it all at rest — so it holds still and scrolls. */
@media (min-width: 1100px) and (prefers-reduced-motion: reduce) {
  .timeline-grid {
    overflow-x: auto;
    scrollbar-width: thin;
  }

  .timeline-grid-track { animation: none; }
}

/* --- Entrance: the rail draws, the dots land on it, the cards open out -----
   The shared .stagger entrance lifts every child by the same 36px, which reads
   wrong here: these cards belong to a line, and the line should arrive first.
   So the node itself is left alone and its parts are animated instead, each
   timed off --tl-i — the chronological index app.js writes onto the node — so
   the whole thing runs left to right in the order the milestones happened.

   Every initial state is scoped to .stagger, the class app.js adds. Without
   scripting nothing is hidden and the timeline just renders. */
.timeline-grid-track.stagger > * { opacity: 1; }
.timeline-grid-track.stagger.in > * { animation: none; }

/* The rail segment wipes in from its left edge, so consecutive segments read
   as one line being drawn across the row. */
.timeline-grid-track.stagger .timeline-node::after {
  transform-origin: left center;
  scale: 0 1;
}

/* Kept close to the 0.06s step between nodes on purpose: a longer wipe leaves
   half a dozen segments part-drawn at once and the leading edge breaks up into
   dashes instead of reading as one line being drawn. */
.timeline-grid-track.stagger.in .timeline-node::after {
  animation: tlRail 0.14s linear both;
  animation-delay: var(--tl-t);
}

@keyframes tlRail {
  to { scale: 1 1; }
}

/* The dot lands a beat after the line reaches it. `scale` rather than
   `transform` so the hover lift and the 3D tilt still compose on top. */
.timeline-grid-track.stagger .timeline-node-dot { scale: 0; }

.timeline-grid-track.stagger.in .timeline-node-dot {
  animation: tlDot 0.44s cubic-bezier(0.34, 1.56, 0.64, 1) both;
  animation-delay: calc(var(--tl-t) + 0.1s);
}

@keyframes tlDot {
  from { scale: 0; }
  to   { scale: 1; }
}

/* A ring that expands once out of the dot as it lands, then is gone. */
.timeline-grid-track.stagger.in .timeline-node-dot::after {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 2px solid rgba(29, 93, 183, 0.5);
  animation: tlPing 0.75s ease-out both;
  animation-delay: calc(var(--tl-t) + 0.1s);
  pointer-events: none;
}

@keyframes tlPing {
  from { opacity: 0.75; scale: 0.5; }
  to   { opacity: 0;    scale: 2.6; }
}

/* Stem, year and card travel outwards from the rail together. */
.timeline-grid-track.stagger .timeline-node-stem,
.timeline-grid-track.stagger .timeline-year,
.timeline-grid-track.stagger .timeline-node-card {
  opacity: 0;
}

.timeline-grid-track.stagger.in .timeline-node-stem,
.timeline-grid-track.stagger.in .timeline-year,
.timeline-grid-track.stagger.in .timeline-node-card {
  animation: tlOpenDown 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
  animation-delay: calc(var(--tl-t) + 0.16s);
}

@keyframes tlOpenDown {
  from { opacity: 0; translate: 0 -16px; }
  to   { opacity: 1; translate: 0 0; }
}

@keyframes tlOpenUp {
  from { opacity: 0; translate: 0 16px; }
  to   { opacity: 1; translate: 0 0; }
}

/* Above the rail, outwards is upwards. Only the single-rail layout puts nodes
   there; everywhere else every card hangs below its year. */
@media (min-width: 1100px) {
  .timeline-grid-track.stagger.in .timeline-node:nth-child(odd) .timeline-node-stem,
  .timeline-grid-track.stagger.in .timeline-node:nth-child(odd) .timeline-year,
  .timeline-grid-track.stagger.in .timeline-node:nth-child(odd) .timeline-node-card {
    animation-name: tlOpenUp;
  }
}

/* ==========================================================================
   Business Divisions (Explorer & Tabs)
   ========================================================================== */
.divisions {
  padding: 60px 0;
  background: var(--bg-secondary);
}

.section-header {
  text-align: center;
  margin-bottom: 28px;
}

.division-tabs {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 24px;
}

.tab-btn {
  padding: 12px 26px;
  border-radius: var(--radius-full);
  background: var(--bg-card);
  color: var(--text-secondary);
  font-weight: 600;
  font-size: 0.95rem;
  border: 1px solid var(--border-color);
  box-shadow: var(--shadow-sm);
  transition: all var(--transition-fast);
}

.tab-btn:hover {
  color: var(--text-primary);
  border-color: rgba(29, 93, 183, 0.4);
}

.tab-btn.active {
  background: linear-gradient(135deg, var(--brand-blue), var(--brand-blue-hover));
  color: #ffffff;
  border-color: transparent;
  box-shadow: var(--shadow-glow);
}

.tab-content {
  display: none;
  animation: fadeIn 0.4s ease forwards;
}

.tab-content.active {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 40px;
  align-items: center;
}

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

.division-info {
  display: flex;
  flex-direction: column;
}

.division-info h3 {
  font-size: 2rem;
  margin-bottom: 16px;
}

.division-info p {
  color: var(--text-secondary);
  margin-bottom: 24px;
  line-height: 1.7;
}

.product-list-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  margin-bottom: 32px;
}

/* Twenty-two products need signposting; six did not. The label spans both
   columns so each group reads as a band across the list. */
.product-group {
  grid-column: 1 / -1;
  margin: 10px 0 -4px;
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.product-group:first-child { margin-top: 0; }

.product-chip {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  background: var(--bg-card);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
  box-shadow: var(--shadow-sm);
  font-size: 0.92rem;
  font-weight: 600;
  transition: border-color var(--transition-fast);
}

.product-chip i {
  color: var(--brand-blue);
  font-size: 1.1rem;
}

.product-chip:hover {
  border-color: var(--border-active);
}

.division-media {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border-color);
  box-shadow: var(--shadow-lg);
  height: 420px;
}

.division-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The frame runs about 1.42:1 at a 1240 container and 1.67:1 at 1440, while
   most of the product photos the chips point at are 1.37:1 — so cover was
   cutting away up to a fifth of their height, and cutting it off-centre once
   the drift's scale(1.12) was applied on top. contain shows the whole part instead, and
   the wash is dropped because multiplying blue over a white product sweep
   tints it. All three effects still belong to the division's own picture. */
/* Client request: product photos fill the frame edge to edge rather than
   sitting in white bands. Centred, so any trim comes evenly off the edges. */
.division-media.is-product img {
  object-fit: cover;
  object-position: center;
  background: #fff;
}

.division-media.is-product::after { opacity: 0; }

/* The water list runs to twenty-two products, so the photo follows the reader
   rather than scrolling away at the top and leaving the column empty. The
   grid's align-items:start already lets the item be shorter than its row,
   which is what sticky needs here. Only above the point where the grid is
   still two columns — below that the photo sits above the list anyway. */
@media (min-width: 993px) {
  .division-media {
    position: sticky;
    top: calc(var(--header-height) + 24px);
  }
}

@media (max-width: 992px) {
  .tab-content.active { grid-template-columns: 1fr; }
  .division-media { height: 320px; }
}

/* ==========================================================================
   Interactive Product Catalog & RFQ Builder
   ========================================================================== */
.materials {
  padding: 60px 0;
  background: var(--bg-primary);
}

.catalog-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
  margin-top: 48px;
}

.catalog-card {
  background: var(--bg-card);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
  padding: 26px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  transition: all var(--transition-normal);
}

.catalog-card:hover {
  transform: translateY(-5px);
  background: var(--bg-card);
  border-color: var(--border-active);
  box-shadow: var(--shadow-md);
}

.catalog-category {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--brand-blue);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: 8px;
}

.catalog-item-name {
  font-size: 1.2rem;
  margin-bottom: 12px;
}

.catalog-specs {
  font-size: 0.88rem;
  color: var(--text-secondary);
  margin-bottom: 20px;
}

.catalog-specs li {
  margin-bottom: 6px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.catalog-specs li i {
  color: var(--brand-blue);
  font-size: 0.8rem;
}

/* ==========================================================================
   Major Clients & Strategic Partners (Official Corporate Logo Grid)
   ========================================================================== */
.clients {
  padding: 60px 0;
  background: var(--bg-secondary);
}

/* The client wall follows the vendor-approvals treatment on the catalogue
   page: one continuous plate divided by hairlines rather than sixteen
   floating cards. Column counts stay divisors of 16 so no row is left with
   a single stranded logo (auto-fill gave 5+5+5+1 on a wide screen). */
.clients-portfolio-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--border-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

@media (min-width: 700px) {
  .clients-portfolio-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.client-card-item {
  background: var(--bg-card);
  padding: 22px 16px 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
  transition: background-color var(--transition-fast);
}

.client-card-item:hover { background: rgba(30, 111, 196, 0.05); }

/* Every supplied logo is a mark with white baked in, so the plate stays white
   in both themes — a dark surface would swallow the dark ink. */
.client-logo-box {
  width: 100%;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  border-radius: 8px;
  padding: 6px 10px;
}

.client-logo-box img,
.client-logo-box svg {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}

/* Most names sit on one line; the longest wrap to two and the row grows with
   them, so every logo plate in a row still starts at the same height. */
.client-name {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.84rem;
  line-height: 1.35;
  color: var(--text-primary);
}

/* ==========================================================================
   Fabric product search
   --------------------------------------------------------------------------
   Seven dropdowns over a twelve-row table. The table is wide by nature, so it
   scrolls inside its own box rather than pushing the page sideways.
   ========================================================================== */
.fs-filters {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 20px;
}

@media (min-width: 700px)  { .fs-filters { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .fs-filters { grid-template-columns: repeat(7, minmax(0, 1fr)); } }

.fs-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }

.fs-cap {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.fs-select {
  width: 100%;
  padding: 10px 12px;
  font-family: inherit;
  font-size: 0.88rem;
  color: var(--text-primary);
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm, 10px);
  cursor: pointer;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.fs-select:hover { border-color: var(--border-active); }
.fs-select:focus-visible {
  outline: none;
  border-color: var(--accent-color, #1e6fc4);
  box-shadow: 0 0 0 3px rgba(30, 111, 196, 0.22);
}

.fs-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.fs-count { font-size: 0.85rem; color: var(--text-secondary); }

.fs-reset {
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 8px 16px;
  color: var(--text-primary);
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: 999px;
  cursor: pointer;
  transition: border-color var(--transition-fast), color var(--transition-fast), opacity var(--transition-fast);
}

.fs-reset:hover:not(:disabled) { border-color: var(--border-active); }
.fs-reset:disabled { opacity: 0.45; cursor: default; }

/* The table is wider than a phone; it scrolls here, not the page. */
.fs-wrap {
  overflow-x: auto;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  background: var(--bg-card);
  box-shadow: var(--shadow-sm);
}

.fs-table { width: 100%; border-collapse: collapse; min-width: 900px; }

.fs-table th, .fs-table td {
  padding: 12px 14px;
  text-align: start;
  vertical-align: top;
  font-size: 0.84rem;
  line-height: 1.5;
  border-bottom: 1px solid var(--border-color);
}

.fs-head th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg-secondary, var(--bg-card));
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}

.fs-body th[scope="row"] {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--text-primary);
  white-space: nowrap;
}

.fs-body td { color: var(--text-secondary); }
.fs-body tr:last-child th, .fs-body tr:last-child td { border-bottom: 0; }
.fs-body tr:hover th, .fs-body tr:hover td { background: rgba(30, 111, 196, 0.045); }

.fs-empty { padding: 28px 16px; text-align: center; color: var(--text-muted); font-size: 0.9rem; }

/* ==========================================================================
   Catalogue download card
   ========================================================================== */
.dl-card {
  display: flex;
  align-items: center;
  gap: 14px;
  align-self: flex-start;
  max-width: 100%;
  margin-top: 16px;
  padding: 14px 18px;
  text-decoration: none;
  color: inherit;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.dl-card:hover {
  transform: translateY(-3px);
  border-color: var(--border-active);
  box-shadow: var(--shadow-md);
}

.dl-icon {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  font-size: 1.15rem;
  color: #c0392b;
  background: rgba(192, 57, 43, 0.1);
}

.dl-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.dl-title {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--text-primary);
}

.dl-meta {
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

.dl-go {
  flex: 0 0 auto;
  margin-inline-start: 8px;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  font-size: 0.8rem;
  color: var(--text-secondary);
  background: var(--bg-secondary, rgba(15, 23, 42, 0.05));
  transition: background-color var(--transition-fast), color var(--transition-fast);
}

.dl-card:hover .dl-go { background: var(--accent-color, #1e6fc4); color: #fff; }

/* ==========================================================================
   Certifications & recognition
   ========================================================================== */
.recognition {
  padding: 80px 0;
  background: var(--bg-primary);
}

.rec-docs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin-bottom: 56px;
}

/* the download card was built to sit under a button; here it fills a cell */
.rec-docs .dl-card { margin-top: 0; align-self: stretch; }
.rec-docs .dl-go { margin-inline-start: auto; }

.rec-letters-title {
  font-family: var(--font-heading);
  font-size: 1.15rem;
  margin-bottom: 20px;
  color: var(--text-primary);
}

/* Fixed column counts rather than auto-fill: there are 12 letters, and 6, 4, 3
   and 2 all divide 12, so every row is full at every width instead of leaving
   a half-empty last row. Revisit the counts if letters are added or removed. */
.rec-letters {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 18px;
}

@media (max-width: 1100px) {
  .rec-letters { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .rec-letters { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
}

.rec-letter {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px;
  text-decoration: none;
  color: inherit;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.rec-letter:hover {
  transform: translateY(-3px);
  border-color: var(--border-active);
  box-shadow: var(--shadow-md);
}

/* Letters come in both orientations. A fixed portrait frame with contain
   keeps the grid even and shows every page whole, landscape ones included. */
.rec-letter img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: contain;
  background: #fff;
  border: 1px solid var(--border-color);
  border-radius: 6px;
  margin-bottom: 8px;
}

.rec-year {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--brand-blue);
}

.rec-from {
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--text-muted);
}

@media (max-width: 600px) {
  .rec-docs { grid-template-columns: 1fr; }
}

@media (max-width: 480px) {
  .rec-letters { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
}

/* ==========================================================================
   Contact Section
   ========================================================================== */
.contact {
  padding: 60px 0;
  background: var(--bg-primary);
}

.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 60px;
}

.contact-info-list {
  display: flex;
  flex-direction: column;
  gap: 28px;
  margin-top: 32px;
}

.contact-info-item {
  display: flex;
  align-items: flex-start;
  gap: 20px;
}

.contact-icon {
  width: 48px;
  height: 48px;
  border-radius: var(--radius-md);
  background: rgba(29, 93, 183, 0.1);
  color: var(--brand-blue);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
  flex-shrink: 0;
}

.contact-details h4 {
  font-size: 1.1rem;
  margin-bottom: 4px;
}

.contact-details p {
  color: var(--text-secondary);
  font-size: 0.95rem;
}

/* Real contact details are now links — make them read as such */
.contact-details a {
  color: var(--brand-blue);
  font-weight: 600;
  border-bottom: 1px solid transparent;
  transition: border-color var(--transition-fast);
}

.contact-details a:hover {
  border-bottom-color: var(--brand-blue);
}

.contact-form-card {
  background: var(--bg-card);
  padding: 40px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-color);
  box-shadow: var(--shadow-md);
}

.form-group {
  margin-bottom: 20px;
}

.form-label {
  display: block;
  font-size: 0.9rem;
  font-weight: 600;
  margin-bottom: 8px;
  color: var(--text-primary);
}

.form-input, .form-textarea, .form-select {
  width: 100%;
  padding: 14px 18px;
  border-radius: var(--radius-sm);
  background: var(--bg-primary);
  border: 1px solid var(--border-color);
  color: var(--text-primary);
  font-family: inherit;
  font-size: 0.95rem;
  transition: border-color var(--transition-fast);
}

.form-input:focus, .form-textarea:focus, .form-select:focus {
  outline: none;
  border-color: var(--brand-blue);
  box-shadow: 0 0 0 3px rgba(29, 93, 183, 0.15);
}

@media (max-width: 992px) {
  .contact-grid { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Footer
   ========================================================================== */
.footer {
  background: var(--bg-secondary);
  border-top: 1px solid var(--border-color);
  padding: 30px 0 16px;
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1.3fr;
  gap: 32px;
  margin-bottom: 24px;
}

.footer-col p {
  color: var(--text-secondary);
  font-size: 0.92rem;
  margin-top: 16px;
  line-height: 1.6;
}

.footer-heading {
  font-size: 1.1rem;
  margin-bottom: 20px;
  color: var(--text-primary);
}

.footer-links li {
  margin-bottom: 12px;
}

.footer-links a {
  color: var(--text-secondary);
  font-size: 0.92rem;
}

.footer-links a:hover {
  color: var(--brand-blue);
}

/* Head office block ------------------------------------------------------ */
/* QR centred on top, pin + address beneath — per the supplied design */
.footer-office {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
  margin-top: 16px;
}

/* The three office columns stretch to the tallest one, and the address takes
   up the slack, so the QR codes, emails and phone numbers sit on the same
   lines across all three however long each address runs. */
.footer-col.is-office {
  display: flex;
  flex-direction: column;
}
.footer-col.is-office .footer-office { flex: 1 1 auto; }
.footer-col.is-office .footer-address { flex: 1 1 auto; }

/* Everything under this heading — the QR plate, the address, the phone — is
   already centred on the column. The heading itself was the one piece still
   sitting hard against the left edge, so it is brought into line here rather
   than by centring every footer heading, which would unpick the three link
   columns beside it. */
.footer-col.is-office .footer-heading { text-align: center; }

/* Three offices across, below the link columns rather than inside them: as a
   fifth column the addresses wrapped to one or two words a line. */
.footer-offices {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 32px;
  margin-bottom: 24px;
  padding-top: 28px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

/* The legal entity sits above the street, and reads as a name rather than as
   the first line of the address. */
.footer-office-org {
  font-weight: 600;
  color: var(--text-primary);
}

@media (max-width: 860px) {
  .footer-offices { grid-template-columns: 1fr; gap: 36px; }
}

/* White plate keeps the dark-green QR scannable on the navy footer */
.footer-qr {
  /* 168px, not 132: these encode a whole contact card, so the symbol has more
     and therefore smaller modules. Below about 2.5px per module a phone
     camera stops resolving them, and the code silently fails to scan. */
  width: 168px;
  height: auto;          /* artwork is 520x508 — let it keep its ratio */
  flex-shrink: 0;
  background: #ffffff;
  padding: 6px;
  border-radius: 8px;
}

.footer-address {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--text-secondary);
  max-width: 30ch;
  /* an address is a label, not a paragraph: centred, never justified */
  text-align: center;
  text-align-last: auto;
}

.footer-address i {
  color: var(--brand-blue);
  font-size: 1rem;
}

.footer-office-phone {
  display: inline-block;
  margin-top: 2px;
  color: var(--brand-blue);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.84rem;
  letter-spacing: 2px;
  white-space: nowrap;
}

.footer-office-phone:hover { text-decoration: underline; }

@media (max-width: 992px) {
  .footer-qr { width: 140px; }
}

.footer-bottom {
  padding-top: 30px;
  border-top: 1px solid var(--border-color);
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 0.88rem;
  color: var(--text-muted);
}

/* The studio credit sits with the copyright and the ISO line. Its link is the
   only one in this bar, so it carries its own colour rather than inheriting
   the muted grey the rest of the row uses. */
.footer-credit a {
  color: var(--brand-blue);
  font-weight: 600;
  text-decoration: none;
  transition: color var(--transition-fast);
}

.footer-credit a:hover {
  color: var(--accent-gold);
  text-decoration: underline;
}

@media (max-width: 992px) {
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 576px) {
  .footer-grid { grid-template-columns: 1fr; }
  .footer-bottom { flex-direction: column; gap: 12px; text-align: center; }
}

/* ==========================================================================
   RFQ Modal Drawer
   ========================================================================== */
/* ==========================================================================
   MODERN MOTION SYSTEM & AMBIENT GRAPHICS
   Scroll transitions · split-text reveals · parallax · ambient canvas
   ========================================================================== */

/* Anchor jumps should clear the fixed header */
html {
  scroll-padding-top: calc(var(--header-height) + 24px);
}

/* Keep real content above the decorative pattern layers */
.container {
  position: relative;
  z-index: 1;
}

/* --------------------------------------------------------------------------
   1. Scroll progress indicator
   -------------------------------------------------------------------------- */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  z-index: 1400;
  pointer-events: none;
}

.scroll-progress-bar {
  height: 100%;
  width: 0;
  border-radius: 0 4px 4px 0;
  background: linear-gradient(90deg, var(--brand-blue), #38bdf8 50%, var(--accent-gold));
  box-shadow: 0 0 14px rgba(29, 93, 183, 0.65);
}

/* --------------------------------------------------------------------------
   2. Split-text word reveal (headings rise word-by-word on scroll)
   -------------------------------------------------------------------------- */
.sw {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}

.sw-i {
  display: inline-block;
  opacity: 0;
  transform: translateY(110%) rotate(4deg);
  transition: transform 0.95s cubic-bezier(0.16, 1, 0.3, 1),
              opacity 0.75s cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform, opacity;
}

.split-ready.in .sw-i {
  opacity: 1;
  transform: translateY(0) rotate(0);
}

/* --------------------------------------------------------------------------
   3. Extra scroll-reveal variants
   -------------------------------------------------------------------------- */
.reveal-scale {
  opacity: 0;
  transform: scale(0.93) translateY(30px);
  transition: opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1),
              transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}

.reveal-blur {
  opacity: 0;
  filter: blur(14px);
  transform: translateY(26px);
  transition: opacity 0.9s ease, filter 0.9s ease,
              transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}

.reveal-scale.active,
.reveal-blur.active {
  opacity: 1;
  filter: blur(0);
  transform: none;
}

/* Staggered children — per-item delay set by app.js as --stagger-delay.

   Driven by an animation rather than a transition, and moved with the
   independent `translate`/`scale` properties rather than `transform`. Both
   details matter: a `transition` shorthand here would replace each child's own
   transition (killing button and card hover easing), and writing `transform`
   would out-rank the hover and 3D-tilt transforms. `translate` composes with
   `transform` instead of competing with it, so the entrance replays every time
   the group scrolls into view without ever disturbing hover behaviour. */
.stagger > * {
  opacity: 0;
}

.stagger.in > * {
  animation: staggerIn 0.75s cubic-bezier(0.16, 1, 0.3, 1) both;
  animation-delay: var(--stagger-delay, 0s);
}

@keyframes staggerIn {
  from { opacity: 0; translate: 0 36px; scale: 0.97; }
  to   { opacity: 1; translate: 0 0;    scale: 1; }
}

/* --------------------------------------------------------------------------
   4. Hero ambient graphics
   -------------------------------------------------------------------------- */
.hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  opacity: 0.6;
  pointer-events: none;
}

/* Drifting blueprint grid */
.hero-grid-overlay {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(29, 93, 183, 0.09) 1px, transparent 1px),
    linear-gradient(90deg, rgba(29, 93, 183, 0.09) 1px, transparent 1px);
  background-size: 58px 58px;
  mask-image: radial-gradient(ellipse 85% 65% at 45% 45%, #000 10%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 85% 65% at 45% 45%, #000 10%, transparent 78%);
  animation: gridDrift 26s linear infinite;
}

@keyframes gridDrift {
  to { background-position: 58px 58px, 58px 58px; }
}

/* Soft floating colour orbs */
.orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(72px);
  pointer-events: none;
  z-index: 0;
}

.orb-1 {
  width: 440px;
  height: 440px;
  top: -110px;
  right: 4%;
  background: radial-gradient(circle, rgba(29, 93, 183, 0.5), transparent 70%);
  animation: orbFloat 19s ease-in-out infinite;
}

.orb-2 {
  width: 360px;
  height: 360px;
  bottom: -80px;
  left: -60px;
  background: radial-gradient(circle, rgba(217, 119, 6, 0.42), transparent 70%);
  animation: orbFloat 24s ease-in-out infinite reverse;
}

.orb-3 {
  width: 300px;
  height: 300px;
  top: 42%;
  right: 34%;
  background: radial-gradient(circle, rgba(5, 150, 105, 0.3), transparent 70%);
  animation: orbFloat 30s ease-in-out infinite;
}

@keyframes orbFloat {
  0%, 100% { transform: translate(0, 0) scale(1); }
  33%      { transform: translate(38px, -30px) scale(1.09); }
  66%      { transform: translate(-26px, 26px) scale(0.94); }
}

/* Rotating blueprint schematic */
/* --------------------------------------------------------------------------
   Regional distribution map
   Al-Khobar is the hub; thin lines reach the domestic yards, thick flowing
   lines are the export routes. Geometry lives in index.html.
   -------------------------------------------------------------------------- */
.hero-map {
  position: absolute;
  top: 11%;
  /* align the map to the content column, not the viewport edge, so it does
     not drift far right on an ultrawide display */
  right: max(2%, calc((100vw - var(--content-max)) / 2));
  width: 360px;
  height: 300px;
  z-index: 1;
  opacity: 0.9;
  pointer-events: none;
}

.hero-map svg { width: 100%; height: 100%; overflow: hidden; }

.map-grid path {
  stroke: var(--brand-blue);
  stroke-width: 0.6;
  opacity: 0.16;
}

/* The country itself */
.map-ksa {
  fill: rgba(29, 93, 183, 0.13);
  stroke: var(--brand-blue);
  stroke-width: 1.4;
  stroke-linejoin: round;
  stroke-linecap: round;
  opacity: 0.95;
}

/* Neighbouring states: outline only, so Saudi Arabia stays the subject */
.map-neighbours {
  fill: rgba(29, 93, 183, 0.03);
  stroke: var(--brand-blue);
  stroke-width: 0.8;
  stroke-linejoin: round;
  opacity: 0.32;
}

/* Domestic yard links — quieter than the export routes */
.map-route-local path {
  fill: none;
  stroke: var(--brand-blue);
  stroke-width: 1;
  stroke-dasharray: 3 5;
  opacity: 0.45;
  animation: routeFlow 3.4s linear infinite;
}

.map-node-local circle {
  fill: var(--brand-blue);
  opacity: 0.55;
}

/* Export routes — the moving delivery lines */
.map-route {
  fill: none;
  stroke: var(--accent-gold);
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-dasharray: 7 9;
  animation: routeFlow 1.9s linear infinite;
}

.map-route.r2 { animation-delay: 0.25s; }
.map-route.r3 { animation-delay: 0.5s;  }
.map-route.r4 { animation-delay: 0.75s; }
.map-route.r5 { animation-delay: 1s;    }
.map-route.r6 { animation-delay: 1.25s; }
.map-route.r7 { animation-delay: 1.5s;  }

/* One dash + gap = 16 units, so this loops seamlessly */
@keyframes routeFlow {
  to { stroke-dashoffset: -16; }
}

.map-node {
  fill: var(--accent-gold);
  stroke: var(--bg-secondary);
  stroke-width: 1.6;
  animation: nodePulse 2.8s ease-in-out infinite;
}

.map-dests circle:nth-child(2) { animation-delay: 0.4s; }
.map-dests circle:nth-child(3) { animation-delay: 0.8s; }
.map-dests circle:nth-child(4) { animation-delay: 1.2s; }
.map-dests circle:nth-child(5) { animation-delay: 1.6s; }
.map-dests circle:nth-child(6) { animation-delay: 2s; }
.map-dests circle:nth-child(7) { animation-delay: 2.4s; }

@keyframes nodePulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}

/* Hub with dispatch rings expanding out of Al-Khobar */
.map-hub {
  fill: var(--brand-blue);
  stroke: var(--bg-secondary);
  stroke-width: 2;
}

.map-hub-ring {
  fill: none;
  stroke: var(--brand-blue);
  stroke-width: 1.6;
  transform-origin: 243.7px 132.6px;
  animation: hubPing 3s ease-out infinite;
}

.map-hub-ring.ring-2 { animation-delay: 1.5s; }

@keyframes hubPing {
  0%   { transform: scale(0.5); opacity: 0.8; }
  100% { transform: scale(2.6); opacity: 0; }
}

.map-label {
  font-family: var(--font-heading);
  font-size: 11px;
  font-weight: 700;
  fill: var(--text-secondary);
  letter-spacing: 0.4px;
}

.map-label-hub {
  fill: var(--brand-blue);
  font-size: 11.5px;
  font-weight: 800;
}

.map-label-ksa {
  fill: var(--brand-blue);
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 1.6px;
  opacity: 0.55;
}

/* Arabic needs no tracking and a slightly larger size to stay legible */
html[lang="ar"] .map-label { letter-spacing: 0; font-size: 12px; }
html[lang="ar"] .map-label-ksa { letter-spacing: 0; font-size: 10.5px; }

@media (max-width: 1200px) {
  .hero-map { display: none; }
}

/* Wave transition from hero into the next section */
.hero-wave {
  position: absolute;
  bottom: -1px;
  left: 0;
  width: 100%;
  line-height: 0;
  z-index: 3;
  pointer-events: none;
}

.hero-wave svg {
  width: 100%;
  height: 90px;
  display: block;
}

.hero-wave path {
  fill: var(--bg-secondary);
}

/* Hero sizing.
   The hero centres its content inside min-height, so any height left over
   after the content lands as empty space split above and below it — on top of
   the bottom padding and the wave. At 90vh that produced a visible dead band
   under the stats bar. Sizing closer to the content removes the gap while
   still filling the fold on normal screens. */
.hero {
  min-height: min(82vh, 900px);   /* the vh alone leaves a gap on tall monitors */
  padding-bottom: 96px;           /* must clear the wave below */
}

.hero-wave svg { height: 72px; }

@media (max-width: 768px) {
  .hero-wave svg { height: 46px; }
  .hero {
    min-height: 0;        /* let the content decide on phones */
    padding-bottom: 62px;
  }
}

/* --------------------------------------------------------------------------
   5. Section pattern layers
   -------------------------------------------------------------------------- */
.divisions,
.materials,
.clients,
.contact {
  position: relative;
  overflow: hidden;
}

.materials::before,
.contact::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: radial-gradient(circle, rgba(29, 93, 183, 0.16) 1.2px, transparent 1.2px);
  background-size: 26px 26px;
  mask-image: radial-gradient(ellipse 70% 70% at 50% 50%, #000, transparent 72%);
  -webkit-mask-image: radial-gradient(ellipse 70% 70% at 50% 50%, #000, transparent 72%);
  opacity: 0.7;
}

.divisions::before,
.clients::before {
  content: '';
  position: absolute;
  top: -140px;
  left: 50%;
  width: 720px;
  height: 380px;
  transform: translateX(-50%);
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(29, 93, 183, 0.14), transparent 68%);
  filter: blur(20px);
}

/* --------------------------------------------------------------------------
   7. Pointer-tracked 3D tilt + light sheen on cards
   -------------------------------------------------------------------------- */
.card-tilt {
  position: relative;
  will-change: transform;
}

.card-tilt::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.35s ease;
  background: radial-gradient(circle at var(--gx, 50%) var(--gy, 50%),
              rgba(29, 93, 183, 0.16), transparent 62%);
}

.card-tilt:hover::before { opacity: 1; }

.catalog-card { position: relative; }

/* --------------------------------------------------------------------------
   8. Partner logo marquee
   -------------------------------------------------------------------------- */
.logo-marquee {
  position: relative;
  overflow: hidden;
  margin-top: 48px;
  padding: 22px 0;
  border-top: 1px solid var(--border-color);
  border-bottom: 1px solid var(--border-color);
  background: linear-gradient(90deg,
    rgba(29, 93, 183, 0.04), transparent 30%, transparent 70%, rgba(217, 119, 6, 0.04));
  mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}

.logo-marquee-track {
  display: flex;
  align-items: center;
  width: max-content;
  /* 2s per logo (34 logos): scale this with the list in app.js so adding
     logos lengthens the loop instead of speeding the strip up */
  animation: marqueeScroll 68s linear infinite;
}

/* Trailing padding equals the gap, so each group tiles perfectly */
.marquee-group {
  display: flex;
  align-items: center;
  gap: 46px;
  padding-right: 46px;
}

/* Manufacturer logo slot. Every supplied file has white baked in, so the slot
   is a white plate — the strip has no plate of its own. 64px rather than the
   old 48 because several marks are square and were reading tiny. */
.marquee-logo {
  flex: 0 0 auto;
  width: 170px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px 12px;
  background: #ffffff;
  border-radius: 6px;
  filter: grayscale(1);
  opacity: 0.62;
  transition: filter var(--transition-fast), opacity var(--transition-fast), transform var(--transition-fast);
}

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

.marquee-logo:hover {
  filter: grayscale(0);
  opacity: 1;
  transform: scale(1.06);
}
.marquee-caption {
  text-align: center;
  margin: 34px 0 14px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.logo-marquee:hover .logo-marquee-track {
  animation-play-state: paused;
}

@keyframes marqueeScroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* --------------------------------------------------------------------------
   9. Micro-interactions
   -------------------------------------------------------------------------- */
.btn {
  position: relative;
  overflow: hidden;
}

/* Sweeping shine across primary buttons */
.btn-primary::after {
  content: '';
  position: absolute;
  top: 0;
  left: -140%;
  width: 55%;
  height: 100%;
  transform: skewX(-22deg);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.38), transparent);
  transition: left 0.75s cubic-bezier(0.16, 1, 0.3, 1);
}

.btn-primary:hover::after { left: 145%; }

/* Section tags get a soft breathing glow */
.section-tag {
  position: relative;
  overflow: hidden;
}

.section-tag::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(29, 93, 183, 0.22), transparent);
  transform: translateX(-100%);
  animation: tagSweep 4.5s ease-in-out infinite;
}

@keyframes tagSweep {
  0%, 60% { transform: translateX(-100%); }
  100%    { transform: translateX(100%); }
}

/* Counter digits keep a stable width while animating */
.stat-number {
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------------------
   10. Dark theme refinements
   Assets with baked-in dark ink (the company logo, partner logo SVGs) need a
   light plate to stay legible — the same treatment the footer logo already had.
   -------------------------------------------------------------------------- */
/* The wordmark is a gradient running from rgb(0,0,88) to white. On a dark
   surface the navy end drops to ~1:1 contrast and simply disappears, and no
   amount of brightness() rescues it. brightness(0) flattens every pixel to
   black while keeping the alpha channel, then invert(1) flips that to white —
   giving a clean mono silhouette with the letterforms and anti-aliasing intact. */
[data-theme="dark"] .official-logo {
  filter: brightness(0) invert(1);
}

/* Cells read as panes of one grid now, so only the hover tint needs lifting. */
[data-theme="dark"] .client-card-item:hover {
  background: rgba(56, 189, 248, 0.08);
}

/* The blueprint grid and dot patterns are tuned for light surfaces */
[data-theme="dark"] .hero-grid-overlay {
  background-image:
    linear-gradient(rgba(56, 189, 248, 0.09) 1px, transparent 1px),
    linear-gradient(90deg, rgba(56, 189, 248, 0.09) 1px, transparent 1px);
}

[data-theme="dark"] .materials::before,
[data-theme="dark"] .contact::before {
  background-image: radial-gradient(circle, rgba(56, 189, 248, 0.18) 1.2px, transparent 1.2px);
}

[data-theme="dark"] .card-tilt::before {
  background: radial-gradient(circle at var(--gx, 50%) var(--gy, 50%),
              rgba(56, 189, 248, 0.14), transparent 62%);
}

/* --------------------------------------------------------------------------
   10b. Facilities gallery & photo lightbox
   -------------------------------------------------------------------------- */
.facilities {
  padding: 60px 0;
  background: var(--bg-primary);
  position: relative;
  overflow: hidden;
}

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 210px;
  grid-auto-flow: dense;
  gap: 18px;
  margin-top: 40px;
}

.gallery-item {
  position: relative;
  display: block;
  padding: 0;
  overflow: hidden;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
  box-shadow: var(--shadow-sm);
  background: var(--bg-tertiary);
  cursor: zoom-in;
  transition: transform var(--transition-normal), box-shadow var(--transition-normal),
              border-color var(--transition-normal);
}

.gallery-item.wide { grid-column: span 2; grid-row: span 2; }
.gallery-item.tall { grid-row: span 2; }

.gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}

.gallery-item:hover {
  transform: translateY(-5px);
  border-color: var(--border-active);
  box-shadow: var(--shadow-lg);
}

.gallery-item:focus-visible {
  outline: 3px solid var(--brand-blue);
  outline-offset: 3px;
}

.gallery-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  padding: 20px;
  text-align: start;
  background: linear-gradient(to top,
    rgba(6, 16, 34, 0.92) 0%,
    rgba(6, 16, 34, 0.55) 38%,
    rgba(6, 16, 34, 0) 72%);
  opacity: 0.92;
  transition: opacity var(--transition-normal);
}

.gallery-item:hover .gallery-overlay { opacity: 1; }

.gallery-caption { display: block; }

.gallery-caption-title {
  display: block;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.05rem;
  color: #ffffff;
  line-height: 1.3;
  margin-bottom: 4px;
}

.gallery-caption-desc {
  display: block;
  font-size: 0.84rem;
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.82);
  max-width: 46ch;
}

.gallery-zoom {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.16);
  backdrop-filter: blur(6px);
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.9rem;
  transition: background var(--transition-fast), transform var(--transition-bounce);
}

.gallery-item:hover .gallery-zoom {
  background: var(--brand-blue);
  transform: scale(1.1);
}

@media (max-width: 992px) {
  .gallery-grid { grid-template-columns: repeat(2, 1fr); }
  /* Full-width feature tile would leave an odd cell empty — even it out */
  .gallery-item.wide { grid-column: span 1; grid-row: span 1; }
}

@media (max-width: 576px) {
  .gallery-grid { grid-template-columns: 1fr; grid-auto-rows: 220px; }
  .gallery-item.wide, .gallery-item.tall { grid-column: span 1; grid-row: span 1; }
  .gallery-caption-desc { display: none; }
}

/* --- Lightbox --- */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 2500;
  display: none;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 32px 20px;
  background: rgba(6, 16, 34, 0.93);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.lightbox.active {
  display: flex;
  animation: fadeIn 0.25s ease;
}

.lightbox-figure {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  max-width: min(1100px, 92vw);
  max-height: 88vh;
}

.lightbox-figure img {
  max-width: 100%;
  max-height: 72vh;
  width: auto;
  border-radius: var(--radius-md);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55);
  object-fit: contain;
}

.lightbox-caption {
  text-align: center;
  max-width: 60ch;
}

.lightbox-caption h4 {
  font-size: 1.2rem;
  color: #ffffff;
  margin-bottom: 6px;
}

.lightbox-caption p {
  font-size: 0.92rem;
  color: rgba(255, 255, 255, 0.75);
  line-height: 1.6;
}

.lightbox-nav,
.lightbox-close {
  flex-shrink: 0;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-full);
  background: rgba(255, 255, 255, 0.12);
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  transition: background var(--transition-fast), transform var(--transition-fast);
}

.lightbox-nav:hover,
.lightbox-close:hover {
  background: var(--brand-blue);
  transform: scale(1.08);
}

.lightbox-close {
  position: absolute;
  top: 24px;
  inset-inline-end: 24px;
}

@media (max-width: 768px) {
  .lightbox { padding: 16px 8px; gap: 4px; }
  .lightbox-nav, .lightbox-close { width: 40px; height: 40px; font-size: 0.95rem; }
  .lightbox-figure { max-width: 100%; }
  .lightbox-figure img { max-height: 70vh; }
  /* The arrows float over the picture's edges instead of taking width beside
     it, so a letter gets the whole screen width on a phone. */
  .lightbox-nav {
    position: absolute;
    top: 50%;
    margin-top: -20px;
    z-index: 1;
    background: rgba(6, 16, 34, 0.7);
  }
  .lightbox-prev { inset-inline-start: 10px; }
  .lightbox-next { inset-inline-end: 10px; }
}

/* --- Illustrated stand-in panels (divisions with no photo yet) --- */
.division-illustration {
  background: var(--bg-tertiary);
  display: block;
}

.division-illustration svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* --------------------------------------------------------------------------
   10c. Photographic treatments
   -------------------------------------------------------------------------- */

/* Hero photo drifts in a slow Ken Burns push */
.hero-bg {
  animation: kenBurns 34s ease-in-out infinite alternate;
  transform-origin: 70% 40%;
}

@keyframes kenBurns {
  from { scale: 1;    filter: saturate(1);    }
  to   { scale: 1.14; filter: saturate(1.18); }
}

/* Photo frames wipe open as they scroll in.
   The clipped state is applied by app.js (which adds .will-wipe), never by
   default. A frame clipped to inset(... 100% ...) is completely invisible while
   still occupying its full height, so if this were the CSS default any JS
   failure would leave a photo-sized hole in the page. Opting in from script
   guarantees the photos are visible whenever the effect can't run. */
/* The clip goes on the CHILDREN, never on the observed frame itself.
   An element clipped to zero height reports no intersection, so the very
   IntersectionObserver that would remove the clip never fires and the photo
   stays hidden forever — that deadlock is what left a blank band where the
   About photo should be. Clipping the children keeps the frame measurable. */
.will-wipe > * {
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.1s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Media inside inactive tabs stays clipped and is opened by the tab handler,
   so switching tabs plays the wipe rather than flickering closed-then-open. */
.will-wipe.shown > * {
  clip-path: inset(0 0 0 0);
}

/* Slow inner drift, driven by app.js — gives the frames depth on scroll */
.about-image-wrapper img,
.division-media img {
  will-change: transform;
}

/* Framed photos carry a subtle brand wash that clears on hover */
.about-image-wrapper::after,
.division-media::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background: linear-gradient(140deg,
    rgba(29, 93, 183, 0.28) 0%,
    rgba(29, 93, 183, 0.04) 45%,
    rgba(217, 119, 6, 0.16) 100%);
  mix-blend-mode: multiply;
  opacity: 0.75;
  transition: opacity 0.6s ease;
}

.about-image-wrapper:hover::after { opacity: 0; }

/* Gallery photos start desaturated and bloom on hover */
.gallery-item img {
  filter: saturate(0.55) contrast(1.05);
  transition: transform 0.8s cubic-bezier(0.16, 1, 0.3, 1), filter 0.6s ease;
}

.gallery-item:hover img { filter: saturate(1.12) contrast(1.02); }

/* Cursor spotlight that follows the pointer across the hero */
.hero-spotlight {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
  background: radial-gradient(320px circle at var(--sx, 50%) var(--sy, 50%),
              rgba(56, 189, 248, 0.16), transparent 70%);
}

.hero:hover .hero-spotlight { opacity: 1; }

/* Fine grain, keeps large flat areas from banding */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.32;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   10e. Text effects
   -------------------------------------------------------------------------- */

/* Words now blur in as well as rise */
.sw-i { filter: blur(6px); transition-property: transform, opacity, filter; }
.split-ready.in .sw-i { filter: blur(0); }

/* Gradient rule draws itself under each section title as it reveals */
.section-title {
  position: relative;
  padding-bottom: 14px;
}

.section-title::after {
  content: '';
  position: absolute;
  bottom: 0;
  inset-inline-start: 0;
  height: 3px;
  width: 0;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--brand-blue), #38bdf8 55%, var(--accent-gold));
  transition: width 1.1s cubic-bezier(0.16, 1, 0.3, 1) 0.35s;
}

.section-title.in::after { width: 82px; }

/* Centred headers get a centred rule */
.section-header .section-title::after {
  inset-inline-start: 50%;
  transform: translateX(-50%);
}

/* Oversized section index sitting behind the header */
.section-index {
  position: absolute;
  top: 50%;
  inset-inline-start: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: clamp(6rem, 15vw, 12rem);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--text-primary);
  opacity: 0.035;
  pointer-events: none;
  user-select: none;
  z-index: 0;
  white-space: nowrap;
}

.section-header {
  position: relative;
  z-index: 1;
}

.section-header > *:not(.section-index) { position: relative; z-index: 1; }

/* --------------------------------------------------------------------------
   10f. Back-to-top with scroll progress ring
   -------------------------------------------------------------------------- */
.to-top {
  position: fixed;
  bottom: 28px;
  inset-inline-end: 28px;
  width: 52px;
  height: 52px;
  z-index: 1300;
  display: grid;
  place-items: center;
  border-radius: var(--radius-full);
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  box-shadow: var(--shadow-md);
  color: var(--brand-blue);
  font-size: 1rem;
  opacity: 0;
  visibility: hidden;
  transform: translateY(16px) scale(0.86);
  transition: opacity 0.4s ease, transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1),
              visibility 0.4s, background 0.25s;
}

.to-top.visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
}

.to-top:hover {
  background: var(--brand-blue);
  color: #ffffff;
}

.to-top svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
  pointer-events: none;
}

/* cx/cy/r are set as SVG attributes for wider browser support */
.to-top circle {
  fill: none;
  stroke-width: 2.5;
}

.to-top .ring-track { stroke: var(--border-color); }

.to-top .ring-fill {
  stroke: var(--brand-blue);
  stroke-linecap: round;
  stroke-dasharray: 151;
  stroke-dashoffset: 151;
  transition: stroke-dashoffset 0.1s linear;
}

.to-top i { position: relative; z-index: 1; }

@media (max-width: 576px) {
  .to-top { width: 46px; height: 46px; bottom: 20px; inset-inline-end: 20px; }
}

/* --------------------------------------------------------------------------
   11. Language toggle button
   -------------------------------------------------------------------------- */
.lang-toggle-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 42px;
  padding: 0 16px;
  border-radius: var(--radius-full);
  background: var(--bg-tertiary);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  font-size: 0.88rem;
  font-weight: 700;
  white-space: nowrap;
  transition: all var(--transition-fast);
}

.lang-toggle-btn i {
  color: var(--brand-blue);
  font-size: 1rem;
}

.lang-toggle-btn:hover {
  background: rgba(29, 93, 183, 0.15);
  color: var(--brand-blue);
  border-color: var(--border-active);
}

@media (max-width: 480px) {
  .lang-toggle-btn span { display: none; }
  .lang-toggle-btn { padding: 0 12px; }
}

/* Arabic temporarily hidden while the client revises the translation.
   Delete this rule (and set ARABIC_ENABLED = true in i18n.js) to restore. */
.lang-toggle-btn { display: none !important; }

/* --------------------------------------------------------------------------
   12. Arabic / RTL support
   -------------------------------------------------------------------------- */

/* Cairo carries the full Arabic set; Outfit and Inter have no Arabic glyphs */
html[lang="ar"] {
  --font-heading: 'Cairo', 'Outfit', sans-serif;
  --font-body: 'Cairo', 'Inter', sans-serif;
}

/* Letter-spacing breaks Arabic's connected letterforms */
html[lang="ar"] .section-tag,
html[lang="ar"] .section-title,
html[lang="ar"] .hero-title,
html[lang="ar"] .catalog-category,
html[lang="ar"] .timeline-year {
  letter-spacing: 0;
}

html[lang="ar"] .hero-title { line-height: 1.35; }
html[lang="ar"] .section-title { line-height: 1.4; }

/* --- Mirrored absolute positioning --- */
[dir="rtl"] .hero-bg {
  right: auto;
  left: 0;
  mask-image: linear-gradient(to right, rgba(0,0,0,1) 40%, rgba(0,0,0,0) 100%);
  -webkit-mask-image: linear-gradient(to right, rgba(0,0,0,1) 40%, rgba(0,0,0,0) 100%);
}

[dir="rtl"] .hero-map { right: auto; left: 2%; }
[dir="rtl"] .orb-1 { right: auto; left: 4%; }
[dir="rtl"] .orb-2 { left: auto; right: -60px; }
[dir="rtl"] .orb-3 { right: auto; left: 34%; }

[dir="rtl"] .about-experience-badge { left: auto; right: 24px; }

/* Mobile drawer slides in from the left */
@media (max-width: 992px) {
  [dir="rtl"] .nav-links {
    right: auto;
    left: -100%;
    border-left: none;
    border-right: 1px solid var(--border-color);
  }
  [dir="rtl"] .nav-links.open { left: 0; }
}

/* The timeline grid and logo ticker stay LTR on purpose. Flipping the writing
   direction would run the milestones 1970-to-today right to left across each
   grid row, and it inverts the marquee translate. The card TEXT is still RTL —
   only the chronological left-to-right flow is preserved. */
[dir="rtl"] .timeline-grid-track,
[dir="rtl"] .logo-marquee-track {
  direction: ltr;
}

[dir="rtl"] .timeline-node-card {
  direction: rtl;
  text-align: right;
}

/* Marquee group padding must flip or the seamless loop drifts */
[dir="rtl"] .marquee-group {
  padding-right: 46px;
  padding-left: 0;
}

/* Partner logos are Latin brand marks drawn at fixed SVG coordinates with the
   default text-anchor:start. SVG <text> inherits CSS `direction`, and under RTL
   "start" flips to the right edge — every label then runs leftward across its
   own icon. Pin the marks to LTR so they render identically in both languages.
   (Arabic runs inside a mark, such as Aramco's subtitle, still shape correctly
   via the bidi algorithm.) */
[dir="rtl"] .client-logo-box svg,
[dir="rtl"] .client-logo-box svg text {
  direction: ltr;
}

/* --------------------------------------------------------------------------
   12b. Mobile refinements
   The base stylesheet only breaks at 992px and 576px, which left several
   two-column grids and the header action row cramped on phones.
   -------------------------------------------------------------------------- */

@media (max-width: 860px) {
  /* Four action buttons plus the logo overflow a phone header. Collapse the
     RFQ button to its icon and keep the badge. */
  .nav-actions { gap: 10px; }

  .lang-toggle-btn {
    padding: 0 12px;
    font-size: 0.82rem;
  }
}

@media (max-width: 768px) {
  :root { --header-height: 76px; }

  .official-logo { height: 26px; }
  .header.scrolled .official-logo { height: 23px; }

  /* Both of these stayed two-up all the way down, squeezing cards to ~150px */
  .about-highlights { grid-template-columns: 1fr; gap: 16px; }
  .product-list-grid { grid-template-columns: 1fr; gap: 12px; margin-bottom: 24px; }

  .about-grid { gap: 36px; }
  .contact-grid { gap: 36px; }
  .contact-form-card { padding: 26px 22px; }

  .division-tabs { gap: 8px; }
  .tab-btn { padding: 10px 18px; font-size: 0.88rem; }

  .section-title { font-size: 1.9rem; }
  .section-subtitle { font-size: 1rem; }
  .hero-description { font-size: 1.02rem; margin-bottom: 26px; line-height: 1.6; }


  .section-index { font-size: clamp(4.5rem, 22vw, 7rem); opacity: 0.045; }

  .about-image-wrapper img { height: 320px; min-height: 0; }
  .about-experience-badge { padding: 14px 16px; gap: 12px; bottom: 16px; }
  .exp-years { font-size: 2rem; }
  .exp-text { font-size: 0.8rem; }

}

@media (max-width: 576px) {
  .container { padding: 0 18px; }

  /* Four stacked stat cards made the hero extremely tall — keep them paired */
  .stats-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 18px;
    padding: 22px;
  }

  .stat-number { font-size: 1.9rem; }
  .stat-label { font-size: 0.78rem; }

  .hero-badge { font-size: 0.8rem; padding: 7px 14px; }
  .hero-actions { gap: 12px; }
  .hero-actions .btn { width: 100%; }
  .btn { padding: 13px 26px; font-size: 0.95rem; }

  .section-tag { font-size: 0.75rem; letter-spacing: 1px; padding: 5px 14px; }

  /* Keep the floating button clear of the toast that appears bottom-start */
  .to-top { bottom: 84px; }
}

@media (max-width: 400px) {
  .hero-title { font-size: 1.9rem; }
  .lang-toggle-btn span { display: none; }
  /* Deliberately still two columns: stacking all four made the hero ~180px
     taller, which is what pushed the content past the fold on a phone. */
  .stats-grid { gap: 14px; padding: 18px; }
  .stat-number { font-size: 1.7rem; }
  .stat-label { font-size: 0.72rem; }
}

/* --------------------------------------------------------------------------
   12c. Large displays
   The layout was capped at 1240px, so on a 27" monitor everything sat in a
   narrow band down the middle with the hero graphic stranded near the edge.
   The content column widens in two steps and the type scales with it.
   -------------------------------------------------------------------------- */

/* Six catalog cards divide evenly into three columns. auto-fit was giving
   four or five per row, leaving a ragged last row on wider screens. */
@media (min-width: 992px) {
  .catalog-grid { grid-template-columns: repeat(3, 1fr); }
}

@media (min-width: 1600px) {
  :root { --content-max: 1440px; }

  .hero-content { max-width: 780px; }
  .hero-title { font-size: 4.1rem; }
  .hero-description { font-size: 1.26rem; }
  .hero-map { width: 420px; height: 350px; }

  .section-title { font-size: 3rem; }
  .section-subtitle { font-size: 1.18rem; }

  .official-logo { height: 40px; }
  .header.scrolled .official-logo { height: 32px; }

  .about-image-wrapper img { min-height: 540px; }
  .division-media { height: 470px; }
  .gallery-grid { grid-auto-rows: 250px; }
}

@media (min-width: 1920px) {
  :root { --content-max: 1560px; }

  .hero-title { font-size: 4.5rem; }
  .hero-content { max-width: 820px; }
  .hero-map { width: 460px; height: 380px; }
  .gallery-grid { grid-auto-rows: 280px; }
}

/* --------------------------------------------------------------------------
   12d. Contact and footer are always dark
   The client wants these two sections in the navy shade in BOTH themes.
   Rather than restyling every descendant, the palette variables are simply
   re-declared on the two sections. Everything inside already reads its colour
   from these, so headings, body copy, borders, inputs, links and the form card
   all follow automatically — and stay correct if the theme is switched.
   -------------------------------------------------------------------------- */
.contact,
.footer {
  --bg-primary: #0a1526;
  --bg-secondary: #0d1b2e;
  --bg-tertiary: #16273f;
  --bg-card: rgba(255, 255, 255, 0.045);

  --text-primary: #f1f5f9;
  --text-secondary: #93a4bd;
  --text-muted: #6d81a0;

  --brand-blue: #4f8ef7;
  --brand-blue-hover: #3b7ae4;
  --accent-gold: #f5b23c;

  --border-color: rgba(255, 255, 255, 0.10);
  --border-active: rgba(79, 142, 247, 0.45);

  --shadow-sm: 0 4px 12px rgba(0, 0, 0, 0.25);
  --shadow-md: 0 10px 30px rgba(0, 0, 0, 0.35);
  --shadow-lg: 0 20px 45px rgba(0, 0, 0, 0.45);

  color: var(--text-primary);
}

.contact { background: #0d1b2e; }

/* Footer sits a shade deeper than the contact block */
.footer {
  background: #08111f;
  border-top-color: rgba(255, 255, 255, 0.08);
}

/* The dot pattern was tuned for a light surface */
.contact::before {
  background-image: radial-gradient(circle, rgba(79, 142, 247, 0.20) 1.2px, transparent 1.2px);
}

/* The footer is dark in both themes, so the mono treatment always applies */
.official-logo-footer { filter: brightness(0) invert(1); }

/* Tag and icon chips need a little more presence on navy */
.contact .section-tag {
  background: rgba(79, 142, 247, 0.14);
  border-color: rgba(79, 142, 247, 0.32);
}

.contact-icon { background: rgba(79, 142, 247, 0.14); }

/* Form panel reads as translucent glass rather than a white block */
.contact-form-card {
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.contact .form-input::placeholder,
.contact .form-textarea::placeholder {
  color: rgba(255, 255, 255, 0.38);
}

/* The native dropdown list is drawn by the OS — keep it readable */
.contact .form-select option {
  background: #ffffff;
  color: #0f172a;
}

/* --------------------------------------------------------------------------
   12e. Division detail pages (piping.html, water.html, …)
   -------------------------------------------------------------------------- */

/* Two actions per division panel on the home page */
.division-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-self: flex-start;
}

/* Banner at the top of a division page, in place of the home hero */
.page-hero {
  position: relative;
  overflow: hidden;
  padding: calc(var(--header-height) + 56px) 0 64px;
  background:
    radial-gradient(circle at 85% 15%, rgba(29, 93, 183, 0.10) 0%, transparent 48%),
    linear-gradient(180deg, var(--bg-secondary) 0%, var(--bg-primary) 100%);
}

.page-hero-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(29, 93, 183, 0.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(29, 93, 183, 0.07) 1px, transparent 1px);
  background-size: 58px 58px;
  mask-image: radial-gradient(ellipse 80% 70% at 40% 40%, #000 10%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at 40% 40%, #000 10%, transparent 78%);
}

.crumbs {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 20px;
}

.crumbs a { color: var(--text-secondary); }
.crumbs a:hover { color: var(--brand-blue); }
.crumbs-current { color: var(--brand-blue); }

.page-hero-title {
  font-family: var(--font-heading);
  font-size: 3rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin-bottom: 18px;
  max-width: 16ch;
}

.page-hero-desc {
  font-size: 1.12rem;
  color: var(--text-secondary);
  line-height: 1.7;
  max-width: 62ch;
}

/* Each division banner carries a photo of that division's work, masked away
   from the text column so contrast never depends on the image itself. The photo
   differs from the one shown immediately below in .division-media. */
.page-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: var(--hero-img);
  background-size: cover;
  background-position: center right;
  opacity: 0.4;
  -webkit-mask-image: linear-gradient(to left, #000 0%, rgba(0, 0, 0, 0.5) 40%, transparent 70%);
  mask-image: linear-gradient(to left, #000 0%, rgba(0, 0, 0, 0.5) 40%, transparent 70%);
}

/* The banner's own children must sit above the photo layer */
.page-hero > .container { position: relative; z-index: 1; }

/* Mirror the fade in Arabic, otherwise the photo lands under the text */
[dir="rtl"] .page-hero::after {
  background-position: center left;
  -webkit-mask-image: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0.5) 40%, transparent 70%);
  mask-image: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0.5) 40%, transparent 70%);
}

/* Photos read far brighter against the dark palette */
[data-theme="dark"] .page-hero::after { opacity: 0.22; }

/* Below 992px the text spans the full width, so the side fade no longer keeps
   the photo clear of it. Drop to a faint bottom-weighted wash instead —
   measured to hold small-text contrast at 4.5:1. */
@media (max-width: 992px) {
  .page-hero::after,
  [dir="rtl"] .page-hero::after {
    opacity: 0.15;
    background-position: center bottom;
    -webkit-mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0.3) 45%, transparent 85%);
    mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0.3) 45%, transparent 85%);
  }
  [data-theme="dark"] .page-hero::after { opacity: 0.1; }
}

.hero-piping   { --hero-img: url('images/stockyard-pipes-galvanized.jpg?v=20260922b'); }
.hero-water    { --hero-img: url('images/water-clarifiers-aerial.jpg?v=20260914'); }
.hero-fabrics  { --hero-img: url('images/fabric-canopy.jpg?v=20260914'); }
.hero-fire     { --hero-img: url('images/fire-sprinkler-system.jpg?v=20260914'); }

/* Rotating banner photos (app.js initHeroSlides). The wrapper takes over the
   ::after layer's fade and opacity, so each theme/width rule above still
   applies; the slides inside only crossfade. Without scripting the single
   ::after photo stays. */
.page-hero.has-slides::after { display: none; }

.page-hero-slides {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.4;
  -webkit-mask-image: linear-gradient(to left, #000 0%, rgba(0, 0, 0, 0.5) 40%, transparent 70%);
  mask-image: linear-gradient(to left, #000 0%, rgba(0, 0, 0, 0.5) 40%, transparent 70%);
}

.page-hero-slide {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center right;
  opacity: 0;
  transition: opacity 1.4s ease;
}

.page-hero-slide.is-active { opacity: 1; }

[dir="rtl"] .page-hero-slides {
  -webkit-mask-image: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0.5) 40%, transparent 70%);
  mask-image: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0.5) 40%, transparent 70%);
}
[dir="rtl"] .page-hero-slide { background-position: center left; }

[data-theme="dark"] .page-hero-slides { opacity: 0.22; }

@media (max-width: 992px) {
  .page-hero-slides,
  [dir="rtl"] .page-hero-slides {
    opacity: 0.15;
    -webkit-mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0.3) 45%, transparent 85%);
    mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0.3) 45%, transparent 85%);
  }
  .page-hero-slide,
  [dir="rtl"] .page-hero-slide { background-position: center bottom; }
  [data-theme="dark"] .page-hero-slides { opacity: 0.1; }
}

/* Chips that pick a photo are buttons; the rest stay plain divs, so style
   only the interactive form and inherit everything else from .product-chip. */
button.product-chip {
  width: 100%;
  font-family: inherit;
  font-size: 0.92rem;
  /* Buttons default to line-height:normal, which renders them shorter than the
     plain .product-chip divs used on the other division pages. */
  line-height: inherit;
  color: inherit;
  text-align: start;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

button.product-chip:hover { border-color: var(--brand-blue); }

button.product-chip:focus-visible {
  outline: 2px solid var(--brand-blue);
  outline-offset: 2px;
}

button.product-chip[aria-pressed='true'] {
  border-color: var(--brand-blue);
  box-shadow: 0 0 0 1px var(--brand-blue);
}

/* Crossfade the division photo as the selection changes. Scoped to the
   division pages so the home page tabs keep their own reveal behaviour. */
.division-media img { transition: opacity 0.26s ease; }
.division-media img.is-swapping { opacity: 0; }

/* Named contacts for a division, under the general enquiry button. Emails and
   numbers are isolated with dir="ltr" so Arabic does not reorder them. */
.division-contacts {
  align-self: stretch;
  margin-top: 24px;
  padding: 20px 22px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

.division-contacts-title {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 14px;
}

.contact-people {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  gap: 18px 26px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.contact-person {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

/* Oil & Gas Piping fields a contact per product category, so those cards
   carry a category label above the name. The other divisions have none. */
.cp-role {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brand-blue);
}

.cp-name {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--text-primary);
}

.cp-line {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 0.87rem;
  color: var(--text-secondary);
  transition: color var(--transition-fast);
  overflow-wrap: anywhere;
}

.cp-line:hover { color: var(--brand-blue); }

.cp-line i {
  color: var(--brand-blue);
  font-size: 0.85rem;
  width: 15px;
  flex-shrink: 0;
  text-align: center;
}

/* Arabic keeps the heading right-aligned but the details stay left-to-right */
[dir="rtl"] .cp-line { flex-direction: row-reverse; justify-content: flex-end; }

.division-page { padding: 60px 0 70px; background: var(--bg-secondary); }

.division-page-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: start;
}

.division-page-body { display: flex; flex-direction: column; }

/* Sibling navigation, so a visitor is never stranded on one division */
.division-siblings {
  margin-top: 60px;
  padding-top: 32px;
  border-top: 1px solid var(--border-color);
}

.division-siblings h3 {
  font-size: 1.1rem;
  margin-bottom: 18px;
  color: var(--text-secondary);
}

.division-sibling-links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
}

.division-sibling {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 20px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-color);
  background: var(--bg-card);
  box-shadow: var(--shadow-sm);
  font-weight: 700;
  font-size: 0.94rem;
  transition: border-color var(--transition-fast), transform var(--transition-fast),
              box-shadow var(--transition-fast), color var(--transition-fast);
}

.division-sibling i { color: var(--brand-blue); font-size: 0.85rem; }

.division-sibling:hover {
  transform: translateY(-3px);
  border-color: var(--border-active);
  box-shadow: var(--shadow-md);
  color: var(--brand-blue);
}

[dir="rtl"] .division-sibling i,
[dir="rtl"] .division-actions .fa-arrow-right { transform: scaleX(-1); }

@media (max-width: 992px) {
  .division-page-grid { grid-template-columns: 1fr; gap: 32px; }
  .page-hero-title { font-size: 2.3rem; max-width: none; }
}

@media (max-width: 768px) {
  .page-hero { padding: calc(var(--header-height) + 36px) 0 44px; }
  .page-hero-title { font-size: 1.95rem; }
  .page-hero-desc { font-size: 1rem; }
  .division-actions .btn { width: 100%; }
}

/* --------------------------------------------------------------------------
   12f. Engineering blocks — ".eng" scope
   Two supplied designs share this vocabulary: the "Held in stock" section on
   the home page and the piping catalogue page. Both arrived using generic
   names (.section .wrap .btn .card .chip .tag .center .mt-*) and a :root token
   block. Those collide with this stylesheet — .card and .crumb already exist,
   and --shadow-sm/--shadow-lg are used throughout — so everything is scoped
   under .eng and the tokens are declared there rather than on :root.

   Both blocks carry class="eng", so these rules are written once.
   Fonts map to the site's Outfit/Inter plus a system mono, rather than
   pulling in Space Grotesk and JetBrains Mono for two pages.
   -------------------------------------------------------------------------- */
.eng {
  --paper-0: #ffffff;
  --paper-100: #f4f7fc;
  --paper-200: #ebf1f9;
  --paper-300: #dde6f3;

  --ink-900: #0a1730;
  --ink-850: #0e1e3c;
  --navy-900: #051436;

  --azure-300: #74aeec;
  --azure-400: #3d8ad9;
  --azure-500: #1e6fc4;
  --azure-600: #1257a6;
  --azure-700: #0c4386;
  --amber-600: #a26714;

  --tx-hi: #08152c;
  --tx: #3c4d67;
  --tx-mid: #5c6e8a;
  --tx-lo: #8497b1;

  --hair: rgba(10, 35, 75, 0.10);
  --hair-str: rgba(10, 35, 75, 0.20);

  --f-display: var(--font-heading);
  --f-body: var(--font-body);
  --f-mono: ui-monospace, "Cascadia Mono", Consolas, "SF Mono", monospace;

  --t-h1: clamp(2.15rem, 1.25rem + 3.3vw, 3.8rem);
  --t-h2: clamp(1.72rem, 1.15rem + 2.1vw, 2.95rem);
  --t-h3: clamp(1.28rem, 1.02rem + 0.95vw, 1.85rem);
  --t-h4: clamp(1.06rem, 0.96rem + 0.38vw, 1.24rem);
  --t-lead: clamp(1.02rem, 0.95rem + 0.42vw, 1.28rem);
  --t-sm: 0.9rem;
  --t-xs: 0.795rem;
  --t-mono: 0.715rem;

  --e-out: cubic-bezier(0.16, 1, 0.3, 1);
  --e-in: cubic-bezier(0.22, 0.61, 0.36, 1);
  --card-shadow: 0 1px 2px rgba(10, 35, 75, 0.05), 0 1px 1px rgba(10, 35, 75, 0.03);
  --card-shadow-lg: 0 30px 60px -30px rgba(10, 35, 75, 0.34);

  font-family: var(--f-body);
  line-height: 1.68;
  color: var(--tx);
}

[data-theme="dark"] .eng {
  --paper-0: #121a26;
  --paper-100: #0b111a;
  --paper-200: #151e2b;
  --paper-300: #222e40;
  --tx-hi: #eef3fa;
  --tx: #bac7d8;
  --tx-mid: #8798ac;
  --tx-lo: #67788c;
  --hair: rgba(255, 255, 255, 0.085);
  --hair-str: rgba(255, 255, 255, 0.18);
  --azure-300: #a6cdf7;
  --azure-400: #6ba9ee;
  --azure-500: #4a92e2;
  --azure-600: #2f79cc;
  --azure-700: #8cbcf2;
  --amber-600: #e0a557;
  --card-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
  --card-shadow-lg: 0 30px 60px -28px rgba(0, 0, 0, 0.8);
}

/* ---- typography ---- */
.eng h1, .eng h2, .eng h3, .eng h4 {
  font-family: var(--f-display);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.028em;
  color: var(--tx-hi);
  margin: 0;
}
.eng h1 { font-size: var(--t-h1); }
.eng h2 { font-size: var(--t-h2); }
.eng h3 { font-size: var(--t-h3); line-height: 1.16; }
.eng h4 { font-size: var(--t-h4); line-height: 1.32; letter-spacing: -0.018em; }
.eng p { margin: 0; }
.eng .lead { font-size: var(--t-lead); line-height: 1.6; color: var(--tx); }
.eng .muted { color: var(--tx-mid); }

.eng .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  font-weight: 500;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--azure-700);
}
.eng .eyebrow::before {
  content: '';
  width: 26px;
  height: 1px;
  flex: none;
  background: linear-gradient(90deg, transparent, var(--azure-600));
}
.eng .eyebrow.no-rule::before { display: none; }
[dir="rtl"] .eng .eyebrow::before { background: linear-gradient(270deg, transparent, var(--azure-600)); }

.eng .mono {
  font-family: var(--f-mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--tx-lo);
}

/* ---- layout helpers (scoped, so they cannot touch the rest of the site) ---- */
.eng .section { padding-block: clamp(3.5rem, 2rem + 5vw, 6.5rem); position: relative; background: var(--paper-100); }
.eng .on-paper { background: var(--paper-0); }
.eng .section-head { max-width: 62ch; margin-bottom: clamp(2.2rem, 1rem + 3vw, 3.6rem); }
.eng .section-head.center { text-align: center; margin-inline: auto; max-width: 74ch; }
.eng .section-head h2 { margin-top: 1.1rem; }
.eng .section-head.center h2 { max-width: 36ch; margin-inline: auto; }
.eng .section-head p { margin-top: 1.25rem; color: var(--tx-mid); font-size: var(--t-lead); }
.eng .section-head.center p { max-width: 56ch; margin-inline: auto; }
.eng .section-head.center .eyebrow::before { display: none; }

.eng .split { display: grid; gap: clamp(2.2rem, 1rem + 4vw, 4.5rem); align-items: start; }
/* Grid children default to min-width:auto, so a wide table inside kept the
   single mobile column at 622px on a 390px screen. */
.eng .split > * { min-width: 0; }
@media (min-width: 900px) {
  .eng .split { grid-template-columns: 1fr 1fr; }
  .eng .split.a { grid-template-columns: 1.05fr 0.95fr; }
}
.eng .cols-2, .eng .cols-3, .eng .cols-4 { display: grid; gap: 1.5rem; }
@media (min-width: 640px)  { .eng .cols-2, .eng .cols-3, .eng .cols-4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .eng .cols-3 { grid-template-columns: repeat(3, 1fr); } .eng .cols-4 { grid-template-columns: repeat(4, 1fr); } }
.eng .center { text-align: center; }
.eng .mt-1 { margin-top: 1rem; }
.eng .mt-2 { margin-top: 1.5rem; }
.eng .mt-3 { margin-top: 2rem; }
.eng .mt-4 { margin-top: 2.75rem; }
.eng .mt-5 { margin-top: 4rem; }
.eng .mb-2 { margin-bottom: 1.5rem; }
.eng .mb-3 { margin-bottom: 2rem; }
.eng .sticky-side { position: sticky; top: calc(var(--header-height) + 2rem); }

.eng .rule { height: 1px; background: var(--hair); position: relative; }
.eng .rule::before { content: ''; position: absolute; inset-inline-start: 0; top: 0; width: 56px; height: 1px; background: var(--azure-600); }

/* engineering grid backdrop */
.eng .gridlines { position: relative; isolation: isolate; }
.eng .gridlines::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(10, 45, 105, 0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(10, 45, 105, 0.045) 1px, transparent 1px);
  background-size: 88px 88px;
  mask-image: radial-gradient(ellipse 80% 62% at 50% 42%, #000 25%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 80% 62% at 50% 42%, #000 25%, transparent 78%);
}
[data-theme="dark"] .eng .gridlines::before {
  background-image:
    linear-gradient(to right, rgba(255, 255, 255, 0.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
}

/* ---- six line-art tiles ---- */
.eng .prod-grid {
  display: grid;
  gap: 1px;
  background: var(--hair);
  border: 1px solid var(--hair);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: var(--card-shadow);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 660px)  { .eng .prod-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .eng .prod-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); } }

.eng .prod {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--paper-0);
  padding: 1.7rem 1rem 1.35rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.55rem;
  transition: background-color 0.35s var(--e-in);
}
.eng .prod::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  background-image:
    linear-gradient(to right, rgba(18, 87, 166, 0.09) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(18, 87, 166, 0.09) 1px, transparent 1px);
  background-size: 14px 14px;
  mask-image: radial-gradient(ellipse 70% 55% at 50% 38%, #000, transparent 72%);
  -webkit-mask-image: radial-gradient(ellipse 70% 55% at 50% 38%, #000, transparent 72%);
  transition: opacity 0.45s var(--e-in);
}
.eng .prod:hover { background: rgba(30, 111, 196, 0.05); }
.eng .prod:hover::before { opacity: 1; }
.eng .prod .art { width: 100%; max-width: 122px; height: 78px; color: var(--azure-700); transition: transform 0.55s var(--e-out), color 0.35s var(--e-in); }
.eng .prod:hover .art { transform: translateY(-4px) scale(1.06); color: var(--azure-500); }
.eng .prod .pn { font-family: var(--f-display); font-weight: 700; font-size: 0.9rem; letter-spacing: -0.015em; color: var(--tx-hi); margin-top: 0.35rem; }
.eng .prod .ps { font-family: var(--f-mono); font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--tx-lo); }

/* The tiles are links into the matching catalogue section. */
.eng a.prod { text-decoration: none; color: inherit; cursor: pointer; }
.eng a.prod:focus-visible { outline: 2px solid var(--azure-600); outline-offset: -3px; }

/* Elbows, tees and reducers are one family and share a destination, so they
   carry a corner tag. Absolute, so it adds no height and the row stays even. */
.eng .prod .pf {
  position: absolute;
  top: 0.55rem;
  inset-inline-start: 0.55rem;
  font-family: var(--f-mono);
  font-size: 0.48rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  line-height: 1;
  padding: 0.22rem 0.4rem;
  border-radius: 999px;
  color: var(--azure-700);
  background: rgba(30, 111, 196, 0.1);
}
[data-theme="dark"] .eng .prod .pf { background: rgba(120, 170, 240, 0.16); }

/* ---- bars ---- */
.eng .bar { height: 4px; border-radius: 4px; background: var(--paper-300); overflow: hidden; margin-top: 0.55rem; }
.eng .bar i {
  display: block;
  height: 100%;
  border-radius: 4px;
  width: 0;
  background: linear-gradient(90deg, var(--azure-700), var(--azure-400));
  transition: width 1.5s var(--e-out);
}
.eng .bar-lg { height: 15px; border-radius: 9px; margin-top: 0; }
.eng .bar-lg i { border-radius: 9px; box-shadow: 0 0 22px -5px rgba(30, 111, 196, 0.8); }
.eng .bar-slow i { background: linear-gradient(90deg, #9aa9bf, #7186a3); box-shadow: none; }
[data-theme="dark"] .eng .bar-slow i { background: linear-gradient(90deg, #4a5a70, #33415a); }

/* ---- cards ---- */
.eng .card {
  position: relative;
  padding: clamp(1.5rem, 1rem + 1.2vw, 2.15rem);
  background: var(--paper-0);
  border: 1px solid var(--hair);
  border-radius: 16px;
  box-shadow: var(--card-shadow);
  overflow: hidden;
  isolation: isolate;
  transition: transform 0.55s var(--e-out), border-color 0.45s var(--e-in), box-shadow 0.45s var(--e-in);
}
/* cursor-following spotlight, driven from app.js */
.eng .card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  background: radial-gradient(520px circle at var(--mx, 50%) var(--my, 0%), rgba(30, 111, 196, 0.09), transparent 62%);
  transition: opacity 0.5s var(--e-in);
}
.eng .card:hover { transform: translateY(-5px); border-color: rgba(18, 87, 166, 0.36); box-shadow: var(--card-shadow-lg); }
.eng .card:hover::before { opacity: 1; }

.eng .card-art { width: 100%; max-width: 148px; height: 92px; margin-bottom: 0.5rem; color: var(--azure-700); transition: transform 0.55s var(--e-out), color 0.35s var(--e-in); }
/* The art turns in 3D on hover. Surface detail inside the pipe symbols rolls
   around the axis at the same time — a cylinder spinning shows its marks
   travelling across the face, not sideways. The roll is gated on a custom
   property because it lives inside a <use> shadow tree, which ordinary
   selectors cannot reach; custom properties inherit into it. */
.eng .card { perspective: 760px; }
.eng .card-art { transform-style: preserve-3d; }

.eng .card:hover .card-art {
  transform: translateY(-4px) scale(1.05) rotateX(9deg) rotateY(-19deg);
  color: var(--azure-500);
}

.eng .card:hover { --art-spin: running; }

@keyframes il-roll {
  from { transform: translateY(0); }
  to   { transform: translateY(56px); }
}

/* Flat lift only, and no roll, when the visitor asks for less movement. */
@media (prefers-reduced-motion: reduce) {
  .eng .card:hover .card-art { transform: translateY(-4px) scale(1.05); }
  .eng .card:hover { --art-spin: paused; }
}

/* Category intros are capped at a readable measure, which left the right
   half of every section head empty. The product cards move up into it. */
.eng .sec-split {
  display: grid;
  gap: clamp(1.6rem, 1rem + 2.4vw, 3.2rem);
  align-items: start;
  margin-bottom: clamp(2.2rem, 1rem + 3vw, 3.6rem);
}

@media (min-width: 1000px) {
  .eng .sec-split { grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr); }
}

/* The head no longer carries the section spacing — the split does. */
.eng .sec-split > .section-head { margin-bottom: 0; max-width: 56ch; }

.eng .head-cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.75rem, 0.4rem + 0.9vw, 1.1rem);
}

@media (max-width: 479px) { .eng .head-cards { grid-template-columns: minmax(0, 1fr); } }

/* Half-width cards need less padding and smaller art than the full row. */
.eng .head-cards .card { padding: clamp(1rem, 0.7rem + 0.8vw, 1.35rem); }
.eng .head-cards .card-art { max-width: 128px; height: 86px; }
.eng .head-cards h4 { font-size: 0.95rem; }
.eng .head-cards p { font-size: var(--t-sm); }
.eng .head-cards .bracket::before { top: 9px; inset-inline-start: 9px; }
.eng .head-cards .bracket::after { bottom: 9px; inset-inline-end: 9px; }

.eng .bracket { position: relative; }
.eng .bracket::before, .eng .bracket::after {
  content: '';
  position: absolute;
  width: 13px;
  height: 13px;
  pointer-events: none;
  border-color: var(--azure-600);
  opacity: 0.42;
  transition: opacity 0.4s var(--e-in), width 0.4s var(--e-in), height 0.4s var(--e-in);
}
.eng .bracket::before { top: 12px; inset-inline-start: 12px; border-top: 1px solid; border-inline-start: 1px solid; }
.eng .bracket::after { bottom: 12px; inset-inline-end: 12px; border-bottom: 1px solid; border-inline-end: 1px solid; }
.eng .bracket:hover::before, .eng .bracket:hover::after { opacity: 1; width: 20px; height: 20px; }

.eng .tag {
  font-family: var(--f-mono); font-size: 0.625rem; letter-spacing: 0.11em; text-transform: uppercase;
  color: var(--tx-mid); padding: 0.3rem 0.55rem; border: 1px solid var(--hair);
  border-radius: 3px; background: var(--paper-200); white-space: nowrap;
}
.eng .tags { display: flex; gap: 0.38rem; flex-wrap: wrap; }

.eng .chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.eng .chip {
  font-family: var(--f-mono); font-size: 0.68rem; letter-spacing: 0.07em;
  padding: 0.45rem 0.78rem; border: 1px solid var(--hair); border-radius: 6px;
  color: var(--tx-mid); background: var(--paper-0);
  transition: border-color 0.3s var(--e-in), color 0.3s var(--e-in), background-color 0.3s;
}
.eng .chip:hover { border-color: rgba(18, 87, 166, 0.42); color: var(--azure-700); background: rgba(30, 111, 196, 0.06); }

.eng .badge {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.45rem 0.85rem; border-radius: 100px;
  border: 1px solid rgba(162, 103, 20, 0.28); background: rgba(255, 180, 84, 0.14);
  font-family: var(--f-mono); font-size: 0.655rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--amber-600);
}
.eng .badge.blue { border-color: rgba(18, 87, 166, 0.3); background: rgba(30, 111, 196, 0.09); color: var(--azure-700); }
.eng .badge i { width: 5px; height: 5px; border-radius: 50%; background: currentColor; flex: none; }
[data-theme="dark"] .eng .badge { background: rgba(224, 165, 87, 0.12); border-color: rgba(224, 165, 87, 0.3); }

/* ---- tables ---- */
.eng .tbl-wrap { overflow-x: auto; border: 1px solid var(--hair); border-radius: 16px; background: var(--paper-0); box-shadow: var(--card-shadow); }
.eng table.tbl { width: 100%; border-collapse: collapse; min-width: 620px; }
.eng table.tbl th, .eng table.tbl td { text-align: start; padding: 0.95rem 1.15rem; border-bottom: 1px solid var(--hair); vertical-align: top; }
.eng table.tbl thead th {
  font-family: var(--f-mono); font-size: 0.625rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--tx-lo); font-weight: 500; background: var(--paper-200); white-space: nowrap;
}
.eng table.tbl tbody th { font-family: var(--f-display); font-weight: 700; font-size: 0.92rem; color: var(--tx-hi); white-space: nowrap; }
.eng table.tbl td { font-family: var(--f-mono); font-size: 0.775rem; color: var(--tx-mid); }
.eng table.tbl tbody tr:last-child th, .eng table.tbl tbody tr:last-child td { border-bottom: 0; }
.eng table.tbl tbody tr { transition: background-color 0.25s var(--e-in); }
.eng table.tbl tbody tr:hover { background: rgba(30, 111, 196, 0.05); }

.eng .specs { border-top: 1px solid var(--hair); margin: 0; }
.eng .spec-row { display: grid; gap: 0.35rem 1.5rem; padding: 1.05rem 0; border-bottom: 1px solid var(--hair); align-items: baseline; }
@media (min-width: 640px) { .eng .spec-row { grid-template-columns: minmax(0, 15rem) 1fr; } }
.eng .spec-row dt { font-family: var(--f-display); font-weight: 700; font-size: 0.95rem; color: var(--tx-hi); letter-spacing: -0.012em; }
.eng .spec-row dd { font-family: var(--f-mono); font-size: 0.8rem; line-height: 1.72; color: var(--tx-mid); margin-inline-start: 0; }

/* ---- buttons (named .ebtn: the site already owns .btn) ---- */
.eng .ebtn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.65rem;
  padding: 0.95rem 1.7rem;
  font-family: var(--f-display); font-size: 0.935rem; font-weight: 700;
  border-radius: 6px; border: 1px solid transparent; white-space: nowrap; cursor: pointer;
  transition: transform 0.35s var(--e-out), background-color 0.3s var(--e-in),
              border-color 0.3s var(--e-in), color 0.3s var(--e-in), box-shadow 0.35s var(--e-out);
}
.eng .ebtn svg { width: 15px; height: 15px; flex: none; transition: transform 0.4s var(--e-out); }
.eng .ebtn:hover { transform: translateY(-2px); }
.eng .ebtn:hover svg { transform: translateX(4px); }
[dir="rtl"] .eng .ebtn svg { transform: scaleX(-1); }
[dir="rtl"] .eng .ebtn:hover svg { transform: scaleX(-1) translateX(4px); }
.eng .ebtn-primary { background: var(--azure-600); color: #fff; box-shadow: 0 12px 26px -12px rgba(18, 87, 166, 0.7); }
.eng .ebtn-primary:hover { background: var(--azure-500); box-shadow: 0 20px 38px -14px rgba(18, 87, 166, 0.8); }
.eng .ebtn-ghost { background: var(--paper-0); border-color: var(--hair-str); color: var(--tx-hi); box-shadow: var(--card-shadow); }
.eng .ebtn-ghost:hover { border-color: var(--azure-600); color: var(--azure-700); }

/* ---- reveal (its own attribute, separate from the site's .reveal class) ---- */
.eng [data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.85s var(--e-out), transform 0.95s var(--e-out);
}
.eng [data-reveal].in { opacity: 1; transform: none; }
.eng [data-reveal][data-d="1"] { transition-delay: 0.08s; }
.eng [data-reveal][data-d="2"] { transition-delay: 0.16s; }
.eng [data-reveal][data-d="3"] { transition-delay: 0.24s; }

@media (prefers-reduced-motion: reduce) {
  .eng [data-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; }
  .eng .prod:hover .art, .eng .card:hover .card-art, .eng .card:hover,
  .eng .ebtn:hover { transform: none; }
  .eng .bar i { transition: none; }
}

/* --------------------------------------------------------------------------
   "Held in stock" — the section box itself
   -------------------------------------------------------------------------- */
#stock {
  position: relative;
  isolation: isolate;
  padding-block: clamp(4.5rem, 2rem + 8vw, 8rem);
  background: var(--paper-100);
}
#stock::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(10, 45, 105, 0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(10, 45, 105, 0.045) 1px, transparent 1px);
  background-size: 88px 88px;
  mask-image: radial-gradient(ellipse 80% 62% at 50% 42%, #000 25%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 80% 62% at 50% 42%, #000 25%, transparent 78%);
}
[data-theme="dark"] #stock::before {
  background-image:
    linear-gradient(to right, rgba(255, 255, 255, 0.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
}
#stock .stock-head { max-width: 62ch; margin-bottom: clamp(2.4rem, 1rem + 3.4vw, 4.2rem); }
#stock .stock-head.center { text-align: center; margin-inline: auto; max-width: 74ch; }
#stock .stock-head h2 { margin-top: 1.1rem; }
#stock .stock-head.center h2 { max-width: 36ch; margin-inline: auto; }
#stock .stock-head p { margin-top: 1.25rem; color: var(--tx-mid); font-size: var(--t-lead); }
#stock .stock-head.center p { max-width: 56ch; margin-inline: auto; }
#stock .stock-head.center .eyebrow::before { display: none; }
#stock .stock-split { display: grid; gap: clamp(2.4rem, 1rem + 4.5vw, 5rem); align-items: center; }
@media (min-width: 900px) { #stock .stock-split { grid-template-columns: 1.05fr 0.95fr; } }
#stock .lead-cmp { display: grid; gap: 1.9rem; }
#stock .lt-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: 0.7rem; }
#stock .lt-label { font-family: var(--f-display); font-weight: 700; font-size: 1rem; letter-spacing: -0.015em; color: var(--tx-hi); }
#stock .lt-val { font-family: var(--f-mono); font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--tx-lo); white-space: nowrap; }
#stock .lt-val.hot { color: var(--azure-700); }
#stock .stock-foot { text-align: center; margin-top: 2.75rem; }
#stock .stock-mt { margin-top: 4rem; }

/* --------------------------------------------------------------------------
   Piping catalogue page
   -------------------------------------------------------------------------- */
#piping-cat .phero {
  position: relative;
  overflow: hidden;
  padding-top: calc(var(--header-height) + clamp(2.5rem, 1.5rem + 4vw, 5rem));
  padding-bottom: clamp(2.6rem, 1.5rem + 3.5vw, 4.5rem);
  background:
    radial-gradient(ellipse 72% 100% at 84% 0%, rgba(30, 111, 196, 0.15), transparent 64%),
    linear-gradient(172deg, var(--paper-0), var(--paper-100) 62%, var(--paper-200));
  border-bottom: 1px solid var(--hair);
}
#piping-cat .phero::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(to right, rgba(10, 45, 105, 0.04) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(10, 45, 105, 0.04) 1px, transparent 1px);
  background-size: 76px 76px;
  mask-image: radial-gradient(ellipse 90% 100% at 70% 10%, #000, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 90% 100% at 70% 10%, #000, transparent 75%);
}
[data-theme="dark"] #piping-cat .phero::before {
  background-image:
    linear-gradient(to right, rgba(255, 255, 255, 0.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
}
/* The banner carries a slow rotation of four stock photographs. Each frame is
   masked away from the text column exactly as the division banners are, so
   contrast never depends on which frame happens to be showing. The peak
   opacity is a custom property because the value lives inside the keyframes —
   a plain override would lose to the running animation. */
#piping-cat .phero-shots {
  --shot-peak: 0.42;
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

#piping-cat .phero-shots i {
  position: absolute;
  inset: 0;
  background-image: var(--shot);
  background-size: cover;
  background-position: center right;
  opacity: 0;
  animation: phero-cycle 36s ease-in-out infinite;
  -webkit-mask-image: linear-gradient(to left, #000 0%, rgba(0, 0, 0, 0.55) 12%, transparent 34%);
  mask-image: linear-gradient(to left, #000 0%, rgba(0, 0, 0, 0.55) 12%, transparent 34%);
}

/* Four frames over 36s — each holds for nine seconds, then hands over. */
#piping-cat .phero-shots i:nth-child(2) { animation-delay: 9s; }
#piping-cat .phero-shots i:nth-child(3) { animation-delay: 18s; }
#piping-cat .phero-shots i:nth-child(4) { animation-delay: 27s; }

@keyframes phero-cycle {
  0%   { opacity: 0; transform: scale(1.05); }
  3%   { opacity: var(--shot-peak); }
  22%  { opacity: var(--shot-peak); }
  25%  { opacity: 0; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.05); }
}

/* Mirror the fade in Arabic, otherwise the photo lands under the text */
[dir="rtl"] #piping-cat .phero-shots i {
  background-position: center left;
  -webkit-mask-image: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0.55) 12%, transparent 34%);
  mask-image: linear-gradient(to right, #000 0%, rgba(0, 0, 0, 0.55) 12%, transparent 34%);
}

[data-theme="dark"] #piping-cat .phero-shots { --shot-peak: 0.24; }

/* Below 992px the text spans the full width, so the side fade no longer keeps
   the photo clear of it — drop to a faint bottom-weighted wash instead. */
/* Below 992px the text spans the full width, so no side mask can keep the
   photo clear of it — and a wash faint enough to hold 4.5:1 on the intro
   paragraph is too faint to be worth showing. Drop the photo instead. */
@media (max-width: 992px) {
  #piping-cat .phero-shots { display: none; }
}

/* No rotation when the visitor asks for less movement — hold the first frame. */
@media (prefers-reduced-motion: reduce) {
  #piping-cat .phero-shots i { animation: none; opacity: 0; transform: none; }
  #piping-cat .phero-shots i:first-child { opacity: var(--shot-peak); }
}

#piping-cat .phero > .container { position: relative; z-index: 1; }
#piping-cat .phero h1 { margin-top: 1.35rem; max-width: 20ch; }
#piping-cat .phero > .container > p { margin-top: 1.5rem; max-width: 58ch; color: var(--tx-mid); font-size: var(--t-lead); }

#piping-cat .crumb {
  display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap;
  font-family: var(--f-mono); font-size: var(--t-mono); letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--tx-lo); margin-bottom: 1.4rem;
}
#piping-cat .crumb a { color: var(--tx-lo); transition: color 0.25s; }
#piping-cat .crumb a:hover { color: var(--azure-700); }
#piping-cat .crumb span { color: var(--azure-700); }

/* The glow below is deliberately oversized and hangs off the right edge
   (inset-inline-end: -14%), which pushed the document 191px wider than the
   viewport. clip contains it without creating a scroll container. */
#piping-cat .bloom { position: relative; isolation: isolate; overflow: clip; }
#piping-cat .bloom::after {
  content: '';
  position: absolute; z-index: -1; pointer-events: none;
  width: 62vw; height: 62vw; max-width: 900px; max-height: 900px;
  top: -22%; inset-inline-end: -14%; border-radius: 50%;
  background: radial-gradient(circle, rgba(30, 111, 196, 0.11) 0%, transparent 68%);
  filter: blur(20px);
}

/* Each value carries its own leading separator and never breaks, so a wrapped
   spec list cannot end a line on a dangling dot or split a code in half. */
.eng .tbl .v { white-space: nowrap; }

/* Long spec lists split into even lines instead of running the full width
   and leaving a short orphan on the second line. */
.eng .tbl td { text-wrap: balance; }

/* Product-type cells are bulleted lists in the source document, so they stay
   lists here rather than collapsing into one dot-separated run. */
.eng .tbl .cell-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.3rem;
}

.eng .tbl .cell-list li {
  position: relative;
  padding-inline-start: 0.85rem;
}

.eng .tbl .cell-list li::before {
  content: '';
  position: absolute;
  inset-inline-start: 0;
  top: 0.58em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--azure-500);
  opacity: 0.75;
}

/* Vendor approvals: a logo on a white plate with the vendor number beneath. */
.eng .ap-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--hair);
  border: 1px solid var(--hair);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: var(--card-shadow);
}

@media (min-width: 640px)  { .eng .ap-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .eng .ap-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.eng .ap-card {
  background: var(--paper-0);
  padding: 1.25rem 1rem 1.1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.5rem;
  transition: background-color 0.35s var(--e-in);
}

.eng .ap-card:hover { background: rgba(30, 111, 196, 0.05); }

/* Every supplied logo has white baked in, so the plate is white in both themes. */
.eng .ap-logo {
  width: 100%;
  height: 76px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  border-radius: 8px;
  padding: 6px 10px;
}

.eng .ap-logo img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

.eng .ap-name {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 0.86rem;
  color: var(--tx-hi);
  line-height: 1.3;
}

.eng .ap-id {
  font-family: var(--f-mono);
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  color: var(--tx-lo);
}

#piping-cat .div-photo {
  margin: 0 0 clamp(2rem, 1rem + 2vw, 3.25rem);
  border-radius: 16px; overflow: hidden; line-height: 0;
  border: 1px solid var(--hair); box-shadow: var(--card-shadow); background: var(--paper-200);
}
#piping-cat .div-photo img { width: 100%; height: clamp(190px, 27vw, 340px); object-fit: cover; transition: transform 1.2s var(--e-out); }
[data-theme="dark"] #piping-cat .div-photo img { filter: brightness(0.78) saturate(0.9); }

#piping-cat .big-n { font-family: var(--f-display); font-size: 1.5rem; font-weight: 800; color: var(--tx-hi); letter-spacing: -0.03em; }

/* closing band — deep navy, tokens flipped so children invert */
#piping-cat .cta-band {
  position: relative; overflow: hidden; isolation: isolate;
  padding-block: clamp(4rem, 2rem + 6vw, 7rem);
  background:
    radial-gradient(ellipse 60% 130% at 80% 50%, rgba(30, 111, 196, 0.30), transparent 62%),
    linear-gradient(122deg, var(--navy-900), var(--ink-850) 66%);
  color: #c6d5ec;
  --tx-hi: #f2f7ff; --tx: #c6d5ec; --tx-mid: #93a9c9; --tx-lo: #6d84a6;
  --hair: rgba(255, 255, 255, 0.10); --hair-str: rgba(255, 255, 255, 0.2);
  --paper-0: rgba(255, 255, 255, 0.045); --paper-200: rgba(255, 255, 255, 0.06);
}
#piping-cat .cta-band .eyebrow { color: var(--azure-300); }
#piping-cat .cta-band .eyebrow::before { background: linear-gradient(90deg, transparent, var(--azure-400)); }
#piping-cat .cta-band h2 { max-width: 18ch; }
#piping-cat .cta-band p { margin-top: 1.3rem; max-width: 48ch; font-size: var(--t-lead); }
#piping-cat .cta-actions { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: 2.2rem; }
#piping-cat .cta-band .ebtn-ghost { background: rgba(255, 255, 255, 0.06); border-color: rgba(255, 255, 255, 0.24); color: #fff; box-shadow: none; }
#piping-cat .cta-band .ebtn-ghost:hover { background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.42); color: #fff; }

#piping-cat .ct-list { display: grid; gap: 1px; background: var(--hair); border: 1px solid var(--hair); border-radius: 16px; overflow: hidden; }
#piping-cat .ct { display: flex; gap: 1.1rem; padding: 1.5rem; background: rgba(255, 255, 255, 0.045); transition: background-color 0.3s var(--e-in); }
#piping-cat .ct:hover { background: rgba(61, 138, 217, 0.14); }
#piping-cat .ct .i { flex: none; width: 38px; height: 38px; display: grid; place-items: center; border-radius: 6px; background: rgba(61, 138, 217, 0.14); border: 1px solid rgba(61, 138, 217, 0.28); color: var(--azure-300); }
#piping-cat .ct .i svg { width: 17px; height: 17px; }
#piping-cat .ct > span { display: block; min-width: 0; }
#piping-cat .ct .k, #piping-cat .ct .v, #piping-cat .ct .s { display: block; }
#piping-cat .ct .k { font-family: var(--f-mono); font-size: 0.625rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--tx-lo); }
#piping-cat .ct .v { margin-top: 0.35rem; font-family: var(--f-display); font-weight: 700; font-size: 0.98rem; color: var(--tx-hi); letter-spacing: -0.015em; word-break: break-word; }
#piping-cat .ct .s { margin-top: 0.3rem; font-size: var(--t-xs); color: var(--tx-mid); }
#piping-cat .form-note { font-size: var(--t-xs); color: var(--tx-lo); line-height: 1.6; }

/* --------------------------------------------------------------------------
   13. Accessibility — honour reduced-motion preferences
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .stagger.in > *,
  .stagger > * {
    animation: none !important;
    translate: none !important;
    scale: none !important;
  }

  /* The timeline animates the node's parts rather than the node, so it needs
     its own line here. */
  .timeline-grid-track.stagger .timeline-node::after,
  .timeline-grid-track.stagger .timeline-node-dot,
  .timeline-grid-track.stagger .timeline-node-stem,
  .timeline-grid-track.stagger .timeline-year,
  .timeline-grid-track.stagger .timeline-node-card,
  .timeline-grid-track.stagger.in .timeline-node::after,
  .timeline-grid-track.stagger.in .timeline-node-dot,
  .timeline-grid-track.stagger.in .timeline-node-stem,
  .timeline-grid-track.stagger.in .timeline-year,
  .timeline-grid-track.stagger.in .timeline-node-card {
    animation: none !important;
    translate: none !important;
    scale: none !important;
    opacity: 1 !important;
  }

  .timeline-grid-track.stagger.in .timeline-node-dot::after { display: none !important; }

  .timeline-grid-track.stagger::after,
  .timeline-grid-track.stagger.in::after {
    animation: none !important;
    scale: none !important;
  }

  /* the travelling tick and the spotlight it hands out are motion for their
     own sake — they simply go */
  .timeline-grid-track.stagger.in::before,
  .timeline-grid-track.stagger.in .timeline-node-card::after {
    display: none !important;
  }


  .sw-i,
  .stagger > *,
  .reveal,
  .reveal-left,
  .reveal-right,
  .reveal-scale,
  .reveal-blur {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }

  .about-image-wrapper > *,
  .division-media > * {
    clip-path: none !important;
    transition: none !important;
  }

  .about-image-wrapper img,
  .division-media img {
    transform: none !important;
  }

  .hero-spotlight { display: none; }

  .section-title::after {
    transition: none !important;
    width: 82px !important;
  }

  .to-top { transition: opacity 0.2s ease !important; }

  .orb,
  .hero-bg,
  .hero-grid-overlay,
  .map-route,
  .map-route-local path,
  .map-node,
  .map-hub-ring,
  .logo-marquee-track,
  .section-tag::after,
  .hero-title .grad,
  .hero-title .grad .sw-i {
    animation: none !important;
  }

  .hero-canvas { display: none; }
}

/* ==========================================================================
   Justified paragraphs (client request)
   --------------------------------------------------------------------------
   Every paragraph is justified at every width. Where the surrounding layout is
   centred (section intros, captions, centred cards), the final line stays
   centred so the block still sits in the middle; everywhere else it runs from
   the start edge as usual.
   ========================================================================== */
p {
  text-align: justify;
  text-justify: inter-word;
}

.section-header p,
.lightbox-caption p,
.client-card-item p,
.footer-office p,
.footer-bottom p,
.marquee-caption p,
.eng .center p,
.eng p.center,
.eng .section-head.center p,
.eng .ap-card p,
#stock .stock-head.center p,
#stock .stock-foot p {
  text-align-last: center;
}

/* Narrow columns hold only a few words per line, so justifying alone would
   open wide gaps between them. Allowing hyphenation there keeps the spacing
   even. */
@media (max-width: 768px) {
  p {
    -webkit-hyphens: auto;
    hyphens: auto;
  }
}

/* ==========================================================================
   Careers page (careers.html)
   ========================================================================== */
.hero-careers { --hero-img: url('images/piping-refinery-engineer.jpg?v=20260914'); }

.careers-hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 28px;
}

.careers-section { padding: 72px 0; background: var(--bg-primary); }
.careers-alt { background: var(--bg-secondary); }

.careers-why {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 20px;
}
.careers-why .highlight-card { background: var(--bg-card); box-shadow: var(--shadow-sm); }

.careers-areas { margin-top: 48px; }
.careers-subhead {
  font-size: 1.25rem;
  margin-bottom: 18px;
  text-align: center;
}
.careers-area-list {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  padding: 0;
  margin: 0;
}
.careers-area-list li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: 0.95rem;
}
.careers-area-list i { color: var(--brand-blue); width: 20px; text-align: center; flex-shrink: 0; }

/* Openings */
.careers-openings { display: grid; gap: 16px; max-width: 900px; margin: 0 auto; }

.careers-empty {
  text-align: center;
  padding: 44px 28px;
  background: var(--bg-card);
  border: 1px dashed var(--border-color);
  border-radius: var(--radius-lg);
}
.careers-empty > i { font-size: 2rem; color: var(--brand-blue); margin-bottom: 14px; }
.careers-empty h4 { font-size: 1.2rem; margin-bottom: 10px; }
.careers-empty p {
  color: var(--text-secondary);
  max-width: 56ch;
  margin: 0 auto 22px;
  text-align-last: center;
}

.careers-job {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 24px 28px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.careers-job h4 { font-size: 1.15rem; margin-bottom: 8px; }
.careers-job p { color: var(--text-secondary); font-size: 0.95rem; margin-top: 10px; }
.careers-job-meta {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  padding: 0;
  margin: 0;
  color: var(--text-muted);
  font-size: 0.88rem;
}
.careers-job-meta i { color: var(--brand-blue); margin-inline-end: 6px; }
.careers-job-apply { flex-shrink: 0; padding: 12px 26px; }

/* Apply */
.careers-apply-grid {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: 48px;
  align-items: start;
}

.careers-steps { list-style: none; padding: 0; margin: 8px 0 28px; display: grid; gap: 22px; }
.careers-steps li { display: flex; gap: 16px; align-items: flex-start; }
.careers-steps h4 { font-size: 1.05rem; margin-bottom: 4px; }
.careers-steps p { color: var(--text-secondary); font-size: 0.95rem; line-height: 1.6; }
.careers-step-n {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(29, 93, 183, 0.12);
  color: var(--brand-blue);
  font-weight: 800;
  font-family: var(--font-heading);
}

.careers-direct {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  padding: 16px 18px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: 0.95rem;
  text-align: start;
}
.careers-direct i { color: var(--brand-blue); }
.careers-email-link { color: var(--brand-blue); font-weight: 700; }
.careers-email-link:hover { text-decoration: underline; }

.careers-form-title { font-size: 1.5rem; margin-bottom: 22px; }
.careers-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 16px;
}
.careers-form-note {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 0.88rem;
  color: var(--text-secondary);
  margin: 4px 0 18px;
  text-align: start;
}
.careers-form-note i { color: var(--accent-gold); margin-top: 3px; }
.careers-form-error {
  color: #c0392b;
  font-weight: 600;
  font-size: 0.9rem;
  margin: -6px 0 14px;
  text-align: start;
}
.careers-submit { width: 100%; }

@media (max-width: 1100px) {
  .careers-why { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 992px) {
  .careers-apply-grid { grid-template-columns: 1fr; gap: 36px; }
  .careers-area-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .careers-section { padding: 52px 0; }
  .careers-why,
  .careers-area-list,
  .careers-form-row { grid-template-columns: 1fr; }
  .careers-job { flex-direction: column; align-items: stretch; padding: 20px; }
  .careers-job-apply { justify-content: center; }
  .careers-hero-actions .btn { flex: 1 1 100%; }
  .contact-form-card { padding: 26px 20px; }
}

/* Careers form: "I'm not a robot" box. Google's widget is a fixed 304px;
   on the narrowest phones it is scaled down so it never overflows the card. */
.careers-recaptcha { min-height: 78px; }
@media (max-width: 360px) {
  .careers-recaptcha .g-recaptcha { transform: scale(0.88); transform-origin: 0 0; }
}

/* Honeypot: kept off-screen rather than display:none, which some bots skip */
.careers-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Careers form: CV upload */
.cv-input {
  /* visually hidden but still focusable and announced; the label is the UI */
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
}
.cv-drop {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border: 1.5px dashed var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-primary);
  cursor: pointer;
  transition: border-color var(--transition-fast), background var(--transition-fast);
}
.cv-drop:hover,
.cv-input:focus-visible + .cv-drop,
.cv-drop:focus-within { border-color: var(--brand-blue); background: rgba(29, 93, 183, 0.05); }
.cv-drop > i { font-size: 1.5rem; color: var(--brand-blue); flex-shrink: 0; }
.cv-drop-text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.cv-drop-text strong {
  font-size: 0.95rem;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cv-drop-text small { font-size: 0.8rem; color: var(--text-muted); }
.cv-drop-btn {
  flex-shrink: 0;
  padding: 8px 16px;
  border-radius: var(--radius-full);
  background: rgba(29, 93, 183, 0.12);
  color: var(--brand-blue);
  font-weight: 700;
  font-size: 0.85rem;
}
.cv-drop.has-file { border-style: solid; border-color: #1e9e5a; background: rgba(30, 158, 90, 0.06); }
.cv-drop.has-file > i { color: #1e9e5a; }
.cv-drop.is-invalid { border-color: #c0392b; background: rgba(192, 57, 43, 0.05); }

/* Careers form: sent confirmation */
.careers-sent {
  text-align: center;
  padding: 28px 12px 12px;
}
.careers-sent > i { font-size: 2.6rem; color: #1e9e5a; margin-bottom: 14px; }
.careers-sent h4 { font-size: 1.25rem; margin-bottom: 10px; }
.careers-sent p { color: var(--text-secondary); text-align-last: center; }

.careers-submit:disabled { opacity: 0.75; cursor: wait; transform: none; }

/* Piping catalogue: the Saudi Aramco spec codes in the project-standards note */
.spec-codes {
  font-weight: 700;
  color: var(--tx-hi, var(--text-primary));
}

