/*
Theme Name: Maritime Alliance
Theme URI: https://malliance.com
Author: Maritime Alliance Pte Ltd
Description: Custom theme for Maritime Alliance Pte Ltd — reliable maritime & logistics solutions across Asia.
Version: 1.0
Requires at least: 6.0
Requires PHP: 7.4
Text Domain: maritime-alliance
*/

:root{
  --primary: #0070ab;     /* 2026-09-25: was #007FC2 (white on it 4.36:1, it on white 4.36:1 — just under WCAG AA); now 5.4:1 */
  --primary-dark: #045d8f;
  --navy: #0b2e4f;
  --navy-dark: #071c33;
  --accent: #F9C321;
  --light-blue: #eaf4fb;
  --text: #333333;
  --muted: #5f6b78;       /* 2026-09-25: was #6b7785 (4.1:1 on the light-blue bands — fails AA); now 4.9:1 */
  --white: #ffffff;
  /* Theme tokens. Light values below are the site's original colours, unchanged; the dark
     palette lives in ONE block at the end of this file ("Dark theme"). --white / --navy /
     --light-blue / --primary stay FIXED brand colours (text on photos, button fills, badges) —
     anything that must change with the theme uses these role tokens instead. */
  --bg: #ffffff;          /* page background */
  --surface: #ffffff;     /* cards, solid header, dropdowns, form panels */
  --surface-alt: #eaf4fb; /* tinted sections, hover fills, soft dividers */
  --heading: #0b2e4f;     /* headings + strong text on the surfaces above */
  --link: #0070ab;        /* brand-blue TEXT/links on the surfaces above (was #007FC2, see --primary) */
  --line: #d8e1e9;        /* input / dropdown borders */
  --line-soft: #e6edf3;   /* card borders, list dividers */
  --font-heading: 'Plus Jakarta Sans', sans-serif;
  --font-body: 'Poppins', sans-serif;
  --radius: 12px;
  /* 2026-09-09: shared "expo-out" curve for scroll reveals / hero motion / card hovers. */
  --ease-out: cubic-bezier(.16, 1, .3, 1);
}

/* 2026-09-04: Plus Jakarta Sans / Poppins have no Thai glyphs, so Thai pages were
   silently falling back to the browser default. Use IBM Plex Sans Thai for both
   headings and body copy whenever the page language is Thai. */
html[lang^="th"]{
  --font-heading: 'IBM Plex Sans Thai', 'Plus Jakarta Sans', sans-serif;
  --font-body: 'IBM Plex Sans Thai', 'Poppins', sans-serif;
}

*{ box-sizing: border-box; }

html{ scroll-behavior: smooth; }

/* 2026-09-09: Lenis inertial smooth-scroll. main.js adds the .lenis* classes only when
   Lenis is actually running (desktop, motion allowed). While it is, it owns scrolling —
   the native `scroll-behavior: smooth` above must be off or the two fight on anchor jumps.
   No-JS / reduced-motion never get these classes, so native smooth scrolling still applies. */
html.lenis, html.lenis body{ height: auto; }
/* 2026-10-03: was .lenis.lenis-smooth — Lenis only adds .lenis-smooth while it is actively
   smoothing, so at rest the native smooth scroll was still on and raced Lenis on a
   load-with-#hash (opening /home/#about landed ~100–250px off) */
html.lenis{ scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent]{ overscroll-behavior: contain; }
.lenis.lenis-stopped{ overflow: hidden; }
.lenis.lenis-smooth iframe{ pointer-events: none; }

body{
  margin: 0;
  font-family: var(--font-body);
  color: var(--text);
  line-height: 1.65;
  background: var(--bg);
  /* 2026-09-04: .site-header is now position:fixed (floats transparently over .hero),
     so it no longer reserves its own space in the flow. Pages that open with .hero pull
     this back off with a matching negative margin so the photo still starts at the true
     top of the viewport; anything without one (the odd page.php/index.php fallback) keeps
     this padding so its content isn't tucked under the header. */
  padding-top: 84px;
}

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

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

h1,h2,h3,h4{
  font-family: var(--font-heading);
  color: var(--heading);
  line-height: 1.25;
  margin: 0 0 .5em;
}

.container{
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 24px;
}

.btn{
  display: inline-block;
  padding: 14px 30px;
  background: var(--primary);
  color: var(--white);
  border-radius: 50px;
  font-weight: 600;
  font-family: var(--font-heading);
  transition: background .2s ease, transform .2s ease;
  border: none;
  cursor: pointer;
}
.btn:hover{ background: var(--primary-dark); color: var(--white); transform: translateY(-2px); }
/* 2026-08-19 Chalermchai Panyasai: ghost button for light backgrounds. */
.btn-outline-primary{ background: transparent; border: 2px solid var(--primary); color: var(--link); }
.btn-outline-primary:hover{ background: var(--primary); color: var(--white); }
/* 2026-09-06: hero CTA — solid accent-yellow pill. Navy label rather than white:
   white on #F9C321 is only 1.6:1 (fails WCAG AA), navy is ~9:1. Its own class so
   the generic .btn (primary blue) is untouched. text-shadow off — it would
   otherwise inherit .hero-inner's shadow and muddy the label. */
.btn-cta{ background: var(--accent); color: var(--navy); text-shadow: none; }
.btn-cta:hover{ background: #e0ab0f; color: var(--navy); }

.eyebrow{
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--link);
  font-weight: 700;
  font-size: 13px;
}

.section{ padding: 80px 0; }
.section-alt{ background: var(--surface-alt); }
.section-title{ text-align: center; max-width: 700px; margin: 0 auto 50px; }
.section-title h2{ font-size: 34px; }

/* 2026-08-19 Chalermchai Panyasai: single-page anchor nav (Home/About/Service/News/Contact) —
   offset so the sticky header doesn't cover the section top when jumping to an anchor. */
#home, #about, #service, #partners, #news, #contact{ scroll-margin-top: 90px; }

/* ---------- About Us — 4-tab slider (Figma node 245:3067 / 245:3373) ----------
   ORPHANED 2026-09-24: superseded by the scroll-driven redesign below
   (.about-scroll-*, Figma node 334:2654) — โต้ง asked for a scroll-interaction
   version with a sticky section nav instead of this click-driven tab slider.
   Left in place per this codebase's "flag, don't delete" convention rather than
   deleted outright, same treatment as the .about-decor watermark this block
   itself replaced back in 2026-09-22.
   2026-09-22: replaces the earlier WFN-quote + 4-column editorial layout (and its
   .about-decor watermark, which doesn't fit this design — that CSS/JS is now
   orphaned, left in place per this codebase's "flag, don't delete" convention).
   2026-09-23 UI refresh (Figma node 253:4014 re-synced): whole layout flipped —
   white section (not the --primary band), horizontal tab-row nav centered above
   the card (was a vertical sidebar), uniform-radius card, and prev/next moved
   outside the card to flank it left/right instead of sitting in its corner. */
.about-slider-section{ background: var(--white); }
.about-slider-section .container{ max-width: 1400px; }

.about-slider{ display: flex; flex-direction: column; align-items: center; gap: 40px; }

/* ---- top tab nav ---- */
.about-nav{
  position: relative; display: flex; flex-direction: row; align-items: flex-start;
  justify-content: center; gap: 48px; width: 100%;
}
/* left/right are set by syncAboutNavConnector() in main.js — the row is centered
   with content-sized (not equal-width) items, so the exact offset to the first/
   last dot's center has to be measured, not guessed as a fixed %. */
.about-nav-connector{
  position: absolute; left: 10%; right: 10%; top: 58px; height: 0;
  border-top: 2px dashed var(--line, #d1d5db); z-index: 0;
}
.about-nav-item{
  position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center;
  gap: 10px; margin: 0; padding: 0; border: none; background: none; cursor: pointer;
}
.about-nav-label{
  font-family: "Poppins", var(--font-heading); font-weight: 300; font-size: 22px;
  color: #6b7280; white-space: nowrap; transition: color .2s ease, font-weight .2s ease;
}
.about-nav-item.is-active .about-nav-label{ font-weight: 700; color: #111827; }
.about-nav-item:hover .about-nav-label{ color: var(--link); }
/* 2026-09-23: re-downloaded from Figma node 253:4014 — the active dot's own asset
   now bakes in a light-blue stroke ring (#6EC8F7, meant for a white background;
   the earlier near-white stroke was tuned for the old blue band). Both icons are
   clean 32x32 squares now, so no odd background-size math is needed. */
.about-nav-dot{
  flex: none; width: 24px; height: 24px; border-radius: 50%;
  background: url('assets/images/icons/about/nav-dot-inactive.svg') no-repeat center / 24px 24px;
  transition: transform .2s ease, box-shadow .2s ease;
}
/* scale() rather than a literal width/height bump — the layout box (and so its
   center, which the connector's top offset and syncAboutNavConnector() both rely
   on) has to stay put; growing the box itself shifts its center down-right since
   flex items here align by their top edge, not their middle. */
.about-nav-item.is-active .about-nav-dot{
  background-image: url('assets/images/icons/about/nav-dot-active.svg');
  transform: scale(1.333);
  box-shadow: 0 0 0 7px rgba(0,112,171,.12);
}

/* ---- slide wrap: prev / card / next ---- */
.about-slide-wrap{ display: flex; align-items: center; gap: 20px; width: 100%; }

/* ---- slide card ---- */
/* Figma pins the card to a fixed height (768px) so all 4 slides read as one
   consistent frame; content stays top-aligned per Figma (shorter panels just
   leave space below), and content taller than the card (Introduction) scrolls
   inside .about-slide-content instead of growing the card. */
.about-slide-card{
  position: relative; flex: 1 1 auto; min-width: 0; display: flex; height: 768px;
  background: var(--white); overflow: hidden; border-radius: 24px;
  box-shadow: 0 24px 60px rgba(4,20,38,.16);
}
.about-slide-content{
  position: relative; flex: 1 1 54%; min-width: 0; height: 100%;
  padding: 48px 64px 48px 48px; overflow-y: auto;
  scroll-behavior: smooth; -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: #d1d5db transparent;
}
.about-slide-content::-webkit-scrollbar{ width: 4px; }
.about-slide-content::-webkit-scrollbar-track{ background: transparent; }
.about-slide-content::-webkit-scrollbar-thumb{ background: #d1d5db; border-radius: 4px; }
.about-slide-photo{ position: relative; flex: 0 0 44%; overflow: hidden; }
.about-slide-photo img{ position: absolute; z-index: 1; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: opacity .25s ease; }
.about-slide-photo img.is-swapping{ opacity: 0; }
/* Figma: soft blue circles show through the cutout photos on Journey / We Believed */
.about-slide-card:has(.about-slide-panel.is-active[data-slide="journey"]) .about-slide-photo::before,
.about-slide-card:has(.about-slide-panel.is-active[data-slide="we-believed"]) .about-slide-photo::before{
  content: ""; position: absolute; z-index: 0; top: -50px; right: 40px;
  width: 340px; height: 340px; border-radius: 50%; background: var(--light-blue); opacity: .7;
}
.about-slide-card:has(.about-slide-panel.is-active[data-slide="journey"]) .about-slide-photo::after,
.about-slide-card:has(.about-slide-panel.is-active[data-slide="we-believed"]) .about-slide-photo::after{
  content: ""; position: absolute; z-index: 0; bottom: -40px; left: 10px;
  width: 220px; height: 220px; border-radius: 50%; background: var(--primary); opacity: .18;
}
/* Figma: the Vision & Mission photo is blended multiply over the white card */
.about-slide-card:has(.about-slide-panel.is-active[data-slide="vision-mission"]) .about-slide-photo img{
  mix-blend-mode: multiply;
}

/* Figma flanks the whole card with prev/next rather than tucking them in a corner.
   chevron.svg already draws its own circle+arrow, so the button stays chromeless. */
.about-slide-arrow{
  flex: none; width: 40px; height: 40px; border-radius: 50%; border: none; background: none;
  padding: 0; cursor: pointer; opacity: .7; transition: opacity .2s ease;
}
.about-slide-arrow img{ width: 100%; height: 100%; display: block; }
.about-slide-prev img{ transform: scaleX(-1); }
.about-slide-arrow:hover:not(:disabled){ opacity: 1; }
.about-slide-arrow:disabled{ opacity: .25; cursor: default; }

/* ---- panels ---- */
.about-slide-panel{ display: none; }
.about-slide-panel.is-active{ display: block; animation: aboutSlideIn .4s var(--ease-out); }
@keyframes aboutSlideIn{ from{ opacity: 0; transform: translateY(10px); } to{ opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce){
  .about-slide-panel.is-active{ animation: none; }
}

.about-lead{ color: var(--link); font-weight: 700; }
.about-slide-text{ display: flex; flex-direction: column; gap: 28px; }
.about-slide-text p{ margin: 0; font-size: 16px; line-height: 1.6; color: #1a1a1a; }

.about-slide-heading{
  margin: 0 0 4px; font-family: "Poppins", var(--font-heading); font-weight: 700;
  font-size: clamp(26px, 3vw, 48px); line-height: 1.2; color: #1a1a1a;
}
.about-slide-stat{
  /* Figma: this now reads in the same near-black as the heading, not the link blue */
  margin: 0 0 28px; font-family: "Poppins", var(--font-heading); font-weight: 800;
  font-size: clamp(42px, 6.5vw, 96px); line-height: 1; color: #1a1a1a;
}
/* Vision & Mission / We Believed use this as their main card heading (no unique
   "hero" line like Introduction/Journey have, so Figma reuses the nav label itself) */
.about-slide-card-title{
  margin: 0 0 32px; font-family: "Poppins", var(--font-heading); font-weight: 800;
  font-size: 40px; line-height: 1.2; color: var(--link);
}

.about-slide-eyebrow-lg{
  margin: 0 0 8px; font-family: var(--font-heading); font-weight: 700;
  font-size: 14px; letter-spacing: 2px; text-transform: uppercase; color: var(--link);
}
.about-slide-eyebrow-sm{
  margin: 0; font-family: var(--font-heading); font-weight: 700;
  font-size: 13px; letter-spacing: 1px; text-transform: uppercase; color: var(--link);
}
.about-slide-name{ margin: 0 0 24px; font-weight: 800; font-size: 26px; line-height: 1.3; color: var(--navy); }
.about-slide-quote{
  margin: 24px 0; padding: 16px 0 16px 20px; border-left: 4px solid var(--light-blue);
  font-family: var(--font-heading); font-weight: 700; font-size: 20px; color: var(--navy);
}
[data-slide="journey"] .about-slide-text + .about-slide-quote{ margin-top: 0; }
[data-slide="journey"] .about-slide-quote + .about-slide-text{ margin-top: 0; }

.about-slide-vm{ margin-bottom: 24px; display: flex; gap: 16px; align-items: baseline; flex-wrap: wrap; }
.about-slide-vm-label{
  margin: 0; font-family: "Poppins", var(--font-heading); font-weight: 800;
  font-size: 30px; text-transform: uppercase; color: var(--link); flex: none;
}
.about-slide-vm-label.is-mission{ color: var(--navy); }
.about-slide-vm-text{
  margin: 0; font-weight: 700; font-size: 15px; line-height: 1.5; letter-spacing: .2px;
  text-transform: uppercase; color: var(--navy); max-width: 420px;
}
.about-slide-vm-divider{ display: block; width: 100%; height: 4px; margin: 0 0 24px; }

/* Figma staggers the belief list left/right — 2nd and 4th items indent further in,
   no bullet marker (the earlier dot-bullet treatment was dropped in this UI pass) */
.about-slide-beliefs{ margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 36px; }
.about-slide-beliefs li{ font-weight: 700; font-size: 19px; line-height: 1.4; color: var(--navy); }
.about-slide-beliefs li:nth-child(2n){ margin-left: 140px; }

/* Between the mobile stack (900px) and a full 1180px container the card had too
   little room, squeezing the heading/stat column into ugly wraps — tighten
   padding/gaps here (font-size itself already fluid via clamp()). */
@media (max-width: 1180px) and (min-width: 901px){
  .about-nav{ gap: 28px; }
  .about-nav-label{ font-size: 19px; }
  .about-slide-content{ padding-left: 32px; padding-right: 40px; }
  .about-slide-beliefs li:nth-child(2n){ margin-left: 80px; }
}

@media (max-width: 900px){
  .about-nav{ flex-wrap: wrap; row-gap: 20px; column-gap: 28px; }
  .about-nav-connector{ display: none; }
  .about-slide-wrap{ gap: 8px; }
  .about-slide-card{ flex-direction: column; height: auto; }
  .about-slide-photo{ flex: none; height: 220px; order: -1; }
  .about-slide-content{
    height: auto; max-height: none; overflow-y: visible; padding: 32px 28px;
  }
  .about-slide-stat{ font-size: 44px; }
  .about-slide-vm{ flex-direction: column; gap: 4px; }
  .about-slide-beliefs li:nth-child(2n){ margin-left: 0; }
}
@media (max-width: 560px){
  .about-nav{ gap: 20px 22px; }
  .about-nav-label{ font-size: 16px; }
  .about-slide-arrow{ width: 32px; height: 32px; }
}

/* ---------- About Us — scroll-driven redesign (Figma node 334:2654) ----------
   2026-09-24: replaces the 4-tab slider above (now orphaned) — โต้ง's ask was
   "interact by scrolling": the four sub-sections (Introduction / Our Journey /
   Vision & Mission / We Believed) stack in normal document flow instead of
   click-swapped panels, and a section nav stays sticky in view the whole time,
   its active dot tracking whichever block is centered in the viewport
   (IntersectionObserver scrollspy — see "About Us scroll-spy" in main.js).
   Reuses the SAME nav-dot-active.svg/nav-dot-inactive.svg icons the old tab
   nav used (โต้ง's earlier call to keep the site's --primary palette instead
   of the Figma's literal #009df0 applies here too).
   Journey (v3, same day): re-synced to the updated Figma — see the Journey
   block below and "Section scroll-fx scrub" in main.js. */
.about-scroll-section{ position: relative; background: var(--bg); overflow: clip; padding-bottom: 0; }
/* 2026-09-25: About Us uses the Figma's Primary/500 blue, nudged just
   enough to pass WCAG (โต้ง: "ปรับให้ผ่านทุกจุด"). Re-pointing --link here
   recolors every brand-blue bit in the section at once: headings, founder
   bar, typing caret, V&M edge, map blinks, active nav label. Contrast:
     #0094de  (≈ #009df0) — 3.3:1 on white, 3.1:1 on the V&M gray: passes for
              large text (the 32–48px bold headings) and graphics (≥3:1)
     #0070ab  (--about-text-blue) — 5.4:1 on white, 5.0:1 on gray, 4.7:1 on
              the team header's blue glow: passes AA for normal-size text
              (We believe lines, intro highlight, nav labels, team eyebrow)
   Also fixed by the same audit: FOUNDER label (#a6d8f2, 1.5:1) → --link,
   and a light navy scrim on the Today band photo for its white text.
   (#009df0 itself is 2.97:1 and the old --primary #007FC2 is 4.36:1 — both
   just under.) Light theme only — dark keeps its own --link (7.9:1). */
html:not([data-theme="dark"]) .about-scroll-section{ --link: #0094de; --about-text-blue: #0070ab; }
html:not([data-theme="dark"]) :is(.about-believe-quote, .about-intro-lead .about-lead, .about-scroll-section .eyebrow){ color: var(--about-text-blue); }
html:not([data-theme="dark"]) .about-journey-founder-role{ color: var(--link); }
/* padding-bottom: 0 — the last block (We believe) carries its own gray band
   down to the section edge, where the gray Our Partners section picks up. */
/* overflow: clip (not hidden) keeps the full-bleed bands and the swirl
   inside the section — no sideways scroll, and the swirl can't spill up into
   the section above — without making the section a scroll container, so the
   sticky section nav inside still sticks. */
.about-scroll-section > .container{ position: relative; z-index: 1; }
/* 2026-09-24: decorative swirl (Figma node 351:3552), bleeding off the left
   edge behind the About Us heading. Inline SVG with currentColor. */
.about-swirl{
  position: absolute; left: -231px; top: 45px; width: 500px; height: 500px;
  color: #d7eaf4; pointer-events: none; z-index: 0;
  transform-origin: 50% 50%; will-change: transform;
}
.about-swirl svg{ display: block; width: 100%; height: 100%; }
html[data-theme="dark"] .about-swirl{ color: var(--surface-alt); }
.about-scroll-section .container{ max-width: 1400px; }

.about-scroll{ position: relative; }
.about-scroll-track{ display: flex; flex-direction: column; gap: 120px; }

/* 2026-09-24: the nav floats over the content instead of taking its own
   column (โต้ง: sticky but independent — don't push the content). It's a
   zero-height sticky box at the top of .about-scroll, pushed to the right
   edge; its items just overflow downward from it, so the track below gets
   the full container width and the nav rides over it while pinned. */
.about-scroll-nav{
  position: sticky; top: 140px; z-index: 5;
  height: 0; width: max-content; margin: 0 0 0 auto; overflow: visible;
  display: flex; flex-direction: column; align-items: flex-end; gap: 32px;
  padding: 0; border: 0; background: none; list-style: none;
}
.about-scroll-nav-item{
  display: flex; align-items: center; gap: 10px; border: 0; background: none;
  padding: 4px 0; cursor: pointer; font-family: inherit; text-align: right;
}
/* inactive labels used to be the blue at 55% opacity (≈2.2:1 — fails);
   now a solid slate gray that passes AA, and the active/hovered label
   turns blue + bold, so the "you are here" cue is kept */
.about-scroll-nav-label{
  font-weight: 300; font-size: clamp(15px, 1.1vw, 18px); color: #5f6b78;
  transition: opacity .2s var(--ease-out), color .2s var(--ease-out), font-weight .2s var(--ease-out);
  white-space: nowrap;
}
html[data-theme="dark"] .about-scroll-nav-label{ color: var(--muted); }
.about-scroll-nav-dot{ flex: 0 0 auto; width: 16px; height: 16px; display: block; }
.about-scroll-nav-item.is-active .about-scroll-nav-label{ font-weight: 700; color: var(--about-text-blue, var(--link)); }
.about-scroll-nav-item:hover .about-scroll-nav-label{ color: var(--about-text-blue, var(--link)); }

/* 2026-09-24: desktop — dots only, parked in the page's right gutter (โต้ง's
   pick) so the nav never sits over content. The negative margin-right pulls
   the zero-height sticky box from the container's right edge out to ~14px
   (plus scrollbar) from the viewport edge (100% here = .about-scroll's width). Vertically
   centered so it stays clear of the floating call/mail buttons bottom-right.
   Labels are absolutely positioned pills to the LEFT of each dot: shown for
   the active section, and on hover/focus for the others. They stay in the
   accessibility tree (opacity only), so the buttons keep their names. */
@media (min-width: 901px){
  .about-scroll-nav{
    top: calc(50vh - 90px); gap: 22px;
    margin-right: calc((100% - 100vw) / 2 + 14px);
  }
  .about-scroll-nav-item{ position: relative; padding: 6px; }
  .about-scroll-nav-label{
    position: absolute; right: calc(100% + 4px); top: 50%;
    transform: translate(6px, -50%);
    padding: 5px 12px; border-radius: 999px;
    background: var(--surface); box-shadow: 0 4px 14px rgba(4, 20, 38, .14);
    font-size: 14px; opacity: 0; pointer-events: none;
    transition: opacity .2s var(--ease-out), transform .2s var(--ease-out);
  }
  /* 2026-09-26 (โต้ง): the active section's pill only flashes up for ~2s when
     the section changes (.is-flash, main.js) — shown permanently it covered
     up to ~170px of content on 1024–1440px screens. Hover/focus still show. */
  .about-scroll-nav.is-flash .about-scroll-nav-item.is-active .about-scroll-nav-label,
  .about-scroll-nav-item:hover .about-scroll-nav-label,
  .about-scroll-nav-item:focus-visible .about-scroll-nav-label{ opacity: 1; transform: translate(0, -50%); }
}

.about-scroll-block{ scroll-margin-top: 140px; }
.about-scroll-heading{
  margin: 0 0 20px; font-weight: 700; font-size: clamp(32px, 3.4vw, 48px);
  line-height: 1.2; color: var(--link); text-align: center;
}

/* Introduction */
.about-intro-kicker{ margin: 0 0 12px; font-weight: 700; font-size: clamp(22px, 2.4vw, 36px); line-height: 1.25; color: var(--heading); text-align: center; }
.about-intro-lead{ max-width: 860px; margin: 0 auto 56px; font-size: clamp(16px, 1.4vw, 24px); line-height: 1.55; color: var(--heading); text-align: center; }
.about-intro-lead .about-lead{ color: var(--link); font-weight: 700; }

/* 2026-09-24 (v3): Figma collage re-synced (node 350:3133) — now layered:
   the truck overlaps the ship's right edge and rises into the plane row.
   Built as two grid rows (not absolute positioning) so longer captions (the
   Thai copy) push things down instead of colliding. Every horizontal size is
   the Figma px value as a % of the 1116px-wide group; % margins resolve
   against the element's own grid area/flex container width, hence the
   different-looking numbers. Each [data-scroll-fx] piece is scrubbed in by
   "Section scroll-fx scrub" in main.js; nothing is hidden without JS. */
.about-intro-collage{ max-width: 1120px; margin: 0 auto; display: flex; flex-direction: column; }
.about-intro-row.is-top{
  /* column %s are of the box INSIDE the 12.12% left padding (980.9px of the
     Figma's 1116): plane 373, gap 22, caption 511 */
  display: grid; grid-template-columns: 38.03% 52.1%; column-gap: 2.24%;
  padding-left: 12.12%; align-items: start;
}
/* bottom row: 3 tracks so the ship (tracks 1-2) and truck column (2-3)
   overlap by the 45px-equivalent middle track. The row's margin-top is the
   ship's 37px gap under the plane row; the truck column's negative margin
   lifts it 75px above the ship, i.e. ~38px up into the plane row. */
.about-intro-row.is-bottom{
  display: grid; grid-template-columns: 51.62% 4.02% 44.36%;
  margin-top: 3.3%; align-items: start;
}
.about-intro-col{ display: flex; flex-direction: column; grid-row: 1; }
.about-intro-row.is-bottom .about-intro-col:first-child{ grid-column: 1 / 3; gap: 17px; }
.about-intro-row.is-bottom .about-intro-col:last-child{ grid-column: 2 / 4; z-index: 1; margin-top: -13.89%; gap: 19px; }
.about-intro-photo{ position: relative; overflow: hidden; border-radius: 8px; background: var(--surface-alt); }
.about-intro-photo img{ display: block; width: 100%; height: 100%; object-fit: cover; transform-origin: center; }
.about-intro-photo.is-plane{ aspect-ratio: 373 / 210; }
.about-intro-photo.is-ship{ aspect-ratio: 621 / 414; }
.about-intro-photo.is-truck{ aspect-ratio: 540 / 303; }
.about-intro-caption{ margin: 0; font-weight: 500; font-size: clamp(15px, 1.67vw, 24px); line-height: 1.34; color: var(--heading); }
.about-intro-caption.is-cap2{ margin-left: 13.15%; width: 69.3%; }
.about-intro-caption.is-cap3{ width: 97.4%; }

/* Journey — title, then the founder → team scene (Figma "Journey sc 1",
   node 382:3513, 2026-09-25), then quote / Today / note. */
.about-journey-title{ margin: 0 0 40px; }

/* Scene 1.1 layout (plain flow = the no-JS / ≤900px / reduced-motion
   version too): name block + 200×267 portrait side by side, bio full
   width below (806px in the Figma). */
.journey-scene{ position: relative; }
.journey-stage{ position: relative; }
.journey-founder{ position: relative; max-width: 806px; margin: 0 auto; padding: 0 0 40px; display: flex; flex-direction: column; align-items: center; gap: 16px; }
.journey-founder-head{ display: flex; align-items: stretch; justify-content: center; width: 100%; max-width: 800px; }
.journey-founder .about-journey-founder{ flex: 0 1 600px; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 16px; padding: 24px 0; } /* Figma 382:3515: vertical padding only */
.journey-founder-head, .journey-founder-copy{ position: relative; z-index: 1; }
/* 2026-09-26: background swirl (Figma 396:3569) — 754px at (373, 98) of the
   806px founder column, i.e. hanging off its right side; clipped by the
   About section. Rotates in slowly and stops once the founder content has
   arrived (.is-swirl-in on .journey-scene, main.js); fades out with the
   founder copy when the scene moves on to the team. */
.journey-swirl{ position: absolute; left: 46.3%; top: 98px; width: 754px; height: 754px; z-index: 0; pointer-events: none; color: #d7eaf4; }
html[data-theme="dark"] .journey-swirl{ color: var(--surface-alt); }
.journey-swirl svg{
  display: block; width: 100%; height: 100%;
  opacity: 0; transform: rotate(-140deg) scale(.86); transform-origin: 50% 50%;
  transition: transform 3.2s cubic-bezier(.16, 1, .3, 1), opacity 1.4s ease;
}
.journey-scene.is-swirl-in .journey-swirl svg{ opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce){
  .journey-swirl svg{ opacity: 1; transform: none; transition: none; }
}
.about-journey-founder-name{
  margin: 0; padding-left: 16px; border-left: 14px solid var(--link);
  font-weight: 600; font-size: clamp(28px, 3.34vw, 48px); line-height: 1.2; color: var(--heading);
}
/* Figma Primary/200 — deliberately pale in the design (light theme uses the
   contrast-safe --link instead, see the About colour block above) */
.about-journey-founder-role{ margin: 0; font-weight: 700; font-size: clamp(22px, 2.5vw, 36px); line-height: 1.22; letter-spacing: .02em; color: #a6d8f2; }
.journey-founder-slot{ flex: 0 0 200px; aspect-ratio: 200 / 267; align-self: flex-start; border-radius: 16px; overflow: hidden; background: var(--surface-alt); }
.journey-founder-slot img{ display: block; width: 100%; height: 100%; object-fit: cover; }
.journey-founder-copy{ width: 100%; display: flex; flex-direction: column; gap: 32px; }
.journey-founder-copy p{ margin: 0; font-weight: 500; font-size: clamp(16px, 1.67vw, 24px); line-height: 1.34; color: var(--heading); }
.journey-founder-copy strong{ font-weight: 400; } /* Figma: the name inside the bio is Poppins Regular */
/* the one element that travels slot → center → small → grid cell (main.js) */
.journey-traveler{
  display: none; position: absolute; left: 0; top: 0; z-index: 6;
  object-fit: cover; border-radius: 16px; pointer-events: none;
  box-shadow: 0 10px 28px rgba(4, 20, 38, .18); will-change: transform, width, height;
}
/* Meet The Team heading (Figma: Medium 20 + SemiBold 48) */
.journey-team-title{ margin: 0 0 40px; text-align: center; }
.journey-team-eyebrow{ margin: 0; font-weight: 500; font-size: 20px; line-height: 28px; color: var(--about-text-blue, var(--link)); }
.journey-team-heading{ margin: 0; font-family: var(--font-body); font-weight: 600; font-size: clamp(28px, 3.34vw, 48px); line-height: 1.2; color: var(--heading); }

/* Pinned mode (desktop, motion OK — main.js adds .is-pinned and sizes the
   scene/stage): the stage sticks under the header while the founder layer
   and the team layer sit stacked on top of each other inside it; JS scales
   each layer to fit short viewports and drives every transform. */
.journey-scene.is-pinned .journey-stage{ position: sticky; }
.journey-scene.is-pinned .about-journey-title{ position: relative; z-index: 1; } /* in flow at the stage top; the founder layer is placed under it by main.js */
.journey-scene.is-pinned .journey-founder,
.journey-scene.is-pinned .about-journey-team{ position: absolute; left: 0; right: 0; top: 0; margin: 0 auto; transform-origin: 50% 0; }
.journey-scene.is-pinned .about-journey-team{ padding: 0; background: none; }
.journey-scene.is-pinned .journey-traveler{ display: block; visibility: hidden; } /* JS shows it only mid-flight */
.journey-scene.is-pinned .journey-team-eyebrow,
.journey-scene.is-pinned .journey-team-heading{ will-change: transform, opacity; }

/* Figma's Neutral/100 gray box — --surface-alt so it flips in dark mode */
.about-journey-quote{ max-width: 904px; margin: 0 auto; padding: 40px 24px; border-radius: 16px; background: var(--surface-alt); text-align: center; }
.about-journey-quote p{
  max-width: 780px; margin: 0 auto; font-weight: 500;
  font-size: clamp(20px, 2.5vw, 36px); line-height: 1.22; color: var(--heading);
}

/* scroll-linked typing ([data-scroll-type], main.js): every grapheme is its
   own span, hidden with visibility (keeps layout fixed — no reflow while
   typing) until the scroll reaches it; the last typed one carries the caret.
   The full sentence is also kept in a visually-hidden copy for screen readers. */
.ma-sr-only{ position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.ma-type-char{ visibility: hidden; }
.ma-type-char.is-typed{ visibility: visible; }
.ma-type-char.is-caret{ position: relative; }
.ma-type-char.is-caret::after{
  content: ""; position: absolute; right: -.08em; top: .12em; bottom: .08em; width: 2px;
  background: var(--link); animation: maTypeCaret 1s steps(1) infinite;
}
@keyframes maTypeCaret{ 50%{ opacity: 0; } }

.about-journey-today{ display: flex; flex-direction: column; align-items: center; text-align: center; }
/* 2026-09-25: "paper stack" — the quote box pins (sticky, within
   .about-journey-stack) and the Today band, stacked above it, slides up over
   it like a sheet of paper; main.js eases the box back/dims it as it's
   covered. The stack ends at the band's bottom, so the pin lets go right as
   the band fully covers the box. */
.about-journey-stack{ position: relative; }
.about-journey-quote-pin{ position: sticky; top: max(96px, 22vh); z-index: 0; transform-origin: 50% 0; will-change: transform, opacity; }
.about-journey-stack .about-journey-today{ position: relative; z-index: 1; }
/* full-bleed band: 100vw wide, centered by the parent's align-items (the
   container is centered, so it lands edge to edge); the section's
   overflow-x: clip absorbs the scrollbar-width overhang. */
.about-journey-today-band{
  width: 100vw; margin-top: 40px; padding: 24px 24px 28px;
  display: flex; flex-direction: column; align-items: center; gap: 32px;
  /* --white (FIXED) not --surface (role token): the text sits on the solid
     --primary band itself, so it must stay white in both themes. */
  background: var(--primary); color: var(--white);
}
/* growth photo behind the band (Figma image 49: 1589×1010, ~105% of the
   1512 band, top-aligned — i.e. only its top strip shows at rest). Flush
   left rather than the Figma's x=10: that offset is off-canvas in the Figma
   frame but showed as a plain strip on our 100vw band. Kept at
   least 170% of the band's height so there's always room to slide it on
   narrow/tall (mobile) bands; main.js moves it up by up to that overflow. */
.about-journey-today-band{ position: relative; overflow: hidden; }
.about-journey-today-bg{
  position: absolute; left: 0; top: 0; width: 105.1%; aspect-ratio: 1589 / 1010; min-height: 170%;
  pointer-events: none; will-change: transform;
}
.about-journey-today-bg img{ display: block; width: 100%; height: 100%; object-fit: cover; }
/* scrim between the photo and the white text — keeps the stats ≥4.5:1
   even where the photo's lighter lower half slides in */
.about-journey-today-band::after{ content: ""; position: absolute; inset: 0; background: rgba(0, 47, 72, .25); pointer-events: none; }
.about-journey-today-heading,
.about-journey-today-stats{ position: relative; z-index: 1; }
.about-journey-today-heading{ margin: 0; font-weight: 700; font-size: clamp(26px, 2.5vw, 36px); line-height: 1.22; color: inherit; }
.about-journey-today-stats{ display: flex; gap: 64px; justify-content: center; align-items: flex-start; flex-wrap: wrap; }
.about-journey-today-stat{ display: flex; flex-direction: column; gap: 14px; min-width: 190px; }
.about-journey-today-stat-label{ font-size: clamp(18px, 1.67vw, 24px); font-weight: 500; opacity: .9; }
/* tabular-nums so the count-up (main.js) doesn't jitter width as digits change */
.about-journey-today-stat-number{ font-weight: 700; font-size: clamp(56px, 6.25vw, 90px); line-height: 1; font-variant-numeric: tabular-nums; }
.about-journey-today-stat-sub{ font-size: clamp(15px, 1.25vw, 18px); font-weight: 500; opacity: .85; }
.about-journey-today-note{ max-width: 1110px; margin: 40px 0 0; font-weight: 700; font-size: clamp(16px, 1.67vw, 24px); line-height: 1.34; color: var(--heading); }

/* Team grid as the close of Journey (was its own <section> after We Believed) */
.about-journey-team{ margin-top: 40px; padding-top: 40px; }
/* 2026-09-26: network particles (canvas) behind the team grid — full-bleed
   and a bit taller than the team block; faded in/out via .is-on (main.js) */
.about-journey-team{ position: relative; }
.team-particles{
  position: absolute; z-index: 0; pointer-events: none;
  top: -80px; bottom: -80px; left: calc(50% - 50vw); width: 100vw; height: calc(100% + 160px);
  opacity: 0; transition: opacity 1s ease;
}
.team-particles.is-on{ opacity: 1; }
.about-journey-team .journey-team-title,
.about-journey-team .team-grid{ position: relative; z-index: 1; }
/* quote / Today / note now follow the team grid */
.journey-scene + .about-journey-stack{ margin-top: 96px; }

/* Vision & Mission (Figma node 351:3712) — gray full-bleed band, then a card:
   photo left (550:697), white VISION half + navy MISSION half stacked right.
   Scroll motion is "Vision & Mission scrub" in main.js; with no JS every
   piece renders in its final state (the accent edge is hidden at rest). */
.about-vm-block{ position: relative; isolation: isolate; padding: 80px 0; }
/* band = the Figma frame's --surface #f5f7fa (a neutral gray — not the
   site's blue-tinted --surface-alt); dark mode keeps --surface-alt */
.about-vm-block::before{
  content: ""; position: absolute; top: 0; bottom: 0; z-index: -1;
  left: calc(50% - 50vw); right: calc(50% - 50vw); background: #f5f7fa;
}
html[data-theme="dark"] .about-vm-block::before{ background: var(--surface-alt); }
.about-vm-block .about-scroll-heading{ margin-bottom: 40px; }
/* 2026-09-25: the card (not the photo) carries the Figma proportion
   (1200×697). It's only a preferred height — if the Mission text wraps
   taller (narrower screens, Thai), the card grows and the photo, which has
   no ratio of its own, stretches with it, so there's never an empty strip
   under the photo. */
.about-vm-card{ display: grid; grid-template-columns: 550fr 650fr; max-width: 1200px; margin: 0 auto; background: var(--surface); overflow: hidden; aspect-ratio: 1200 / 697; }
.about-vm-photo{ position: relative; overflow: hidden; }
/* vision-blocks.webp is pre-cropped to the Figma framing, so it just centers */
.about-vm-photo img{ position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; transform-origin: 50% 100%; }
.about-vm-panels{ display: grid; grid-template-rows: 1fr 1fr; }
.about-vm-panel{ position: relative; display: flex; align-items: center; padding: 40px; }
.about-vm-panel-inner{ position: relative; z-index: 1; width: 100%; }
.about-vm-panel.is-vision .about-vm-panel-inner{ text-align: left; color: #002f48; } /* Figma primary/900 */
html[data-theme="dark"] .about-vm-panel.is-vision .about-vm-panel-inner{ color: var(--heading); }
/* navy half: the fill is a pseudo-element so the scrub can wipe it in with a
   clip-path (--vm-mission-clip) without clipping the text layer above it.
   Figma's Primary/900 + Primary/100, kept literal: the panel is dark in both
   themes, so its light text must not flip. */
.about-vm-panel.is-mission{ color: #d7eaf4; }
.about-vm-panel.is-mission::before{ content: ""; position: absolute; inset: 0; background: #002f48; clip-path: var(--vm-mission-clip, none); }
.about-vm-heading{ margin: 0; font-weight: 800; font-size: clamp(28px, 2.78vw, 40px); line-height: 1.45; text-transform: uppercase; }
.about-vm-copy{ margin: 0; font-weight: 700; font-size: clamp(16px, 1.67vw, 24px); line-height: 1.34; text-transform: uppercase; }
/* logo-swirl bullets (Figma "bullet-mission": 24×42 icon, 8px gap, 4px
   between items) — sized in em so they scale with the text */
.about-vm-list{ margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; font-weight: 700; font-size: clamp(16px, 1.67vw, 24px); line-height: 1.34; text-transform: uppercase; }
.about-vm-list li{ display: flex; align-items: flex-start; gap: 8px; }
.about-vm-bullet{ flex: 0 0 auto; width: 1em; height: 1.75em; margin-top: -.125em; }
/* hard accent line that slashes across the seam during the scrub, then
   retracts — invisible at rest so the finished card matches the Figma */
.about-vm-edge{ position: absolute; left: 0; right: 0; top: 0; height: 6px; z-index: 2; background: var(--link); transform: scaleX(0); transform-origin: left; }

/* We Believe (Figma node 354:3743, re-synced 2026-09-25) — the Figma now
   drops the gray band and the white card: the section sits on the page
   background and the map + statements + logo float freely. The layout box
   (.about-believe-card, kept as the JS hook) = the Figma's map frame plus
   the logo below it: 1274×722. Everything in it is placed by % of that box
   so it scales as one picture, and the statements use container-query
   units (cqw) so their type scales with it too (24px/18px at 1274).
   It still sits right after V&M (the negative margin cancels the track gap,
   so the heading is 40px below V&M's band like the stacked Figma frames).
   Motion: "We Believe scrub" in main.js; nothing is hidden without JS. */
.about-believe-block{ position: relative; isolation: isolate; padding: 40px 0 70px; background: var(--bg); }
.about-vm-block + .about-believe-block{ margin-top: -120px; }
.about-believe-block .about-scroll-heading{ margin-bottom: 70px; }
.about-believe-card{
  position: relative; max-width: 1274px; margin: 0 auto; aspect-ratio: 1274 / 722;
  container-type: inline-size;
}
/* the exported image is a touch narrower than the Figma's 1274×632 map box,
   so it's stretched to that box (aspect-ratio + default object-fit: fill) —
   the blink coordinates are measured against the same box */
.about-believe-map{ position: absolute; left: 0; top: 0; width: 100%; height: auto; aspect-ratio: 1274 / 632; pointer-events: none; }
html[data-theme="dark"] .about-believe-map{ opacity: .18; }
/* random twinkling blue dots (โต้ง's ask) — same box as the map image;
   main.js drops short-lived .about-believe-blink spans onto real dot
   centers. Blink size = one map dot (9.3px of the 1274px-wide map). */
.about-believe-blinks{ position: absolute; left: 0; top: 0; width: 100%; aspect-ratio: 1274 / 632; pointer-events: none; }
.about-believe-blink{
  position: absolute; width: .73%; aspect-ratio: 1; border-radius: 50%;
  background: var(--link); transform: translate(-50%, -50%) scale(.4); opacity: 0;
  box-shadow: 0 0 0 0 rgba(0, 157, 240, .45);
  animation: aboutBelieveBlink 1.8s var(--ease-out) forwards;
}
@keyframes aboutBelieveBlink{
  0%  { opacity: 0; transform: translate(-50%, -50%) scale(.4); box-shadow: 0 0 0 0 rgba(0, 157, 240, .45); }
  25% { opacity: 1; transform: translate(-50%, -50%) scale(1.15); }
  60% { opacity: 1; box-shadow: 0 0 0 7px rgba(0, 157, 240, 0); }
  100%{ opacity: 0; transform: translate(-50%, -50%) scale(.9); box-shadow: 0 0 0 7px rgba(0, 157, 240, 0); }
}
/* Figma Group 14: 200×200 at (518, 186) of the 1274×722 box */
.about-believe-cycle{ position: absolute; left: 40.67%; top: 25.76%; width: 15.7%; aspect-ratio: 1; z-index: 1; }
/* ring + mark are both exported in the icon's own 200×200 frame (Figma
   Group 14), so they overlay 1:1 and the ring's circle is centered on the
   box — it spins about 50% 50% without wobbling. The mark's own center in
   that frame is (100.4, 101.6), hence its transform-origin. */
.about-believe-ring,
.about-believe-mark{ position: absolute; inset: 0; width: 100%; height: 100%; }
.about-believe-ring{ transform-origin: 50% 50%; }
.about-believe-mark{ transform-origin: 50.2% 50.8%; }
.about-believe-list{ margin: 0; padding: 0; list-style: none; }
.about-believe-quote{
  position: absolute; z-index: 2; left: calc(var(--cx) - var(--w) / 2); top: var(--top); width: var(--w);
  text-align: center; color: var(--link);
}
/* centers of the Figma's statement boxes (Frame 128: two rows, 149px /
   284px apart, 324px between row tops) */
.about-believe-quote.is-tl{ --cx: 20.62%; --top: 13.02%; --w: 38%; }
.about-believe-quote.is-tr{ --cx: 70.51%; --top: 13.02%; --w: 50%; }
.about-believe-quote.is-br{ --cx: 74.59%; --top: 57.89%; --w: 38%; }
.about-believe-quote.is-bl{ --cx: 23.45%; --top: 57.89%; --w: 38%; }
.about-believe-quote-inner{ display: flex; flex-direction: column; align-items: center; }
/* 2026-09-27 (Figma 362:2295): two-tone statements — body Primary/700
   #006499, keyword Primary/400 #29b5ff exactly as designed — โต้ง exempted
   this section from the WCAG pass (keyword is 2.3:1 on white); dark theme
   uses a pale body (#a6d8f2) and the same keyword. */
.about-believe-card{ --believe-body: #006499; --believe-key: #29b5ff; }
html[data-theme="dark"] .about-believe-card{ --believe-body: #a6d8f2; --believe-key: #29b5ff; }
.about-believe-line{ font-weight: 500; font-size: max(12px, 1.413cqw); line-height: 1.35; color: var(--believe-body); }
.about-believe-line strong{ color: var(--believe-key); }
.about-believe-line strong{ font-weight: 700; font-size: max(19px, 1.884cqw); } /* ≥19px bold = WCAG "large text" at every width (keyword colour is 3:1-tuned) */
/* Figma Frame 6: 272×90 at (501, 632) */
.about-believe-logo{ position: absolute; left: 39.32%; top: 87.53%; width: 21.35%; height: auto; }

@media (max-width: 1180px){
  .about-scroll-nav-label{ font-size: 15px; }
}

@media (max-width: 900px){
  /* 2026-09-25 (โต้ง): tablet + phone use the same right-edge dot rail as
     desktop, dots only (no labels), instead of the full-width bar. Same
     zero-height sticky box, pulled to 8px from the viewport edge; the dots
     sit on a small translucent pill so they stay visible over content.
     Items keep 6px padding → 28px tap targets. Labels are visually hidden
     but still name the buttons for screen readers. */
  .about-scroll-nav{
    top: calc(50vh - 70px); gap: 0;
    margin-right: calc((100% - 100vw) / 2 + 8px);
  }
  .about-scroll-nav::before{
    content: ""; position: absolute; right: 0; top: -4px; width: 28px; height: calc(4 * 28px + 8px);
    border-radius: 999px; background: var(--surface); /* 2026-10-03: fallback for browsers without color-mix() (Safari < 16.2, Firefox < 113) */
    background: color-mix(in srgb, var(--surface) 82%, transparent);
    box-shadow: 0 2px 10px rgba(4, 20, 38, .12); pointer-events: none;
  }
  .about-scroll-nav-item{ position: relative; padding: 6px; }
  .about-scroll-nav-label{
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  }
  .about-scroll-track{ gap: 88px; }
  .about-intro-collage{ gap: 32px; }
  .about-intro-row.is-top{ grid-template-columns: 1fr 1fr; column-gap: 24px; padding-left: 0; }
  .about-intro-row.is-bottom{ grid-template-columns: 1.3fr 1fr; column-gap: 24px; margin-top: 0; }
  .about-intro-row.is-bottom .about-intro-col:first-child,
  .about-intro-row.is-bottom .about-intro-col:last-child{ grid-column: auto; margin-top: 0; gap: 16px; }
  .about-intro-caption.is-cap2,
  .about-intro-caption.is-cap3{ margin-left: 0; width: auto; }
  .journey-founder{ padding: 0 0 16px; }
  .journey-founder .about-journey-founder{ padding: 0 16px 0 0; }
  .journey-founder-slot{ flex-basis: 30%; max-width: 200px; }
  .about-journey-quote{ padding: 32px 20px; }
  .about-vm-block{ padding: 56px 0; }
  .about-vm-card{ grid-template-columns: 1fr; aspect-ratio: auto; }
  .about-vm-photo{ aspect-ratio: 16 / 10; }
  .about-vm-photo img{ object-position: 50% 45%; }
  .about-vm-panel{ padding: 32px 24px; }
  .about-believe-block{ padding: 32px 0 56px; }
  .about-believe-block .about-scroll-heading{ margin-bottom: 24px; }
  .about-vm-block + .about-believe-block{ margin-top: -88px; }
  .about-believe-card{ aspect-ratio: auto; display: flex; flex-direction: column; align-items: center; gap: 24px; padding: 32px 20px; }
  .about-believe-map,
  .about-believe-blinks{ left: 0; top: 50%; width: 100%; transform: translateY(-50%); }
  .about-believe-map{ opacity: .6; }
  .about-believe-cycle{ position: relative; left: auto; top: auto; width: 140px; }
  .about-believe-list{ position: relative; z-index: 2; display: flex; flex-direction: column; gap: 20px; width: 100%; }
  .about-believe-quote{ position: static; width: auto; }
  .about-believe-line{ font-size: 15px; }
  .about-believe-line strong{ font-size: 19px; }
  .about-believe-logo{ position: relative; left: auto; top: auto; width: min(200px, 60%); }
  .about-swirl{ width: 300px; height: 300px; left: -150px; top: 30px; }
  .about-journey-team{ margin-top: 32px; padding-top: 32px; }
  .journey-scene + .about-journey-stack{ margin-top: 72px; }
  .journey-team-eyebrow{ font-size: 17px; line-height: 24px; }
}

@media (max-width: 560px){
  /* 2026-09-26 (โต้ง): phones stack the founder — portrait on top, centered,
     then the name + FOUNDER full width below. Side by side, the one-word
     "Phattharakasemsi" (~250px at 28px) couldn't fit the ~190px beside it. */
  .journey-founder-head{ flex-direction: column; align-items: center; gap: 24px; }
  .journey-founder-slot{ order: -1; flex: 0 0 auto; width: 160px; max-width: none; align-self: center; }
  .journey-founder .about-journey-founder{ flex: 0 0 auto; width: 100%; padding: 0; gap: 12px; }
  .journey-swirl{ left: 30%; top: 40px; width: 420px; height: 420px; }
  .about-intro-row.is-top,
  .about-intro-row.is-bottom{ grid-template-columns: 1fr; row-gap: 16px; }
  .about-intro-row.is-bottom{ row-gap: 32px; }
  .about-intro-row.is-bottom .about-intro-col:first-child,
  .about-intro-row.is-bottom .about-intro-col:last-child{ grid-row: auto; }
  .about-journey-today-stats{ gap: 28px; }
  .about-journey-today-stat{ min-width: 140px; }
}

/* ---------- Our Partners (Figma node 369:3369) ----------
   2026-09-25: logo wall right after About Us. Shares the gray band color of
   Vision & Mission / We believe, and About Us drops its bottom padding (see
   .about-scroll-section below) so the bands join with no white strip. Cards
   stay white in dark mode too — the carrier logos are drawn for a light
   background. 5 × 200px columns at full width (Figma), shrinking evenly
   below that, then 3 and 2 columns. Motion: shared [data-scroll-fx] scrub. */
.partners-section{ padding: 40px 0 80px; background: var(--surface-alt); }
.partners-heading{
  margin: 0 0 40px; text-align: center; font-weight: 700;
  font-size: clamp(32px, 3.34vw, 48px); line-height: 1.2; color: var(--heading);
}
.partners-grid{
  list-style: none; margin: 0 auto; padding: 8px; max-width: 1150px;
  display: grid; grid-template-columns: repeat(5, minmax(0, 200px)); gap: 24px; justify-content: center;
}
.partners-card{
  height: 100px; padding: 16px; display: flex; align-items: center; justify-content: center;
  background: var(--white); border: 1px solid #e5e7eb; border-radius: 8px;
  will-change: transform, opacity; /* 2026-10-03: smooth zoom scrub, no repaint shimmer */
}
/* 2026-10-03: --logo-h (inline, per card) = a shorter logo height from the Figma */
.partners-card img{ display: block; width: 100%; max-width: 166px; height: var(--logo-h, 50px); object-fit: contain; }
@media (max-width: 900px){
  .partners-grid{ grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
}
@media (max-width: 560px){
  .partners-section{ padding: 32px 0 56px; }
  .partners-heading{ margin-bottom: 24px; }
  .partners-grid{ grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; padding: 0; }
  .partners-card{ height: 84px; padding: 12px; }
  .partners-card img{ height: calc(var(--logo-h, 50px) * 0.8); }
}

/* ---------- Contact (Figma node 359:2674) ----------
   2026-09-25: title + subtitle, full-width 400px live Google Map (consent-
   gated, see page-home.php / "Contact map" in main.js), contact lines, pill
   CTA. The Figma's fixed slate grays (#64748b / #475569) are mapped onto
   theme tokens so the block still reads in dark mode. */
.contact-section{ padding: 40px 0 48px; background: var(--bg); text-align: center; }
.contact-section .container{ max-width: 1440px; }
@media (min-width: 901px){ .contact-section .container{ padding-left: 40px; padding-right: 40px; } }
.contact-heading{ margin: 0; font-weight: 700; font-size: clamp(32px, 3.34vw, 48px); line-height: 1.2; color: var(--heading); }
.contact-sub{ margin: 8px 0 8px; font-weight: 500; font-size: clamp(17px, 1.39vw, 20px); line-height: 1.4; color: var(--link); }
/* 2026-10-03: will-change keeps the map on its own layer — scrubbing transform/opacity
   on the Google Maps iframe every scroll frame re-rasterized it and it flickered */
.contact-map{ position: relative; height: 400px; background: var(--surface-alt); overflow: hidden; will-change: transform, opacity; }
.contact-map iframe{ position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
.contact-map-placeholder{
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 24px; color: var(--heading);
}
.contact-map-placeholder .icon-svg{ width: 40px; height: 40px; color: var(--link); }
.contact-map-placeholder p{ margin: 0; max-width: 420px; font-size: 14px; line-height: 1.5; opacity: .8; }
.contact-map-actions{ display: flex; align-items: center; gap: 20px; flex-wrap: wrap; justify-content: center; }
.contact-map-open{ font-size: 14px; font-weight: 600; color: var(--link); }
.contact-map.is-loaded .contact-map-placeholder{ display: none; }
/* 2026-09-27: /contact-us/ — full-width map band right under the hero */
.contact-page-map .contact-map{ height: 420px; }
@media (max-width: 640px){ .contact-page-map .contact-map{ height: 300px; } }
.contact-details{ max-width: 832px; margin: 0 auto; padding: 18px 0 26px; display: flex; flex-direction: column; gap: 6px; }
.contact-details p{ margin: 0; font-size: max(12px, .84vw); line-height: 1.6; color: var(--heading); }
.contact-address{ max-width: 576px; margin: 0 auto !important; opacity: .72; }
/* was opacity .85 on the whole line, which also faded the links to 3.5:1 —
   soften only the plain text instead, so links keep full colour */
.contact-details .contact-line{ color: var(--heading); color: color-mix(in srgb, var(--heading) 85%, var(--bg)); font-weight: 500; }
.contact-details a{ color: var(--link); }
.contact-cta{ display: flex; justify-content: center; }
.contact-cta-btn{
  display: inline-flex; align-items: center; justify-content: center; padding: 12px 32px; border-radius: 9999px;
  background: var(--primary); color: var(--white); font-weight: 700; font-size: 16px; line-height: 1.5;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .1), 0 1px 2px -1px rgba(0, 0, 0, .1);
  transition: background-color .2s var(--ease-out), transform .2s var(--ease-out);
}
.contact-cta-btn:hover{ background: var(--primary-dark); color: var(--white); transform: translateY(-1px); }
@media (max-width: 560px){
  .contact-map{ height: 320px; }
  .contact-details p{ font-size: 13px; }
}

/* ---------- Team / employee showcase ---------- */
/* 2026-09-24: dense photo mosaic, no names/captions (data not available yet) — a
   wall of faces rather than a roster.
   2026-09-24 (v3): scroll-SCRUBBED entrance, not scroll-TRIGGERED — โต้ง wanted
   each photo's scale/position to be a direct function of scroll position (not a
   fixed-duration transition fired once by IntersectionObserver), finishing
   exactly when the section's top edge reaches the header. Every tile flies in
   from its own random direction and converges on its own grid cell as scroll
   progress goes 0→1; ~6 random tiles additionally overshoot bigger before
   settling. This is the same technique as the old .about-decor parallax
   (updateAboutDecor in main.js: progress computed from getBoundingClientRect()
   on every scroll frame, applied straight to inline transform/opacity — no CSS
   transition, since a transition would add lag between scroll input and the
   visual response). See "Team grid scroll-scrub" in main.js.
   No CSS states to define here beyond the resting look — JS drives
   transform/opacity directly via inline styles while animating, and clears
   them (falling back to this rest state) once a pass finishes or before JS
   has run at all (no-JS / reduced-motion / crawler renders always get this). */
/* 2026-09-24: soft blue radial glow behind the section, top-center — โต้ง
   supplied this as a Tailwind arbitrary-value div (absolute, full-viewport,
   z-[-2]). Ported to plain CSS as a background-image on the section itself
   instead: same visual (the gradient box's own position/size already default
   to the element's box), without an extra DOM node or z-index stacking to
   manage on a site that isn't Tailwind-based.
   var(--bg) not var(--white) — --white is a FIXED token that never changes
   with theme, and this site is dark-mode-live right now; a literal white
   section background sat in the middle of a dark page washed out the
   (correctly theme-aware) heading text against it. --bg picks up the same
   html[data-theme="dark"] override everything else on the page uses. */
.team-section{
  background-color: var(--bg);
  background-image: radial-gradient(100% 50% at 50% 0%, rgba(0,163,255,.13) 0%, rgba(0,163,255,0) 50%, rgba(0,163,255,0) 100%);
}

/* grid-auto-flow:dense so the regular tiles pack around the explicitly-
   placed .is-hero tile instead of leaving a gap where it "should" have been
   in plain DOM order.
   2026-09-24 (v10): โต้ง asked for every row to hold an equal number of
   photos — the last row was short (8 of 9) since 44 doesn't divide evenly
   by 9. Column counts are now divisors of the total tile count (44) at
   every breakpoint so grid-auto-flow never leaves a partial row: 11 cols
   on desktop (4 even rows), 4 cols on tablet/mobile (11 even rows). This
   needs re-picking whenever the total tile count changes (see hero-
   placement comment below for the row math). */
/* 2026-09-28: 38 tiles after โต้ง removed 6 people — no longer divisible into
   even rows, so the grid is a centered flex-wrap: 13 per row on desktop
   (13/13/12, last row centered), 4 on tablet/phone (last 2 centered). The
   founder tile is placed with CSS `order` (--hero-k / --hero-k-sm, computed
   in page-home.php for the middle cell); staff tiles carry even orders.
   (Tried and reverted the same day: 10 cols, a tall 2-row founder tile at
   13×3, and 19×2 — see memory.) */
.team-grid{
  --cols: 13; --gap: 6px;
  display: flex; flex-wrap: wrap; justify-content: center; gap: var(--gap);
}
.team-grid > .team-photo{ flex: 0 0 calc((100% - (var(--cols) - 1) * var(--gap)) / var(--cols)); }
.team-photo{
  position: relative; aspect-ratio: 1 / 1; overflow: hidden; border-radius: 6px;
  background: var(--surface-alt);
  opacity: 1; /* no-JS / reduced-motion / crawler default: always visible */
}
/* once JS/motion/IntersectionObserver are confirmed available (same gate as
   .reveal elsewhere), tiles default to invisible until the scroll handler's
   first teamUpdate() call sets their real progress-driven opacity/transform. */
/* 2026-09-26: scoped to .team-anim (added by main.js only on desktop ≥901px) —
   tablets/phones show the grid as-is, no fly-in (โต้ง) */
html.team-anim .team-photo{ opacity: 0; }
/* 2026-09-26 perf: compositor hints only while the fly-in is running (main.js) */
.team-grid.is-animating .team-photo{ will-change: transform, opacity; }
.team-photo img{
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .4s var(--ease-out);
}
.team-photo:hover img{ transform: scale(1.08); }

/* 2026-09-24 (v5): center.webp — the one photo โต้ง wants given priority, but
   (as of this pass) at the SAME size as every other tile, not spanning extra
   cells like before — its priority is carried entirely by timing/sequence in
   main.js now (delayed start, settles first, slow eased catch-up), not by
   being physically bigger. Still placed dead center via explicit grid-column/
   grid-row, just as a plain 1x1 cell.
   2026-09-24 (v10): column counts changed to divisors of the 44-cell total
   (see .team-grid comment above) so every row is full — 11x4 on desktop
   (col 6, row 3 = center), 4x11 on tablet and mobile (col 2, row 6 = center;
   tablet and mobile now share the same column count/hero cell, they only
   differ in tile pixel size and gap/border-radius). These numbers assume
   exactly 43 non-hero tiles (44 total cells) — revisit both this and the
   .team-grid column counts if that count changes. Border-radius/shadow are
   back to matching .team-photo's own defaults so an equally-sized tile
   doesn't look inconsistent next to its neighbors; the shadow alone stays
   as a subtle "still important" accent. */
.team-photo.is-hero{
  order: var(--hero-k, 0);
  box-shadow: 0 8px 20px rgba(4,20,38,.16);
  /* 2026-09-24 (v6): back to the default center-center scale anchor (โต้ง's
     ask) — it still always rises in from straight below (main.js), but now
     grows evenly from its own middle rather than from a fixed bottom point. */
  transform-origin: center;
}

@media (max-width: 900px){
  .team-grid{ --cols: 4; --gap: 5px; }
  .team-photo{ border-radius: 5px; }
  .team-photo.is-hero{ order: var(--hero-k-sm, 0); }
}
@media (max-width: 560px){
  .team-grid{ --gap: 4px; }
  .team-photo{ border-radius: 4px; }
}

/* ---------- Service (single-page, malliance.com content) ---------- */
/* 2026-09-18: Home's Service section heading — plain heading (matched to Figma node
   197:3654) ahead of the .transport-cards row shared with page-services.php. Replaced
   the old WE COLLECT/STORE/SHIP zoom banner, whose CSS/JS has since been removed. */
.service-tagline{ text-align: center; margin: 0 0 40px; }
.service-tagline h3{ font-size: 32px; margin: 0 0 8px; }
.service-tagline p{ color: var(--muted); font-size: 18px; margin: 0; }
.ma-capability-grid{
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; text-align: center;
}
.ma-capability-item .icon-svg{ width: 30px; height: 30px; color: var(--muted); }
.ma-capability-item p{ margin: 10px 0 0; font-size: 13px; font-weight: 600; color: var(--heading); }
/* 2026-09-18: /services/ swapped this grid's icons for the Figma pictograms (its own
   dark-slate fill baked in) — Home keeps the plain .icon-svg stroke set above untouched. */
.ma-capability-icon{ height: 36px; width: auto; margin: 0 auto; }

/* ---------- News empty state (no posts published yet) ---------- */
.ma-news-placeholder{ font-size: 17px; color: var(--muted); margin: 30px 0 0; text-align: center; }

/* ---------- Header ---------- */
/* 2026-09-04: transparent-over-the-hero-photo at the top of the page, solid white once
   scrolled — main.js toggles .scrolled past a small scroll threshold. Every content page
   (page-home/about/services/faqs/contact) opens with a full-bleed .hero photo directly
   under the header, so floating a transparent bar over it needs the header out of normal
   flow (fixed, not sticky) — otherwise it'd just reserve its own white bar above the photo
   instead of overlapping it. */
.site-header{
  position: fixed; top: 0; left: 0; right: 0; width: 100%; z-index: 100;
  background: transparent; box-shadow: none;
  transition: background-color .3s ease, box-shadow .3s ease;
}
.site-header.scrolled{
  background: var(--surface);
  box-shadow: 0 2px 10px rgba(0,0,0,.06);
}
.site-header .container{
  display: flex; align-items: center; justify-content: space-between;
  padding-top: 14px; padding-bottom: 14px;
}
.site-logo{ display: flex; align-items: center; gap: 12px; }
/* 2026-09-04: combined icon+wordmark lockup (one wide image) replaces the old
   separate icon <img> + text <span>. Sized by height since it's a ~6:1 wide image,
   not a square icon. Two pre-coloured versions, swapped by .scrolled: the source file
   has "Maritime" as pure white — reads fine over a photo, but is invisible once the
   header goes solid white on scroll, so Logo-Head-2_navy.png (that word recoloured to
   navy) is used there instead of trying to fake it with a CSS filter. */
.logo-lockup{ height: 42px; width: auto; }
.logo-lockup-color{ display: none; }
.site-header.scrolled .logo-lockup-white{ display: none; }
.site-header.scrolled .logo-lockup-color{ display: block; }
.main-nav ul{ list-style: none; display: flex; gap: 34px; margin: 0; padding: 0; }
.main-nav a{
  color: var(--white); font-weight: 600; font-family: var(--font-heading); font-size: 15px;
  /* 2026-09-04: the lighter overlay means the header sometimes sits over a genuinely
     bright patch of the photo (pale sky, light metal) — plain white text can lose all
     contrast right there. A shadow gives it an edge regardless of what's behind it. */
  text-shadow: 0 1px 5px rgba(0,0,0,.4);
  transition: color .3s ease, text-shadow .3s ease;
}
.main-nav a:hover, .main-nav .current-menu-item > a{ color: var(--accent); }
.site-header.scrolled .main-nav a{ color: var(--heading); text-shadow: none; }
.site-header.scrolled .main-nav a:hover, .site-header.scrolled .main-nav .current-menu-item > a{ color: var(--link); }

.header-actions{ display: flex; align-items: center; gap: 10px; }
.header-actions a{
  width: 42px; height: 42px; border-radius: 50%;
  background: rgba(255,255,255,.18); color: var(--white);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px; flex-shrink: 0;
  box-shadow: 0 1px 6px rgba(0,0,0,.18);
  transition: background-color .3s ease, color .3s ease, box-shadow .3s ease;
}
.header-actions a .icon-svg{ filter: drop-shadow(0 1px 3px rgba(0,0,0,.4)); transition: filter .3s ease; }
.header-actions a:hover{ background: var(--white); color: var(--primary); }
.site-header.scrolled .header-actions a{ background: var(--surface-alt); color: var(--heading); box-shadow: none; }
.site-header.scrolled .header-actions a:hover{ background: var(--primary); color: var(--white); }
.site-header.scrolled .header-actions a .icon-svg{ filter: none; }

/* 2026-08-19 Chalermchai Panyasai: outline SVG icons — color inherits from the parent link. */
.icon-svg{ width: 18px; height: 18px; }

/* 2026-08-18 Chalermchai Panyasai: language dropdown (was plain TH/EN links). */
.lang-switcher{ position: relative; font-family: var(--font-heading); font-weight: 700; font-size: 13px; flex-shrink: 0; }
.lang-toggle{
  display: flex; align-items: center; gap: 8px; height: 42px; padding: 0 14px;
  border: 1px solid rgba(255,255,255,.45); border-radius: 21px; background: rgba(255,255,255,.14); color: var(--white);
  font: inherit; cursor: pointer; box-shadow: 0 1px 6px rgba(0,0,0,.18);
  text-shadow: 0 1px 4px rgba(0,0,0,.4);
  transition: background-color .3s ease, color .3s ease, border-color .3s ease, box-shadow .3s ease, text-shadow .3s ease;
}
.lang-toggle:hover{ background: rgba(255,255,255,.26); border-color: var(--white); }
.site-header.scrolled .lang-toggle{
  border-color: var(--line-soft); background: var(--surface); color: var(--heading); box-shadow: 0 2px 6px rgba(11,46,79,.06);
  text-shadow: none;
}
.site-header.scrolled .lang-toggle:hover{ border-color: var(--primary); color: var(--link); }
.lang-flag{ width: 22px; height: 16px; border-radius: 3px; object-fit: cover; flex-shrink: 0; }
.lang-caret{ font-size: 9px; line-height: 1; color: inherit; opacity: .75; transition: transform .15s ease; }
.lang-switcher.open .lang-caret{ transform: rotate(180deg); }

.lang-menu{
  display: none; position: absolute; top: calc(100% + 10px); right: 0; z-index: 20;
  width: max-content; min-width: 150px; max-width: calc(100vw - 32px);
  padding: 6px; background: var(--surface); border-radius: 14px;
  box-shadow: 0 12px 28px rgba(11,46,79,.16);
}
.lang-menu::before{
  content: ""; position: absolute; top: -5px; right: 17px;
  width: 10px; height: 10px; background: var(--surface);
  border-radius: 2px; transform: rotate(45deg);
}
.lang-switcher.open .lang-menu{ display: block; }
.lang-menu a{
  /* 2026-08-18: explicit width/height/background/font-size reset — without them
     .header-actions a (the 42x42 circular icon-button rule) leaks in here since
     .lang-menu is nested inside .header-actions with equal CSS specificity. */
  display: flex; align-items: center; justify-content: flex-start; gap: 10px;
  width: auto; height: auto; padding: 9px 10px; border-radius: 10px;
  background: transparent; color: var(--heading); font-size: 14px; font-weight: 600; white-space: nowrap;
}
.lang-menu a:hover{ background: var(--surface-alt); }
.lang-menu a.is-current{ background: var(--surface-alt); }
.lang-menu .lang-name{ flex: 1; }
.lang-menu .lang-check{ color: #1a9c5c; font-weight: 700; flex-shrink: 0; }

.menu-toggle{
  display: none; background: var(--primary); border: none; width: 44px; height: 44px;
  border-radius: 6px; color: var(--white); font-size: 20px; cursor: pointer; flex-shrink: 0;
}

/* 2026-08-19 Chalermchai Panyasai: mobile nav slot for the language switcher (main.js moves it here). */
.main-nav-lang:empty{ display: none; }
.main-nav-lang{ margin-top: 18px; padding: 18px 16px 16px; border-top: 1px solid var(--line-soft); }
/* 2026-08-19: full-width "select box" style — toggle + dropdown read as one attached
   bordered box (like a country/currency picker), not a floating card with a shadow. */
.main-nav-lang .lang-switcher{ display: block; width: 100%; }
.main-nav-lang .lang-toggle{
  width: 100%; justify-content: flex-start; height: auto; padding: 16px 18px;
  border: 1px solid var(--line); border-radius: 10px; box-shadow: none;
  /* the base toggle is white-on-transparent (made for the hero); this box sits on the white
     mobile menu panel, so it needs its own dark-on-white colours regardless of scroll state. */
  background: var(--surface); color: var(--heading); text-shadow: none;
}
.main-nav-lang .lang-toggle:hover{ background: var(--surface-alt); border-color: var(--primary); color: var(--heading); }
/* 2026-08-19: keep flag+label left-aligned, push only the caret to the right (bigger, per reference). */
.main-nav-lang .lang-caret{ margin-left: auto; font-size: 16px; }
.main-nav-lang .lang-switcher.open .lang-toggle{
  border-radius: 10px 10px 0 0; border-bottom-color: transparent;
}
.main-nav-lang .lang-menu{
  position: static; display: none; width: 100%; max-width: none;
  margin: 0; padding: 0; border: 1px solid var(--line); border-top: none;
  border-radius: 0 0 10px 10px; box-shadow: none;
}
.main-nav-lang .lang-switcher.open .lang-menu{ display: block; }
.main-nav-lang .lang-menu::before{ display: none; }
.main-nav-lang .lang-menu a{
  border-radius: 0; padding: 14px 16px; border-bottom: 1px solid var(--line-soft);
}
.main-nav-lang .lang-menu a:last-child{ border-bottom: none; }

/* 2026-08-19 sticky call/email buttons. 2026-09-20: shown on every screen size as a floating stack in
   the bottom-right corner (was mobile-only, bottom-left; desktop had duplicate round icons in the
   header, now removed). Bottom-right also clears the cookie "reopen" tab, which lives bottom-left. */
.contact-fab{
  display: flex; position: fixed; right: 16px; bottom: calc(16px + env(safe-area-inset-bottom, 0px)); z-index: 40;
  flex-direction: column; gap: 10px;
}
.contact-fab a{
  width: 48px; height: 48px; border-radius: 50%;
  background: var(--primary); color: var(--white);
  display: flex; align-items: center; justify-content: center;
  font-size: 19px; box-shadow: 0 6px 16px rgba(11,46,79,.28);
  transition: background-color .2s ease, transform .25s var(--ease-out);
}
.contact-fab a:hover{ background: var(--primary-dark); transform: translateY(-2px); }
.contact-fab .icon-svg{ width: 21px; height: 21px; }
@media (min-width: 769px){
  .contact-fab{ right: 24px; bottom: 24px; }
}
@media (prefers-reduced-motion: reduce){
  .contact-fab a{ transition: background-color .2s ease; }
  .contact-fab a:hover{ transform: none; }
}

/* ---------- Landing gate (regional splash page) ---------- */
/* 2026-08-19 Chalermchai Panyasai: hide the normal site chrome on the gateway page —
   it's a standalone full-screen splash, not a page within the regular site nav. */
/* 2026-09-08: the Welcome / regional-gate styles now live inline in front-page.php
   (search "ma-welcome-css") so the page can be deployed on its own without touching
   this file. Fold them back in here when the full redesign ships. */

/* ---------- Hero ---------- */
.hero{
  position: relative;
  min-height: 100vh;
  /* svh ("small viewport height") excludes the address bar that mobile browsers show/hide
     on scroll — 100vh alone measures the LARGEST possible viewport, so on mobile the hero
     would be taller than the screen when the address bar is showing, and you'd never quite
     see the bottom of it (buttons cut off) until the bar auto-hides on scroll. */
  min-height: 100svh;
  margin-top: -84px; /* cancels body's header-safety padding-top so the photo hits true y:0 */
  display: flex; align-items: center;
  color: var(--white);
  text-align: center;
  overflow: hidden;
  /* covers every inner page's hero (About/Services/FAQs/Contact/News set their photo via
     inline background-image) — the home hero's own .hero-slide layers handle their own. */
  background-size: cover; background-position: center; background-repeat: no-repeat;
}
/* 2026-09-05: same background-attachment:fixed parallax as .hero-slide and the
   "WE COLLECT" banner, generalised to every page's hero (not just Home's slideshow) —
   zero JS, GPU-composited. Desktop/tablet only, and off for reduced-motion (see below),
   same reasoning as those two. */
@media (min-width: 769px){
  .hero{ background-attachment: fixed; }
}
@media (prefers-reduced-motion: reduce){
  .hero{ background-attachment: scroll; }
}
.hero-slides{ position: absolute; inset: 0; z-index: 0; transform-origin: center; }
.hero-slide{
  position: absolute; inset: 0;
  overflow: hidden;
  opacity: 0; z-index: 0;
  transition: opacity 1.6s ease-in-out;
}
.hero-slide.active{ opacity: 1; z-index: 2; }
/* 2026-09-07: on the crossfade effects (fade / zoom) the outgoing slide stays fully
   opaque one layer DOWN while the new one fades in on top — so a crossfade never
   dips through to a darker frame mid-transition. main.js clears .leaving once the
   fade has finished. The slide effect does its own horizontal push, so it opts out. */
.hero-slides:not(.hero-slides--slide) .hero-slide.leaving{ opacity: 1; z-index: 1; transition: none; }

/* 2026-09-07: the image is its own layer inside .hero-slide. `translate` (parallax,
   written by main.js each scroll frame) and `scale` (Ken Burns) are independent
   properties, so the per-frame translate never disturbs the scale transition —
   which `background-attachment: fixed` + `transform` could never do together.
   top/height bleed gives the parallax room to move without exposing an edge. */
.hero-slide__img{
  position: absolute; left: 0; right: 0; top: -12%; height: 124%;
  background-position: center; background-size: cover; background-repeat: no-repeat;
  background-image: var(--hero-bg, none);
  scale: 1.05;
}
/* 2026-09-26: phones get the 608×1080 portrait center crop (same slice they'd
   show of the 16:9 image, ~⅓ the bytes); falls back to the 16:9 one */
/* 2026-09-26: per-slide focus point (Slide Home admin) — tablets position the
   16:9 image on it; phones use the portrait crop that was cut around it */
@media (max-width: 1023px){
  .hero-slide__img{ background-position: var(--hero-focus, 50%) center; }
}
@media (max-width: 600px){
  .hero-slide__img{ background-image: var(--hero-bg-sm, var(--hero-bg, none)); background-position: var(--hero-focus-sm, 50%) center; }
}
@media (min-width: 769px) and (prefers-reduced-motion: no-preference){
  /* Ken Burns: zoom IN only. The transition lives on `.active`; on the way out
     main.js pins the scale so the slide just fades, no reverse zoom-out. */
  .hero-slide.active .hero-slide__img{ scale: 1.13; transition: scale 7.5s ease-out; }
  .hero-slides--zoom .hero-slide.active .hero-slide__img{ scale: 1.2; transition: scale 9s ease-out; }
  /* 2026-09-09: sideways room for the pointer-parallax `translate` main.js writes
     (top/height already bleed for the vertical scroll drift). */
  .hero-slide__img{ left: -3%; right: -3%; }
  /* only hint the compositor where main.js actually drives transforms (home hero,
     desktop, motion-OK) — never promote these layers on mobile where the JS is off. */
  .hero-slides{ will-change: transform; }
  .hero-inner{ will-change: opacity, transform; }
}

/* 2026-09-05: transition effect picked in wp-admin (Slide Home). Parallax + Ken Burns
   apply to every option; the effect only changes how one slide gives way to the next.
   fade / zoom use the base opacity crossfade; slide adds a horizontal push.
   2026-09-09: "slide" is now directional + cinematically eased — main.js parks the
   incoming slide on the side the nav is heading and sets --leave-x on the outgoing one
   (−100% on next / auto-advance, +100% on prev). Each layer also settles from a slight
   1.05 zoom so the slide reads as layered depth, not a flat card sliding. */
.hero-slides--slide{ --slide-dur: 1.15s; --slide-ease: cubic-bezier(.16, 1, .3, 1); }
.hero-slides--slide .hero-slide{
  opacity: 1;
  transform: translateX(100%) scale(1.05);
  transition: transform var(--slide-dur) var(--slide-ease);
}
.hero-slides--slide .hero-slide.active{ transform: translateX(0) scale(1); z-index: 2; }
.hero-slides--slide .hero-slide.leaving{
  transform: translateX(var(--leave-x, -100%)) scale(1.05);
  z-index: 1;
  transition: transform var(--slide-dur) var(--slide-ease);
}
/* start position for the incoming slide — transition:none so main.js can commit it
   with a reflow before swapping to .active (which eases it to centre). */
.hero-slides--slide .hero-slide.slide-enter-right{ transform: translateX(100%) scale(1.05); transition: none; }
.hero-slides--slide .hero-slide.slide-enter-left{ transform: translateX(-100%) scale(1.05); transition: none; }
@media (prefers-reduced-motion: reduce){
  .hero-slides--slide .hero-slide{ opacity: 0; transform: none; transition: opacity 1.4s ease; }
  .hero-slides--slide .hero-slide.active{ opacity: 1; transform: none; }
  .hero-slides--slide .hero-slide.leaving{ opacity: 0; transform: none; }
}
.hero::before{
  content: ""; position: absolute; inset: 0; z-index: 1;
  /* 2026-09-04: the radial darken behind the text (needed so it didn't "sink" into a
     bright/busy photo) read as gloomy once it was dark enough to guarantee contrast on
     its own — backed it off a lot and leaned more on text-shadow to carry legibility
     instead, so the photo underneath stays visibly bright and colourful. */
  background:
    radial-gradient(55% 45% at 50% 42%, rgba(3,16,30,.38), rgba(3,16,30,0) 75%),
    linear-gradient(180deg, rgba(0,127,194,.16), rgba(11,46,79,.3));
}
.hero-inner{ position: relative; z-index: 2; margin: 0 auto; max-width: 820px; padding: 60px 24px; }
.hero-inner{ text-shadow: 0 2px 10px rgba(0,0,0,.6); }
/* 2026-09-09: main.js (home hero, desktop, motion-OK) drives opacity + translate + scale
   off scroll so the text zooms, drifts down and fades as the hero scrolls away.
   Scroll-linked, so no CSS transition here — it would lag the effect behind the scroll.
   (`will-change` is set in the desktop media query above, not globally.) */
.hero-logo-mark{ width: 120px; height: 120px; margin: 0 auto 28px; filter: drop-shadow(0 2px 8px rgba(0,0,0,.35)); }
.hero .eyebrow{ color: var(--white); opacity: .95; }
.hero h1{ color: var(--white); font-size: 46px; margin-bottom: 24px; }

/* 2026-09-04: hero headline — two lines, second line in the accent gold, both
   uppercase + letter-spaced to match the reference design. Thai has no letter
   case and gets cramped/misreads with tracked-out spacing (vowel/tone marks sit
   right on top of the consonant), so the Thai html[lang] override below resets
   both for that language instead of just translating the copy. */
.hero-title{ text-transform: uppercase; letter-spacing: 2px; font-weight: 800; }
.hero-title .line{ display: block; }
.hero-title .accent{ color: var(--accent, #F9C321); }
html[lang^="th"] .hero-title{ text-transform: none; letter-spacing: normal; }

.hero p{ font-size: 18px; opacity: .92; margin-bottom: 30px; }
.hero-actions{ display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }

/* 2026-09-25: Home hero re-synced to Figma node 345:3008 — scoped to #home so
   the other pages' heroes (same .hero base) keep their current look.
   Vertical logo, two big Poppins Bold lines (white 48 / blue 72), short
   subline, blue pill CTA; content gap 16px as in the Figma. The blue line
   uses the Figma's brighter #009df0 rather than the site's --primary
   (now #0070ab): it always sits on the darkened photo, where the darker blue
   loses contrast. The CTA keeps --primary, where white text reads better
   (5.4:1 vs ~3:1 on #009df0). */
/* 1248 − 2×24 padding = 1200px: room for the 72px blue line (~1150px) on one
   line at full width, still clear of the 48px arrows 32px in from each edge */
/* 2026-09-25 (WCAG pass, โต้ง's pick "เพิ่มเงาเข้มหลังข้อความ"): a wide, soft
   dark ellipse just behind the text block, on top of the base overlay. Sized
   and tuned against all three slides (canvas-measured median contrast behind
   each line): blue 72px line ≥3.3:1, white lines ≥8:1, subline ≥9:1. The
   photo's outer edges keep the base, lighter overlay. */
#home .hero::before{
  background:
    radial-gradient(70% 34% at 50% 54%, rgba(3,16,30,.61) 0%, rgba(3,16,30,.55) 62%, rgba(3,16,30,0) 100%),
    radial-gradient(55% 45% at 50% 42%, rgba(3,16,30,.38), rgba(3,16,30,0) 75%),
    linear-gradient(180deg, rgba(0,127,194,.16), rgba(11,46,79,.3));
}
#home .hero-inner{ max-width: 1248px; display: flex; flex-direction: column; align-items: center; gap: 16px; }
#home .hero-logo-full{
  display: block; width: 300px; max-width: 64vw; height: auto; margin: 0;
  filter: drop-shadow(0 2px 8px rgba(0,0,0,.35));
}
#home .hero-title{ margin: 0; font-family: var(--font-body); font-weight: 700; letter-spacing: 0; line-height: 1.12; }
#home .hero-title .line{ font-size: clamp(24px, 3.34vw, 48px); color: var(--white); }
#home .hero-title .accent{ font-size: clamp(32px, 5vw, 72px); color: #009df0; }
/* 2026-10-03: a little air between the white line and the blue line (they sat
   almost touching at line-height 1.12); Thai gets more, see below */
#home .hero-title .accent{ margin-top: clamp(6px, 0.84vw, 12px); }
/* 2026-10-03: Thai only — 24px between the white line and the blue line; Thai's
   stacked vowels/tone marks made the two lines look like they were touching */
html[lang^="th"] #home .hero-title .accent{ margin-top: 24px; }
@media (max-width: 768px){ html[lang^="th"] #home .hero-title .accent{ margin-top: 16px; } }
#home .hero-sub{ margin: 0; font-size: 16px; line-height: 1.6; opacity: .92; }
/* 2026-10-03: Thai phrase wrapping — see ma_phrases() in functions.php. Each phrase
   is unbreakable (it still wraps inside if it's wider than the line on its own);
   balance evens out line lengths so a lone word isn't left on the last line. */
.ma-phrase{ display: inline-block; }
/* 2026-10-03: site-wide for Thai — balanced headings stop a heading leaving one
   syllable on its own last line ("…ไปข้าง / หน้า", "…ครบ / วงจร"); `pretty` does the
   same for body copy. Browsers without text-wrap just wrap as before. */
html[lang^="th"] :is(h1, h2, h3, h4, .eyebrow, .hero-sub){ text-wrap: balance; }
html[lang^="th"] :is(p, li){ text-wrap: pretty; }
#home .hero-title .line, #home .hero-sub{ text-wrap: balance; }
#home .hero-cta{
  /* 2026-09-27 (โต้ง): same blue as the "Join Us…" line (#009df0) —
     knowingly below WCAG for its white label (~3:1), like We believe */
  padding: 16px 32px; border-radius: 999px; background: #009df0; color: var(--white);
  font-size: 18px; font-weight: 700; line-height: 28px; text-shadow: none;
}
#home .hero-cta:hover{ background: #0086cc; }
#home .hero-arrow{ width: 48px; height: 48px; border-width: 1px; border-color: rgba(255,255,255,.5); font-size: 22px; }
@media (min-width: 769px){
  #home .hero-arrow.prev{ left: 32px; }
  #home .hero-arrow.next{ right: 32px; }
}
@media (max-width: 640px){
  #home .hero-arrow{ width: 38px; height: 38px; }
}
.hero-arrow{
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 46px; height: 46px; border-radius: 50%; border: 2px solid rgba(255,255,255,.7);
  background: transparent; color: var(--white); font-size: 18px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; transition: background .2s ease;
}
.hero-arrow:hover{ background: rgba(255,255,255,.15); }
.hero-arrow.prev{ left: 24px; }
.hero-arrow.next{ right: 24px; }

/* 2026-09-06: "scroll for more" cue, bottom-centre of the hero — a static mouse
   icon (capsule body + scroll-wheel tick) with a chevron BELOW it that loops
   downward to suggest scrolling. Only the chevron moves; the mouse stays put.
   drop-shadow on the whole cue keeps it readable over a bright patch of the
   hero photo, the same fix used for the header nav. */
.hero-scroll-cue{
  position: absolute; left: 50%; bottom: 26px; z-index: 3;
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  filter: drop-shadow(0 1px 5px rgba(0,0,0,.55));
}
.hero-scroll-cue-mouse{
  width: 24px; height: 38px;
  border: 2px solid rgba(255,255,255,.85);
  border-radius: 13px;
  display: flex; justify-content: center;
  padding-top: 6px;
  transition: border-color .2s ease;
}
.hero-scroll-cue-wheel{
  width: 2.5px; height: 7px;
  background: rgba(255,255,255,.85);
  border-radius: 2px;
  transition: background .2s ease;
}
.hero-scroll-cue:hover .hero-scroll-cue-mouse{ border-color: var(--white); }
.hero-scroll-cue:hover .hero-scroll-cue-wheel{ background: var(--white); }
.hero-scroll-cue-arrow{
  display: flex; color: rgba(255,255,255,.85);
  animation: heroScrollArrowMove 1.6s ease-in-out infinite;
}
.hero-scroll-cue-arrow .icon-svg{ width: 14px; height: 14px; }
@keyframes heroScrollArrowMove{
  0%   { opacity: 0; transform: translateY(-3px); }
  45%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(6px); }
}
@media (prefers-reduced-motion: reduce){
  .hero-scroll-cue-arrow{ animation: none; opacity: .85; transform: none; }
}
@media (max-width: 640px){
  .hero-scroll-cue{ bottom: 16px; }
  .hero-scroll-cue-mouse{ width: 21px; height: 33px; }
}

/* ---------- Scroll reveal ----------
   2026-09-05: was hidden (opacity:0) until scrolled into view via JS/IntersectionObserver.
   That broke anything that reads the page without simulating a real scroll — the Figma
   capture tool, and in principle screen readers/SEO crawlers/no-JS visitors too — content
   below the fold just wasn't there. Content is visible by default.
   2026-09-09: the hidden/offset start state is scoped under <html class="reveal-ready">,
   which main.js adds ONLY when IntersectionObserver is driving reveals and motion is
   allowed. A no-JS / reduced-motion / crawler / capture render never gets that class and
   still sees everything at rest — visible, no transform. */
.reveal{ opacity: 1; transform: none; }

html.reveal-ready .reveal{
  opacity: 0; transform: translateY(28px);
  transition: opacity .8s var(--ease-out), transform .8s var(--ease-out);
}
html.reveal-ready .reveal.in-view{ opacity: 1; transform: none; }

/* stagger containers: the container itself holds still — its direct children cascade in
   (main.js sets each child's transition-delay the first time the container enters view). */
html.reveal-ready :is(.about-columns, .news-grid, .ma-capability-grid, .transport-cards, .ship-grid, .capability-detail-list).reveal{
  opacity: 1; transform: none; transition: none;
}
html.reveal-ready :is(.about-columns, .news-grid, .ma-capability-grid, .transport-cards, .ship-grid, .capability-detail-list).reveal > *{
  opacity: 0; transform: translateY(22px);
  transition: opacity .7s var(--ease-out), transform .7s var(--ease-out);
}
html.reveal-ready :is(.about-columns, .news-grid, .ma-capability-grid, .transport-cards, .ship-grid, .capability-detail-list).reveal.in-view > *{
  opacity: 1; transform: none;
}

/* ---------- Home Service section CTA ---------- */
.service-acc-cta{ text-align: center; margin-top: 30px; }

/* ---------- News grid (single-page News section) ---------- */
/* 2026-08-19 Chalermchai Panyasai: mirrors the old services-grid/service-card so it reads as
   the same design system, not a one-off component.
   2026-09-18: card radius/shadow/image-height/badge refined to match Figma node
   181:3947 — shared by this teaser grid and page-news.php's full listing (same
   .news-card markup on both). */
.news-grid{ display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; margin-top: 10px; }
.news-card{
  display: block; background: var(--surface); border-radius: 20px;
  box-shadow: 0 10px 25px -5px rgba(15,23,42,.08), 0 8px 10px -6px rgba(15,23,42,.06);
  text-align: left; overflow: hidden; transition: transform .2s ease;
}
.news-card:hover{ transform: translateY(-6px); }
.news-card-image{ position: relative; }
.news-card-image img{ width: 100%; height: 192px; object-fit: cover; }
.news-card-badge{
  position: absolute; top: 14px; left: 14px; background: var(--primary); color: var(--white);
  border: 1px solid var(--primary-dark); box-shadow: 0 1px 1px rgba(0,0,0,.05);
  font-family: var(--font-heading); font-weight: 700; font-size: 11px; letter-spacing: .5px;
  text-transform: uppercase; padding: 5px 12px; border-radius: 20px;
}
.news-card-body{ padding: 22px 24px; }
.news-card-body h3{ font-size: 17px; margin: 0 0 8px; }
.news-card-meta{ color: var(--muted); font-size: 13px; margin: 0; }

/* 2026-09-19: Home's News cards zoom the thumbnail to 1.1x on hover (back to 1x on
   mouse-out), staying inside the image frame — scoped to .news-section so the full
   /news/ listing (same .news-card markup) is unchanged. The overflow clip keeps the
   scaled image from spilling over the card body; the category badge sits inside that
   frame so it's unaffected. Gated to real hover pointers + motion-OK, so touch screens
   never get a stuck-hover zoom and reduced-motion users get no movement. */
@media (hover: hover) and (prefers-reduced-motion: no-preference){
  .news-section .news-card-image{ overflow: hidden; }
  .news-section .news-card-image img{ transition: transform .5s var(--ease-out); }
  .news-section .news-card:hover .news-card-image img,
  .news-section .news-card:focus-visible .news-card-image img{ transform: scale(1.1); }
}

/* 2026-09-19: News section background = looping video under a dark navy overlay (replaces the
   tsParticles canvas, which replaced the CSS glow/grid/tiles). The section is now dark, so its
   title/eyebrow/"See More" flip to light; the cards stay white. Decorative layer: aria-hidden,
   pointer-events:none, absolute + below .container so it never shifts layout.
   Desktop (>=769px): main.js shows the poster frame, then loads + plays the video and
   fades it in (.is-playing). <=768px and reduced-motion never download the video — they get
   plain navy (mobile) / the poster (reduced-motion desktop). */
.news-section{ position: relative; overflow: hidden; background: var(--navy-dark); }
.news-section .container{ position: relative; z-index: 1; }
.news-bg-decor{ position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.news-bg-video{
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity .9s ease;
}
.news-bg-video.is-playing{ opacity: 1; }
.news-bg-overlay{
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(7,28,51,.88) 0%, rgba(7,28,51,.74) 45%, rgba(7,28,51,.9) 100%);
}
/* .news-bg-ready is added by main.js (desktop only) when the section nears the viewport, so the
   poster isn't downloaded up-front. */
.news-section.news-bg-ready .news-bg-decor{ background: url("assets/video/news-bg-poster.jpg") center / cover no-repeat; }
@media (max-width: 768px){
  .news-bg-video{ display: none; }
}
.news-section .eyebrow{ color: #7dd3fc; }
.news-section .section-title h2{ color: var(--white); }
.news-section .btn-outline-primary{ border-color: var(--white); color: var(--white); }
.news-section .btn-outline-primary:hover{ background: var(--white); color: var(--navy); }
.page-numbers{
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 40px; height: 40px; padding: 0 8px; border-radius: 8px;
  font-family: var(--font-heading); font-weight: 700; color: var(--heading);
}
.page-numbers.current{ background: var(--primary); color: var(--white); }
.page-numbers:not(.current):not(.dots):hover{ background: var(--surface-alt); }

/* ---------- Single post content ---------- */
.ma-post-cover{ max-width: 980px; margin: 30px auto 0; padding: 0 24px; }
.ma-post-cover img{ width: 100%; max-height: 460px; object-fit: cover; border-radius: var(--radius); }
.ma-post-content p{ margin: 0 0 20px; font-size: 16px; line-height: 1.75; }
.ma-post-content p:last-child{ margin-bottom: 0; }

.services-cta{ text-align: center; margin-top: 46px; }

/* ---------- Values / About ---------- */
.values-grid{ display: grid; grid-template-columns: repeat(4, 1fr); gap: 26px; }
.value-card{
  background: var(--surface-alt); border-radius: var(--radius); padding: 28px; text-align: center;
}
.value-card h3{ font-size: 18px; }
.value-card p{ color: var(--muted); font-size: 14px; margin: 0; }

.two-col{ display: grid; grid-template-columns: 1fr 1fr; gap: 50px; align-items: center; }
.two-col img{ border-radius: var(--radius); }

.check-list{ list-style: none; padding: 0; margin: 20px 0; }
.check-list li{ padding-left: 30px; position: relative; margin-bottom: 12px; }
.check-list li::before{
  content: "✓"; position: absolute; left: 0; top: 0;
  color: var(--link); font-weight: 700;
}

/* ---------- FAQ accordion ---------- */
.faq-list{ max-width: 800px; margin: 0 auto; }
.faq-item{
  border: 1px solid var(--line-soft); border-radius: 10px; margin-bottom: 14px; overflow: hidden;
  background: var(--surface);
}
.faq-question{
  display: flex; align-items: center; justify-content: space-between;
  padding: 20px 24px; cursor: pointer; font-family: var(--font-heading);
  font-weight: 700; color: var(--heading); background: none; border: none; width: 100%; text-align: left;
  font-size: 16px;
}
.faq-question::after{ content: "+"; font-size: 22px; color: var(--link); transition: transform .2s ease; }
.faq-item.open .faq-question::after{ transform: rotate(45deg); }
.faq-answer{ max-height: 0; overflow: hidden; transition: max-height .25s ease; padding: 0 24px; color: var(--muted); }
.faq-item.open .faq-answer{ max-height: 400px; padding: 0 24px 22px; }

/* ---------- Contact ---------- */
.contact-grid{ display: grid; grid-template-columns: 1fr 1fr; gap: 50px; }
.contact-info-item{ margin-bottom: 22px; }
.contact-info-item .label{ font-family: var(--font-heading); font-weight: 700; color: var(--heading); display: block; margin-bottom: 4px; }
.contact-form input, .contact-form textarea{
  width: 100%; padding: 14px 16px; margin-bottom: 16px; border: 1px solid var(--line);
  border-radius: 8px; font-family: var(--font-body); font-size: 15px;
}
.contact-form textarea{ min-height: 130px; resize: vertical; }
.form-note{ margin-top: 10px; font-size: 13px; color: var(--muted); }

.offices-grid{ display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; margin-top: 20px; }
.office-card{ background: var(--surface-alt); border-radius: var(--radius); padding: 22px; }
.office-card h4{ font-size: 17px; margin-bottom: 10px; }
.office-card p{ font-size: 14px; color: var(--muted); margin: 4px 0; }
.office-card{ display: flex; flex-direction: column; }
.office-visit{ margin-top: auto; padding-top: 12px; font-size: 14px; font-weight: 600; color: var(--link); }
.office-visit:hover{ text-decoration: underline; }

/* ---------- Footer ---------- */
.site-footer{ background: var(--navy-dark); color: rgba(255,255,255,.75); padding: 40px 0; text-align: center; font-size: 14px; }
.site-footer a{ color: rgba(255,255,255,.9); }
.footer-menu{
  list-style: none; display: flex; justify-content: center; flex-wrap: wrap;
  gap: 24px; margin: 0 0 20px; padding: 0; font-family: var(--font-heading); font-weight: 600; font-size: 13px;
}

/* ---------- Hover micro-interactions ----------
   2026-09-09: gentle lift + shadow on card-like blocks, plus the expo-out curve on the
   the .news-card that already lifted (it had a plain .2s ease). Motion only,
   no colour change — dropped for reduced-motion. */
.news-card{ transition: transform .3s var(--ease-out), box-shadow .3s var(--ease-out); }
.news-card:hover{ box-shadow: 0 16px 38px rgba(11,46,79,.14); }
.value-card{ transition: transform .3s var(--ease-out), box-shadow .3s var(--ease-out); }
.value-card:hover{ transform: translateY(-5px); box-shadow: 0 14px 32px rgba(11,46,79,.12); }
.ma-capability-item{ transition: transform .25s var(--ease-out); }
.ma-capability-item .icon-svg{ transition: color .25s ease; }
.ma-capability-item:hover{ transform: translateY(-4px); }
.ma-capability-item:hover .icon-svg{ color: var(--link); }
@media (prefers-reduced-motion: reduce){
  .news-card:hover,
  .value-card:hover, .ma-capability-item:hover{ transform: none; }
}

/* ---------- Responsive ---------- */
@media (max-width: 900px){
  .values-grid, .offices-grid, .news-grid{ grid-template-columns: repeat(2, 1fr); }
  .two-col, .contact-grid{ grid-template-columns: 1fr; }
  .hero h1{ font-size: 32px; }
}
/* 2026-09-25 (โต้ง): the hamburger menu now kicks in at ≤900px instead of
   ≤640px — between those widths the desktop row squeezed and wrapped
   ("About / Us"; Thai labels wrap below ~900px). 2026-09-26: raised to
   ≤1023px once "Our Partners" joined the menu (6 items wrap below ~1000px;
   at 1024 Thai still has ~11px spare). main.js' language-switcher mover
   uses the same query. */
@media (max-width: 1023px){
  .main-nav{ display: none; position: absolute; top: 100%; left: 0; right: 0; background: var(--surface); box-shadow: 0 10px 20px rgba(0,0,0,.08); }
  .main-nav.open{ display: block; }
  .main-nav ul{ flex-direction: column; padding: 20px 24px; gap: 18px; }
  /* the dropdown panel itself is always solid white, regardless of .scrolled — so its
     links stay navy always too, instead of inheriting the transparent-header's white text.
     text-shadow (added for legibility over the hero photo) also needs dropping here —
     same reason as the button-hover fix, it just looks muddy on a solid white panel. */
  .main-nav a{ color: var(--heading); text-shadow: none; }
  .main-nav a:hover, .main-nav .current-menu-item > a{ color: var(--link); }
  .menu-toggle{ display: block; }
  /* 2026-08-19: language switcher moves into the mobile menu. */
  .header-actions .lang-switcher{ display: none; }
}
@media (max-width: 640px){
  .values-grid, .offices-grid, .news-grid{ grid-template-columns: 1fr; }
  .hero h1{ font-size: 26px; }
  .hero-arrow{ width: 38px; height: 38px; }
  .hero-arrow.prev{ left: 10px; }
  .hero-arrow.next{ right: 10px; }


  /* 2026-08-19: single-page Service section — narrower grids on mobile. */
  .ma-capability-grid{ grid-template-columns: repeat(2, 1fr); }
}

/* ---------- Services page (2026-09-18: WFN network positioning, from Figma
   node 197:3660) — new components only; reuses .section/.section-title/.eyebrow/
   .btn/.ma-capability-grid and the site's own icon set + colour tokens throughout,
   so this page stays visually consistent with Home/About rather than importing the
   Figma's own fonts/colours/icon assets. ---------- */
.services-intro{
  display: flex; align-items: stretch; border-radius: var(--radius); overflow: hidden;
  box-shadow: 0 20px 45px rgba(11,46,79,.10);
}
.services-intro-highlight{
  flex: 1 1 0; min-width: 260px;
  background: var(--primary); color: var(--light-blue);
  display: flex; flex-direction: column; justify-content: center; gap: 10px;
  padding: 40px 32px; text-align: center;
}
.services-intro-kicker{ font-family: var(--font-heading); font-weight: 800; font-size: 28px; line-height: 1.25; margin: 0; }
.services-intro-tagline{ font-family: var(--font-heading); font-weight: 500; font-size: 17px; line-height: 1.4; margin: 0; }
.services-intro-body{
  flex: 1 1 0; min-width: 280px; background: var(--surface);
  display: flex; flex-direction: column; justify-content: center; gap: 24px;
  padding: 40px; color: var(--muted); font-size: 15px; line-height: 1.6;
}
.services-intro-body p{ margin: 0; text-align: center; }
.services-intro-divider{ border: none; border-top: 1px solid var(--surface-alt); margin: 0; width: 100%; }
@media (max-width: 768px){ .services-intro{ flex-direction: column; } }

.transport-cards{ display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 40px; }
.transport-card{
  background: var(--primary); border-radius: var(--radius);
  padding: 28px 24px; text-align: center; color: var(--light-blue);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  transition: transform .3s var(--ease-out), box-shadow .3s var(--ease-out);
}
.transport-card:hover{ transform: translateY(-5px); box-shadow: 0 14px 32px rgba(11,46,79,.18); }
/* 2026-09-18: pictogram from Figma (assets/images/icons/services/) — ships with its own
   light fill baked in, unlike the site's stroke .icon-svg set which takes `color`. */
.transport-card-icon{ width: 56px; height: 56px; }
.transport-card h3{ color: var(--white); font-size: 18px; margin: 0; letter-spacing: .4px; }
.transport-card p{ margin: 0; font-size: 14px; line-height: 1.5; font-weight: 300; }
@media (max-width: 768px){ .transport-cards{ grid-template-columns: 1fr; } }

/* 2026-09-19: hover reveal per the Service Figma (node 221:1930) — the blue card fades to
   a photo, its icon/title/description fade out, and a "[mark] TITLE" header slides up into the
   top-left. Markup lives in template-parts/transport-cards.php (shared by Home + /services/).
   The photo layer and hover header are display:none by default, so touch devices and
   reduced-motion users get the plain blue card AND never download the photos (lazy imgs
   inside a display:none parent aren't fetched). Card size is set by .transport-card-rest,
   which stays in flow, so nothing shifts on hover. Opacity/transform only. */
.transport-card{ position: relative; overflow: hidden; }
.transport-card-rest{ display: flex; flex-direction: column; align-items: center; gap: 10px; width: 100%; position: relative; z-index: 1; }
.transport-card-photo, .transport-card-hover-title{ display: none; }
@media (hover: hover) and (prefers-reduced-motion: no-preference){
  .transport-card-photo{
    display: block; position: absolute; inset: 0; z-index: 0; opacity: 0; overflow: hidden;
    transition: opacity .45s var(--ease-out);
  }
  /* photo starts zoomed in (1.2x) and settles to 1x while it fades in on hover — slower
     than the fade (.9s) so the zoom-out is still easing after the photo is fully visible;
     reverses on mouse-out. The card's overflow:hidden crops the scaled edges. */
  .transport-card-photo img{
    width: 100%; height: 100%; object-fit: cover;
    transform: scale(1.2); transition: transform .9s var(--ease-out);
  }
  .transport-card--sea .transport-card-photo img{ object-position: 60% 68%; }
  /* dark wash, heaviest behind the top-left header, so the white title stays legible */
  .transport-card-photo::after{
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(4,18,33,.58) 0%, rgba(4,18,33,.14) 52%, rgba(4,18,33,.22) 100%);
  }
  .transport-card-rest{ transition: opacity .3s ease, transform .45s var(--ease-out); }
  .transport-card-hover-title{
    display: flex; align-items: center; gap: 10px;
    position: absolute; z-index: 2; top: 20px; left: 22px; right: 22px;
    opacity: 0; transform: translateY(70px); pointer-events: none;
    transition: opacity .35s ease, transform .5s var(--ease-out);
  }
  .transport-card-mark{ width: 24px; height: 24px; flex: none; }
  .transport-card-hover-title span{
    font-family: var(--font-heading); font-weight: 700; font-size: 18px; letter-spacing: .4px; color: var(--white);
    text-shadow: 0 1px 6px rgba(0,0,0,.35);
  }
  .transport-card:hover .transport-card-photo{ opacity: 1; }
  .transport-card:hover .transport-card-photo img{ transform: scale(1); }
  .transport-card:hover .transport-card-rest{ opacity: 0; transform: translateY(-14px); }
  .transport-card:hover .transport-card-hover-title{ opacity: 1; transform: translateY(0); transition-delay: .08s; }
  /* the brand mark (Figma 223:1982, was a "+") makes one full turn as the header rises and
     decelerates (expo-out — fast at first, easing to a slow finish) until it stops upright.
     Started with the header's own .08s delay so the spin is already going as it slides in.
     Rotation only: no scale/bounce (the earlier spring version was dropped on request). */
  .transport-card:hover .transport-card-mark{ animation: transportMarkSpin 1.1s var(--ease-out) .08s both; }
  @keyframes transportMarkSpin{
    from { transform: rotate(-360deg); }
    to   { transform: rotate(0deg); }
  }
}
.ship-section{ background: var(--surface-alt); }
.ship-badge{
  display: inline-flex; align-items: center; gap: 12px;
  background: var(--primary); color: var(--white); border-radius: 999px;
  padding: 10px 24px; margin-top: 18px; font-family: var(--font-heading);
}
.ship-badge span:first-child{ font-weight: 700; font-size: 13px; letter-spacing: .5px; }
.ship-badge-divider{ width: 1px; height: 16px; background: rgba(255,255,255,.3); }
.ship-badge-formula{ font-weight: 800; font-size: 16px; letter-spacing: 1px; }
.ship-grid{ display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
.ship-card{
  background: var(--surface); border-radius: 16px; padding: 28px; min-height: 320px;
  box-shadow: 0 1px 2px rgba(0,0,0,.05); display: flex; flex-direction: column; justify-content: space-between;
  transition: transform .3s var(--ease-out), box-shadow .3s var(--ease-out);
}
.ship-card:hover{ transform: translateY(-5px); box-shadow: 0 14px 32px rgba(11,46,79,.12); }
.ship-card-badge{
  display: flex; align-items: center; justify-content: center;
  width: 48px; height: 48px; border-radius: 12px; background: var(--primary);
  color: var(--white); font-family: var(--font-heading); font-weight: 800; font-size: 22px;
  margin-bottom: 12px;
}
.ship-card h3{ font-size: 14px; letter-spacing: .5px; color: var(--heading); margin: 0 0 8px; text-transform: uppercase; }
.ship-card p{ font-size: 14px; color: var(--muted); margin: 0; line-height: 1.5; }
.ship-card-tag{
  margin-top: 20px !important; padding-top: 13px; border-top: 1px solid var(--surface-alt);
  color: var(--link) !important; font-weight: 700; font-size: 12px !important;
}
@media (max-width: 900px){ .ship-grid{ grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px){ .ship-grid{ grid-template-columns: 1fr; } .ship-card{ min-height: 0; } }

.capability-detail-list{ max-width: 900px; margin: 0 auto; display: flex; flex-direction: column; gap: 20px; }
.capability-detail-row{
  background: var(--surface); border: 1px solid var(--line-soft); border-radius: 16px;
  display: flex; align-items: center; gap: 24px; padding: 28px; flex-wrap: wrap;
  transition: transform .3s var(--ease-out), box-shadow .3s var(--ease-out);
}
.capability-detail-row:hover{ transform: translateY(-3px); box-shadow: 0 12px 28px rgba(11,46,79,.10); }
.capability-detail-head{ display: flex; align-items: center; gap: 16px; flex: 1 1 260px; }
/* 2026-09-18: pictogram from Figma (assets/images/icons/services/), dark-slate fill baked in. */
.capability-detail-icon{ width: 56px; height: 56px; flex-shrink: 0; }
.capability-detail-head h3{ font-size: 18px; margin: 0; color: var(--heading); }
.capability-detail-sub{ margin: 2px 0 0; font-size: 13px; font-weight: 700; color: var(--link); }
.capability-detail-desc{
  flex: 2 1 320px; margin: 0; padding-left: 24px; border-left: 1px solid var(--surface-alt);
  color: var(--muted); font-size: 14px; line-height: 1.6;
}
@media (max-width: 640px){
  .capability-detail-desc{ border-left: none; padding-left: 0; padding-top: 16px; border-top: 1px solid var(--surface-alt); }
}

.services-contact-cta .container{ max-width: 700px; text-align: center; }
.services-contact-cta p{ margin: 6px 0; color: var(--muted); font-size: 14px; }
.services-contact-cta .btn{ margin-top: 20px; }

/* ==========================================================================
   Theme toggle button (2026-09-19) — only rendered when MA_DARK_MODE_ENABLED is true
   (functions.php); mirrors the round header icon buttons.
   ========================================================================== */
.theme-toggle{
  width: 42px; height: 42px; border-radius: 50%; border: none; padding: 0; cursor: pointer; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.18); color: var(--white); box-shadow: 0 1px 6px rgba(0,0,0,.18);
  transition: background-color .3s ease, color .3s ease, box-shadow .3s ease;
}
.theme-toggle .icon-svg{ filter: drop-shadow(0 1px 3px rgba(0,0,0,.4)); transition: filter .3s ease; }
.theme-toggle:hover{ background: var(--white); color: var(--primary); }
.site-header.scrolled .theme-toggle{ background: var(--surface-alt); color: var(--heading); box-shadow: none; }
.site-header.scrolled .theme-toggle:hover{ background: var(--primary); color: var(--white); }
.site-header.scrolled .theme-toggle .icon-svg{ filter: none; }
.theme-toggle .icon-svg:nth-child(2){ display: none; }              /* sun: shown in dark */
html[data-theme="dark"] .theme-toggle .icon-svg:nth-child(1){ display: none; }  /* moon: shown in light */
html[data-theme="dark"] .theme-toggle .icon-svg:nth-child(2){ display: block; }

/* Mobile menu section (<=640px): full-width bordered row like the language box — moon icon +
   label on the left, switch on the right. Hidden on desktop (the header icon button is used
   there); on mobile the header icon button is hidden instead, so there's one control per size. */
.main-nav-theme{ display: none; }
.theme-switch{
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 14px 18px;
  background: var(--surface); color: var(--heading); border: 1px solid var(--line); border-radius: 10px;
  font: inherit; font-family: var(--font-heading); font-weight: 700; font-size: 13px; text-align: left; cursor: pointer;
}
.theme-switch:hover{ background: var(--surface-alt); border-color: var(--primary); }
.theme-switch .icon-svg{ width: 20px; height: 20px; flex-shrink: 0; }
.theme-switch-label{ flex: 1; }
.theme-switch-track{
  position: relative; flex-shrink: 0; width: 46px; height: 26px; border-radius: 13px;
  background: var(--line); transition: background-color .25s ease;
}
.theme-switch-thumb{
  position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--white); box-shadow: 0 1px 3px rgba(0,0,0,.3); transition: transform .25s var(--ease-out);
}
html[data-theme="dark"] .theme-switch-track{ background: var(--primary); }
html[data-theme="dark"] .theme-switch-thumb{ transform: translateX(20px); }
@media (max-width: 1023px){ /* same breakpoint as the hamburger menu */
  .main-nav-theme{ display: block; padding: 0 16px 18px; }
  .header-actions .theme-toggle{ display: none; }
}
@media (prefers-reduced-motion: reduce){
  .theme-switch-track, .theme-switch-thumb{ transition: none; }
}

/* ==========================================================================
   DARK THEME (2026-09-19)  —  the ONE place a designer needs to edit.
   --------------------------------------------------------------------------
   Status: built but not public. Nothing here applies unless <html data-theme="dark"> is set,
   which happens only when (a) MA_DARK_MODE_ENABLED is true in functions.php, or (b) someone
   previews with ?theme=dark on any URL (?theme=reset clears it).
   Tuning colours: change the 9 role tokens in the first rule — everything on the site reads
   from them. The rules after it are small element fixes (logo swap, pictogram icons, borders)
   for things a plain colour swap can't handle; adjust freely.
   Not themed on purpose: hero/gate photos + video, the News section (already dark), the footer
   (already dark), primary-blue buttons/badges/cards. The cookie banner has its own dark mode
   (Settings > cookie consent), independent of this one.
   ========================================================================== */
html[data-theme="dark"]{
  color-scheme: dark;            /* native form controls, scrollbars */
  --bg: #0a1622;                 /* page background */
  --surface: #13293f;            /* cards, solid header, dropdowns */
  --surface-alt: #0e2135;        /* tinted sections, hover fills */
  --heading: #f1f6fb;            /* headings + strong text */
  --text: #d4dfea;               /* body text */
  --muted: #9db0c3;              /* secondary text */
  --link: #4fb4ec;               /* brand-blue text/links (lighter than #007FC2 for contrast) */
  --line: #2a4661;               /* input / dropdown borders */
  --line-soft: #1f3a52;          /* card borders, dividers */
}
/* header logo: the scrolled header is a dark surface, so use the white lockup */
html[data-theme="dark"] .site-header.scrolled .logo-lockup-white{ display: block; }
html[data-theme="dark"] .site-header.scrolled .logo-lockup-color{ display: none; }
html[data-theme="dark"] .site-header.scrolled{ box-shadow: 0 2px 12px rgba(0,0,0,.45); }
/* Figma pictograms ship with a dark-slate fill baked in — flip them to light */
html[data-theme="dark"] .ma-capability-icon,
html[data-theme="dark"] .capability-detail-icon{ filter: brightness(0) invert(.9); }
/* the soft blue-tinted shadows vanish on dark; give cards a hairline instead */
html[data-theme="dark"] .news-card{ box-shadow: 0 0 0 1px var(--line-soft), 0 10px 25px -5px rgba(0,0,0,.45); }
html[data-theme="dark"] .ship-card{ box-shadow: 0 0 0 1px var(--line-soft); }
html[data-theme="dark"] .services-intro{ box-shadow: 0 20px 45px rgba(0,0,0,.4); }
html[data-theme="dark"] .contact-form input,
html[data-theme="dark"] .contact-form textarea{ background: var(--surface); color: var(--text); }
html[data-theme="dark"] .site-footer{ border-top: 1px solid var(--line-soft); }

/* ==========================================================================
   2026-09-28: inner pages v2 — Services (Figma 428:4529) + Contact (Figma
   432:5263), mapped onto the site's own system: transparent header over a
   photo banner (so the banner is 362px of visible image + the 84px header
   band), Poppins, colour tokens (dark theme for free), and WCAG-passing
   colours where the Figma's #009df0 would fail for body-size text.
   ========================================================================== */
.hero.page-banner{
  min-height: 446px; display: flex; align-items: center; justify-content: center;
  padding-top: 84px; text-align: center;
  background: linear-gradient(rgba(0, 56, 125, .7), rgba(0, 56, 125, .7)), var(--banner) center / cover no-repeat;
}
.hero.page-banner::before{ display: none; }
.page-banner-inner{ position: relative; z-index: 2; padding: 0 24px; }
.page-banner-title{ margin: 0; font-family: var(--font-body); font-weight: 600; font-size: clamp(28px, 2.5vw, 36px); line-height: 1.22; color: #ebf4f9; text-shadow: none; }
@media (max-width: 640px){ .hero.page-banner{ min-height: 300px; } }

.page-intro-section{ padding: 40px 0 80px; }
.page-container{ max-width: 1232px; }
.page-intro{ display: flex; flex-direction: column; gap: 16px; margin-bottom: 24px; }
.page-intro-title{ margin: 0; font-family: var(--font-body); font-weight: 600; font-size: clamp(26px, 2.5vw, 36px); line-height: 1.22; color: var(--heading); }
.page-intro-sub{ margin: 0; max-width: 760px; font-weight: 500; font-size: clamp(17px, 1.39vw, 20px); line-height: 1.4; color: var(--link); }

/* Services: photo cards */
.svc-grid{ display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 45px; }
.svc-card{
  position: relative; display: flex; flex-direction: column; justify-content: flex-end;
  min-height: 320px; padding: 24px; border-radius: 8px; overflow: hidden; color: #ebf4f9;
  isolation: isolate;
}
.svc-card-bg{ position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; object-fit: cover; transition: transform .6s var(--ease-out); }
/* Figma: flat 50% black; a touch deeper at the bottom so the light copy stays ≥4.5:1 on busy photos */
.svc-card::before{ content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(to top, rgba(0,0,0,.72), rgba(0,0,0,.45) 60%, rgba(0,0,0,.4)); }
.svc-card:hover .svc-card-bg{ transform: scale(1.04); }
.svc-card-body{ display: flex; flex-direction: column; gap: 10px; }
.svc-card-title{ display: flex; align-items: center; gap: 10px; margin: 0; font-family: var(--font-body); font-weight: 700; font-size: 20px; line-height: 28px; color: #ebf4f9; }
.svc-card-mark{ flex: 0 0 24px; width: 24px; height: 24px; }
.svc-card p{ margin: 0; font-weight: 300; font-size: clamp(16px, 1.25vw, 18px); line-height: 26px; color: #ebf4f9; }
.svc-card p + p{ margin-top: 16px; }
/* full-width "Why" card — brand blue (--primary, contrast-safe for its light text) */
.svc-card.is-why{ grid-column: 1 / -1; min-height: 0; background: var(--primary); justify-content: flex-start; }
.svc-card.is-why::before{ display: none; }
.svc-card.is-why ul{ margin: 0; padding-left: 27px; font-weight: 300; font-size: clamp(16px, 1.25vw, 18px); line-height: 26px; }
@media (max-width: 900px){
  .svc-grid{ grid-template-columns: 1fr; gap: 24px; }
}

/* Contact */
.contact-page-map-box{ width: 100%; height: auto; aspect-ratio: 1360 / 410; margin-bottom: 24px; }
@media (max-width: 900px){ .contact-page-map-box{ aspect-ratio: auto; height: 320px; } }
.contact-hq{ padding: 24px; text-align: center; }
.contact-hq-name{ margin: 0 0 8px; font-family: var(--font-body); font-weight: 700; font-size: clamp(26px, 2.5vw, 36px); line-height: 1.22; color: var(--heading); }
.contact-hq-address{ max-width: 576px; margin: 0 auto 8px; font-size: 15px; line-height: 1.6; color: var(--muted); }
.contact-hq-line{ margin: 4px 0; font-size: 15px; font-weight: 500; color: var(--heading); }
.contact-hq-line a{ color: var(--link); }
.contact-offices-section{ padding: 0 0 80px; }
.contact-offices-panel{ padding: 64px clamp(20px, 5vw, 72px); background: var(--surface-alt); }
.contact-offices-panel .office-card{ background: none; padding: 0; }

/* 2026-09-28: Contact office cards — flag + icon lines */
.office-city{ display: flex; align-items: center; gap: 10px; }
.office-flag{ flex: 0 0 22px; width: 22px; height: 15px; border-radius: 2px; object-fit: cover; box-shadow: 0 0 0 1px rgba(0,0,0,.12); }
.office-card .office-line{ display: flex; align-items: flex-start; gap: 10px; }
.office-line .icon-svg{ flex: 0 0 16px; width: 16px; height: 16px; margin-top: 3px; color: var(--link); }
.office-line a{ color: inherit; }
.office-line a:hover{ color: var(--link); }
.office-visit{ display: inline-flex; align-items: center; gap: 8px; }
.office-visit .icon-svg{ width: 16px; height: 16px; }

/* 2026-09-28 (โต้ง): dotted inner dividers between office cards (no outer
   frame) — right edge on every card except the last column, bottom edge on
   every row except the last. The :nth-last-child pair picks the last row
   whatever the card count. 3 cols → 2 cols → 1 col, matching .offices-grid. */
.contact-offices-panel .offices-grid{ gap: 0; margin-top: 32px; }
.contact-offices-panel .office-card{ padding: 32px clamp(16px, 2.6vw, 40px); border: 0 dotted var(--line); }
@media (min-width: 901px){
  .contact-offices-panel .office-card:not(:nth-child(3n)){ border-right-width: 1.5px; }
  .contact-offices-panel .office-card{ border-bottom-width: 1.5px; }
  .contact-offices-panel .office-card:nth-child(3n+1):nth-last-child(-n+3),
  .contact-offices-panel .office-card:nth-child(3n+1):nth-last-child(-n+3) ~ .office-card{ border-bottom-width: 0; }
}
@media (min-width: 641px) and (max-width: 900px){
  .contact-offices-panel .office-card:not(:nth-child(2n)){ border-right-width: 1.5px; }
  .contact-offices-panel .office-card{ border-bottom-width: 1.5px; }
  .contact-offices-panel .office-card:nth-child(2n+1):nth-last-child(-n+2),
  .contact-offices-panel .office-card:nth-child(2n+1):nth-last-child(-n+2) ~ .office-card{ border-bottom-width: 0; }
}
@media (max-width: 640px){
  .contact-offices-panel .office-card{ padding: 24px 0; }
  .contact-offices-panel .office-card:not(:last-child){ border-bottom-width: 1.5px; }
}

/* 2026-09-28: country label above the HQ name (flag + "Thailand") */
.contact-hq-country{ display: inline-flex; align-items: center; gap: 8px; margin: 0 0 6px; font-weight: 700; font-size: 18px; color: var(--link); }
.contact-hq-country .office-flag{ flex: 0 0 26px; width: 26px; height: 18px; }

/* 2026-09-28: Home "Service" (Figma 452:12966) — heading block + a full-bleed
   row of four photo cards. Hover / keyboard focus grows a card to 50% of the
   row (flex-basis 25% → 50%, the rest 50% ÷ 3) and the others' copy fades so it doesn't
   reflow in the narrow columns; copy has a fixed width for the same reason.
   Section stays on the page background (โต้ง moved Service to white). */
.home-service{ padding: 40px 0 40px; }
.home-service-head{ text-align: center; margin-bottom: 24px; }
.home-service-title{ margin: 0; font-family: var(--font-body); font-weight: 700; font-size: clamp(32px, 3.34vw, 48px); line-height: 1.2; color: var(--heading); }
.home-service-eyebrow{ margin: 0 0 24px; font-weight: 500; font-size: clamp(16px, 1.39vw, 20px); line-height: 1.4; letter-spacing: .02em; text-transform: uppercase; color: var(--link); }
.home-service-heading{ margin: 0 0 8px; font-family: var(--font-body); font-weight: 700; font-size: clamp(24px, 2.5vw, 36px); line-height: 1.22; color: var(--heading); }
.home-service-sub{ max-width: 890px; margin: 0 auto; font-weight: 700; font-size: clamp(16px, 1.39vw, 20px); line-height: 1.4; color: var(--link); }

.svc-accordion{ display: flex; height: clamp(480px, 47.8vw, 688px); margin: 0 24px; overflow: hidden; }
.svc-acc-card{
  position: relative; flex: 0 0 25%; min-width: 0; overflow: hidden; isolation: isolate;
  display: flex; flex-direction: column; justify-content: flex-end; padding: 24px; color: #ebf4f9;
  /* 2026-09-28 (โต้ง: "smoother"): slower, symmetric ease-in-out + a short
     hover-intent delay so sweeping the mouse across doesn't jolt the row */
  transition: flex-basis .8s cubic-bezier(.65, 0, .35, 1);
  outline: none;
}
.svc-acc-card::before{ content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(to top, rgba(0,0,0,.72), rgba(0,0,0,.45) 55%, rgba(0,0,0,.4)); transition: background .6s var(--ease-out); }
.svc-acc-card .svc-card-bg{ position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; object-fit: cover; transform: scale(1.06); transition: transform 1.2s cubic-bezier(.22, 1, .36, 1); }
.svc-acc-card.is-active .svc-card-bg{ transform: scale(1); }
.svc-acc-body{ display: flex; flex-direction: column; gap: 10px; width: min(300px, calc(100% - 0px)); }
/* exact split: active card 50%, the other three 50% ÷ 3. Driven by JS
   (.has-active / .is-active, "Service accordion" in main.js) instead of :hover —
   with :hover the growing card slid out from under the pointer, the neighbour
   took the hover, and the row flickered back and forth. */
.svc-accordion.has-active .svc-acc-card{ flex-basis: calc(50% / 3); }
.svc-accordion .svc-acc-card.is-active{ flex-basis: 50%; }
.svc-acc-card:focus-visible{ box-shadow: inset 0 0 0 3px var(--link); }
/* copy keeps one width while the card resizes (no mid-animation reflow) */
.svc-acc-card p{ margin: 0; font-weight: 300; font-size: clamp(15px, 1.25vw, 18px); line-height: 1.45; color: #ebf4f9; transition: opacity .5s ease .25s; }
.svc-acc-card p + p{ margin-top: 16px; }
.svc-accordion.has-active .svc-acc-card:not(.is-active) p{ opacity: 0; transition-delay: 0s; transition-duration: .3s; }
.svc-accordion.has-active .svc-acc-card:not(.is-active)::before{ background: rgba(0,0,0,.55); }
.svc-acc-card{ contain: layout paint; }
.home-service-cta{ display: flex; justify-content: center; margin-top: 24px; }
@media (max-width: 900px){
  .svc-accordion{ flex-direction: column; height: auto; margin: 0 16px; gap: 12px; }
  .svc-acc-card{ min-height: 300px; flex: none; }
  .svc-accordion.has-active .svc-acc-card,
  .svc-accordion .svc-acc-card.is-active{ flex-basis: auto; }
  .svc-acc-body{ width: 100%; }
  .svc-accordion.has-active .svc-acc-card:not(.is-active) p{ opacity: 1; }
}
@media (prefers-reduced-motion: reduce){ .svc-acc-card{ transition: none; } }
