/* global React, ReactDOM */
const { useState, useEffect, useRef } = React;
const C = window.FL_CONTENT;

/* Router uses ISO 'el' for Greek; the legacy content map is keyed 'gr'.
   Bridge them at the boundary so internal lookups keep working. */
const routerLangToContent = (l) => (l === 'el' ? 'gr' : 'en');
const contentLangToRouter = (l) => (l === 'gr' ? 'el' : 'en');

/* ---------------- Brand mark (FL waves) ---------------- */
function BrandMark({ size = 32, color = 'currentColor' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 64 64" fill="none">
      <defs>
        <linearGradient id="fl-grad" x1="0" y1="0" x2="64" y2="64">
          <stop offset="0" stopColor={color} stopOpacity="0.95" />
          <stop offset="1" stopColor={color} stopOpacity="0.55" />
        </linearGradient>
      </defs>
      <path d="M14 12 L14 44 L20 44 L20 30 L30 30 L30 24 L20 24 L20 18 L34 18 L34 12 Z" fill="url(#fl-grad)" />
      <path d="M40 12 L40 38 L52 38 L52 32 L46 32 L46 12 Z" fill="url(#fl-grad)" />
      <path d="M6 50 Q 18 42 32 50 T 58 50 L 58 56 Q 44 48 32 56 T 6 56 Z" fill={color} opacity="0.5" />
    </svg>
  );
}

/* ---------------- Splash ---------------- */
function Splash() {
  const [done, setDone] = useState(false);
  useEffect(() => {
    const t = setTimeout(() => {
      setDone(true);
      // Flags <html> so CSS starts the hero entrance exactly as the splash
      // lifts; persists so hero remounts from client-side nav animate at once.
      document.documentElement.classList.add('fl-splash-done');
    }, 1700);
    return () => clearTimeout(t);
  }, []);
  return (
    <div className={`splash ${done ? 'done' : ''}`}>
      <div className="splash-mark" style={{ width: 220, height: 'auto' }}><img src="/assets/frontline-logo-light.png" alt="FRONT LINE" width="600" height="200" style={{ width: '100%', height: 'auto', display: 'block' }} /></div>
      <div className="splash-bar"></div>
      <div className="splash-text mono">FRONT LINE · LOADING OPERATIONS</div>
    </div>
  );
}

/* ---------------- Nav ---------------- */
function Nav({ page, navigate, switchLang, lang }) {
  const [scrolled, setScrolled] = useState(false);
  const [menuOpen, setMenuOpen] = useState(false);
  const cl = routerLangToContent(lang);
  const t = C[cl].nav;
  const buildPath = window.FL_ROUTER.buildPath;
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 40);
    window.addEventListener('scroll', onScroll);
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  useEffect(() => {
    document.body.style.overflow = menuOpen ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [menuOpen]);
  const dark = page === 'home' && !scrolled && !menuOpen;
  const items = [['home', t.home], ['about', t.about], ['services', t.services], ['network', t.network], ['newsroom', t.newsroom || 'Newsroom'], ['contact', t.contact]];
  const go = (k) => { navigate(k); setMenuOpen(false); };
  const homeLabel = lang === 'el' ? 'FRONT LINE — Αρχική' : 'FRONT LINE — Home';
  const contactLabel = lang === 'el' ? 'Επικοινωνία με την FRONT LINE' : 'Contact FrontLine';
  return (
    <header className={`nav ${scrolled ? 'scrolled' : ''} ${dark ? 'dark' : ''} ${menuOpen ? 'menu-open' : ''}`}>
      <a className="brand" href={buildPath(lang, 'home')} aria-label={homeLabel} onClick={(e) => { e.preventDefault(); go('home'); }}>
        <img src="/assets/frontline-logo-dark.png" alt="FRONT LINE — return to home" width="600" height="200" className="brand-logo dark" decoding="async" />
        <img src="/assets/frontline-logo-light.png" alt="FRONT LINE — return to home" width="600" height="200" className="brand-logo light" decoding="async" />
      </a>
      <nav className="nav-links" aria-label={lang === 'el' ? 'Κύρια πλοήγηση' : 'Primary'}>
        {items.map(([k, label]) => (
          <a key={k} className={`nav-link ${page === k ? 'active' : ''}`} aria-current={page === k ? 'page' : undefined} onClick={(e) => { e.preventDefault(); go(k); }} href={buildPath(lang, k)}>{label}</a>
        ))}
      </nav>
      <div className="nav-right">
        <div className="lang-toggle mono" role="group" aria-label={lang === 'el' ? 'Επιλογή γλώσσας' : 'Language'}>
          <button className={`lang-btn ${lang === 'en' ? 'active' : ''}`} aria-pressed={lang === 'en'} aria-label="Switch site to English" onClick={() => switchLang('en')}>EN</button>
          <button className={`lang-btn ${lang === 'el' ? 'active' : ''}`} aria-pressed={lang === 'el'} aria-label="Αλλαγή σε Ελληνικά" onClick={() => switchLang('el')}>EL</button>
        </div>
        <button className="nav-burger" aria-label={lang === 'el' ? 'Μενού' : 'Menu'} aria-expanded={menuOpen} onClick={() => setMenuOpen(!menuOpen)}>
          <span></span><span></span><span></span>
        </button>
      </div>
      {menuOpen && (
        <div className="nav-drawer" onClick={(e) => { if (e.target === e.currentTarget) setMenuOpen(false); }}>
          <nav className="nav-drawer-inner" aria-label={lang === 'el' ? 'Κινητή πλοήγηση' : 'Mobile'}>
            {items.map(([k, label]) => (
              <a key={k} className={`nav-drawer-link ${page === k ? 'active' : ''}`} aria-current={page === k ? 'page' : undefined} onClick={(e) => { e.preventDefault(); go(k); }} href={buildPath(lang, k)}>{label}</a>
            ))}
          </nav>
        </div>
      )}
    </header>
  );
}

/* ---------------- Hero Background — Spinning Globe ---------------- */
function HeroBackdrop() {
  const canvasRef = useRef(null);
  const rafRef = useRef(0);

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let W = 0, H = 0, DPR = window.devicePixelRatio || 1;

    // Star field — positions stored as fractions of the canvas so they
    // survive resizes; density scales with area. Reseeded on resize.
    let stars = [];
    const seedStars = () => {
      const n = Math.round((W * H) / 11000);
      stars = Array.from({ length: n }, () => ({
        fx: Math.random(), fy: Math.random() * 0.82,
        r: 0.5 + Math.random() * 1.3,
        a: 0.18 + Math.random() * 0.45,
        tw: 0.4 + Math.random() * 1.3, // twinkle speed (rad/s)
        ph: Math.random() * Math.PI * 2,
      }));
    };

    const resize = () => {
      DPR = window.devicePixelRatio || 1;
      const r = canvas.getBoundingClientRect();
      W = r.width; H = r.height;
      canvas.width = W * DPR; canvas.height = H * DPR;
      ctx.setTransform(DPR, 0, 0, DPR, 0, 0);
      seedStars();
      // Resizing wipes the buffer; under reduced-motion no loop is running
      // to repaint it, so schedule a single fresh frame.
      if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
        cancelAnimationFrame(rafRef.current);
        rafRef.current = requestAnimationFrame((ts) => draw(ts));
      }
    };

    // Basemap projection — shared between the office dots and the land texture
    // so they're guaranteed to line up. Tweaking these without re-deriving
    // offices/land will desync them.
    const PROJ = {
      X0: 549.7,          // basemap x pixel where lon = 0
      X_PER_LON: 3.56,    // px per degree of longitude
      Y0: 488.3,          // basemap y pixel where lat = 0
      Y_PER_MERC: -224.3, // px per Mercator unit (negative: y grows southward)
    };
    // basemap pixel → sphere (lat, lon) using inverse Mercator.
    const pixelToLatLon = (mx, my) => {
      const lon = (mx - PROJ.X0) / PROJ.X_PER_LON;
      const ymerc = (PROJ.Y0 - my) / -PROJ.Y_PER_MERC;
      const lat = (2 * Math.atan(Math.exp(ymerc)) - Math.PI / 2) * 180 / Math.PI;
      return [lat, lon];
    };

    // Each office is anchored to a basemap pixel (matching where the Network
    // tab places it). Sphere coords are derived via pixelToLatLon — since the
    // land grid uses the same projection, the dot is guaranteed to sit on its
    // country regardless of how non-standard the basemap's projection is.
    // [mx, my] are pixel coords in world-map.png's native 1198×784.
    const officePixels = [
      [625,  315, 'PIR'],   // Piraeus      — from network-map gr
      [560,  255, 'RTM'],   // Rotterdam    — from network-map nl
      [1058, 302, 'TYO'],   // Tokyo        — from network-map jp-tk
      [962,  308, 'SHA'],   // Shanghai     — from network-map cn
      [1003, 318, 'PUS'],   // Busan        — extrapolated SE of Seoul (988,298)
      [940,  475, 'SIN'],   // Singapore    — from network-map sg
      [933,  467, 'KUL'],   // Kuala Lumpur — extrapolated NW of Singapore
    ];
    const offices = officePixels.map(([mx, my, code]) => {
      const [lat, lon] = pixelToLatLon(mx, my);
      return [lat, lon, code];
    });

    // Real continent outlines — sampled from world-map.png + japan.png (the same
    // pair the Network page uses; the basemap PNG omits Japan, hence the overlay).
    // Built once after both images load; rendered as a transparent blue texture
    // on the globe.
    let landGrid = null;
    (() => {
      const loadImg = (src) => new Promise((resolve) => {
        const im = new Image();
        im.onload = () => resolve(im);
        im.onerror = () => resolve(null);
        im.src = src;
      });
      const readPixels = (im) => {
        const w = im.naturalWidth, h = im.naturalHeight;
        const off = document.createElement('canvas');
        off.width = w; off.height = h;
        const oc = off.getContext('2d');
        oc.drawImage(im, 0, 0);
        try { return { w, h, data: oc.getImageData(0, 0, w, h).data }; }
        catch (e) { return null; }
      };

      Promise.all([loadImg('/world-map.png'), loadImg('/japan.png')]).then(([wmImg, jpImg]) => {
        if (!wmImg) return;
        const wm = readPixels(wmImg);
        if (!wm) return;
        const jp = jpImg ? readPixels(jpImg) : null;

        // Use the SAME projection params as the office dots above — critical
        // for keeping dots and continents aligned.
        const { X0, X_PER_LON, Y0, Y_PER_MERC } = PROJ;

        // japan.png overlay placement in basemap coordinates — must stay in
        // sync with network-map.jsx's <image href="japan.png" .../>.
        const JP_X = 965, JP_Y = 231, JP_W = 150, JP_H = 150;

        // Sphere lat/lon coverage of the basemap.
        const LAT_TOP = 77, LAT_BOT = -60;

        // Step controls density of the land texture on the globe.
        const STEP = 0.7;
        const grid = [];
        for (let lat = LAT_BOT + 0.5; lat <= LAT_TOP - 0.5; lat += STEP) {
          const ymerc = Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360));
          const my = Math.floor(Y0 + Y_PER_MERC * ymerc);
          if (my < 0 || my >= wm.h) continue;
          for (let lon = -180; lon < 180; lon += STEP) {
            const mx = Math.floor(X0 + lon * X_PER_LON);
            if (mx < 0 || mx >= wm.w) continue;
            // Basemap: land pixels are near-white; ocean is light gray.
            let isLand = wm.data[(my * wm.w + mx) * 4] > 233;
            // Japan overlay: fills the islands the basemap is missing.
            if (!isLand && jp &&
                mx >= JP_X && mx < JP_X + JP_W &&
                my >= JP_Y && my < JP_Y + JP_H) {
              const px = Math.floor((mx - JP_X) / JP_W * jp.w);
              const py = Math.floor((my - JP_Y) / JP_H * jp.h);
              const a = jp.data[(py * jp.w + px) * 4 + 3];
              if (a > 60) isLand = true;
            }
            if (isLand) grid.push([lat, lon]);
          }
        }
        landGrid = grid;
      });
    })();

    // Project lat/lon onto sphere with rotation
    // Returns {x, y, z, visible} — z>0 means front-facing
    const project = (lat, lon, rotLon, cx, cy, R) => {
      const φ = lat * Math.PI / 180;
      const λ = (lon + rotLon) * Math.PI / 180;
      const x = Math.cos(φ) * Math.sin(λ);
      const y = -Math.sin(φ);
      const z = Math.cos(φ) * Math.cos(λ);
      return { x: cx + x * R, y: cy + y * R, z, visible: z > 0 };
    };

    // Like project(), but lifts the point off the surface by `lift` (fraction
    // of R). A lifted point stays visible slightly past the limb — it is
    // hidden only when it sits behind the sphere AND inside the disc outline.
    const projectLifted = (lat, lon, rotLon, cx, cy, R, lift) => {
      const φ = lat * Math.PI / 180;
      const λ = (lon + rotLon) * Math.PI / 180;
      const x = Math.cos(φ) * Math.sin(λ);
      const y = -Math.sin(φ);
      const z = Math.cos(φ) * Math.cos(λ);
      const m = 1 + lift;
      return { x: cx + x * R * m, y: cy + y * R * m, z, visible: z > 0 || (x * x + y * y) * m * m > 1 };
    };

    // Great-circle arc between two lat/lon points, sampled
    const arcPoints = (lat1, lon1, lat2, lon2, n = 40) => {
      const pts = [];
      const φ1 = lat1 * Math.PI / 180, λ1 = lon1 * Math.PI / 180;
      const φ2 = lat2 * Math.PI / 180, λ2 = lon2 * Math.PI / 180;
      const d = 2 * Math.asin(Math.sqrt(
        Math.sin((φ2 - φ1) / 2) ** 2 +
        Math.cos(φ1) * Math.cos(φ2) * Math.sin((λ2 - λ1) / 2) ** 2
      ));
      if (d === 0) return [[lat1, lon1]];
      for (let i = 0; i <= n; i++) {
        const f = i / n;
        const A = Math.sin((1 - f) * d) / Math.sin(d);
        const B = Math.sin(f * d) / Math.sin(d);
        const x = A * Math.cos(φ1) * Math.cos(λ1) + B * Math.cos(φ2) * Math.cos(λ2);
        const y = A * Math.cos(φ1) * Math.sin(λ1) + B * Math.cos(φ2) * Math.sin(λ2);
        const z = A * Math.sin(φ1) + B * Math.sin(φ2);
        const lat = Math.atan2(z, Math.sqrt(x * x + y * y)) * 180 / Math.PI;
        const lon = Math.atan2(y, x) * 180 / Math.PI;
        pts.push([lat, lon]);
      }
      return pts;
    };

    // Pre-compute arc geometry from Piraeus to others. altPeak lifts each
    // route off the surface like a flight path — longer hauls fly higher.
    const CYCLE = 7; // seconds per departure on every route
    const arcs = offices.slice(1).map((o, i) => {
      const φ1 = offices[0][0] * Math.PI / 180, λ1 = offices[0][1] * Math.PI / 180;
      const φ2 = o[0] * Math.PI / 180, λ2 = o[1] * Math.PI / 180;
      const d = 2 * Math.asin(Math.sqrt(
        Math.sin((φ2 - φ1) / 2) ** 2 +
        Math.cos(φ1) * Math.cos(φ2) * Math.sin((λ2 - λ1) / 2) ** 2
      ));
      return {
        pts: arcPoints(offices[0][0], offices[0][1], o[0], o[1], 60),
        delay: i * 1.2,
        targetIdx: i + 1,
        altPeak: 0.035 + Math.min(0.075, d * 0.045),
      };
    });

    // Directional light (upper-left, toward the viewer) — keep in sync with
    // the sphere-gradient highlight in draw(). Pre-normalized.
    const LIGHT = [-0.45, -0.52, 0.727];
    // 32-step colour LUT for land dots: deep steel in shadow → bright sky in
    // light. Pre-built strings — a template literal per dot per frame (~14k)
    // is too hot, and bucketing lets fillStyle changes be skipped entirely
    // when consecutive dots share a shade.
    const LAND_LUT = [];
    for (let i = 0; i < 32; i++) {
      const s = i / 31;
      LAND_LUT.push(`rgba(${Math.round(88 + 97 * s)},${Math.round(150 + 75 * s)},${Math.round(205 + 45 * s)},${(0.09 + 0.52 * s).toFixed(3)})`);
    }

    let t0 = performance.now();
    let parked = false; // true while the hero is scrolled out of view — loop pauses
    const draw = (now) => {
      const t = (now - t0) / 1000;
      // Pendulum sweep instead of a full spin: every office sits between
      // lon 3° (RTM) and 140° (TYO), so a 360° rotation hides the entire
      // network behind the globe for half of each turn. Oscillating
      // rotLon over [-100°, -10°] keeps Piraeus on the visible face at all
      // times and sweeps the camera Europe ↔ East Asia. Phase offset opens
      // on the Europe/Piraeus view.
      const rotLon = -55 + 45 * Math.sin(t * 0.18 + 1.12);
      // Center sits below the midline: the network lives in the northern
      // hemisphere, so this keeps the lifted Europe→Asia arcs (which peak
      // ~10% above the surface) inside the canvas instead of cropped.
      const cx = W / 2, cy = H * 0.58;
      const R = Math.min(W, H) * 0.50;
      // Highlight point on the sphere, aligned with LIGHT — shared by the
      // base gradient and the night-side shading so they agree.
      const hx = cx - R * 0.32, hy = cy - R * 0.36;

      ctx.clearRect(0, 0, W, H);

      // Background gradient
      const bg = ctx.createLinearGradient(0, 0, 0, H);
      bg.addColorStop(0, '#061634');
      bg.addColorStop(0.5, '#0A1F3D');
      bg.addColorStop(1, '#163b66');
      ctx.fillStyle = bg;
      ctx.fillRect(0, 0, W, H);

      // Star field — faint slow twinkle (celestial-navigation nod). The
      // sphere paints over whatever falls behind the globe.
      for (let i = 0; i < stars.length; i++) {
        const st = stars[i];
        const al = st.a * (0.55 + 0.45 * Math.sin(t * st.tw + st.ph));
        if (al < 0.02) continue;
        ctx.fillStyle = `rgba(205,228,250,${al})`;
        ctx.fillRect(st.fx * W, st.fy * H, st.r, st.r);
      }

      // Glow halos
      const g1 = ctx.createRadialGradient(W * 0.7, H * 0.3, 0, W * 0.7, H * 0.3, W * 0.5);
      g1.addColorStop(0, 'rgba(127,179,213,0.22)');
      g1.addColorStop(1, 'rgba(127,179,213,0)');
      ctx.fillStyle = g1;
      ctx.fillRect(0, 0, W, H);

      // Atmosphere glow around globe — biased slightly toward the light
      const atm = ctx.createRadialGradient(cx - R * 0.06, cy - R * 0.07, R * 0.95, cx, cy, R * 1.3);
      atm.addColorStop(0, 'rgba(127,179,213,0.28)');
      atm.addColorStop(0.5, 'rgba(127,179,213,0.09)');
      atm.addColorStop(1, 'rgba(127,179,213,0)');
      ctx.fillStyle = atm;
      ctx.beginPath();
      ctx.arc(cx, cy, R * 1.3, 0, Math.PI * 2);
      ctx.fill();

      // Globe sphere — dark base, highlight aligned with LIGHT
      const sphere = ctx.createRadialGradient(hx, hy, 0, cx, cy, R);
      sphere.addColorStop(0, '#16365e');
      sphere.addColorStop(0.65, '#0A1F3D');
      sphere.addColorStop(1, '#03101f');
      ctx.fillStyle = sphere;
      ctx.beginPath();
      ctx.arc(cx, cy, R, 0, Math.PI * 2);
      ctx.fill();

      // Latitude lines (every 20°)
      ctx.strokeStyle = 'rgba(127,179,213,0.08)';
      ctx.lineWidth = 0.6;
      for (let lat = -80; lat <= 80; lat += 20) {
        ctx.beginPath();
        let started = false;
        for (let lon = -180; lon <= 180; lon += 4) {
          const p = project(lat, lon, rotLon, cx, cy, R);
          if (p.visible) {
            if (!started) { ctx.moveTo(p.x, p.y); started = true; }
            else ctx.lineTo(p.x, p.y);
          } else {
            started = false;
          }
        }
        ctx.stroke();
      }

      // Longitude meridians (every 20°)
      for (let lon = -180; lon < 180; lon += 20) {
        ctx.beginPath();
        let started = false;
        for (let lat = -80; lat <= 80; lat += 4) {
          const p = project(lat, lon, rotLon, cx, cy, R);
          if (p.visible) {
            if (!started) { ctx.moveTo(p.x, p.y); started = true; }
            else ctx.lineTo(p.x, p.y);
          } else {
            started = false;
          }
        }
        ctx.stroke();
      }

      // Land texture — transparent blue rendering of the network-tab map,
      // projected onto the sphere and lit by LIGHT so the globe reads as 3D:
      // bright sky-blue toward the upper-left, falling into shadow on the
      // far side. For orthographic projection the screen offset over R IS
      // the unit normal's x/y, so no extra trig is needed.
      if (landGrid) {
        const dotSize = Math.max(1.2, R * 0.006);
        let lastIdx = -1;
        for (let i = 0; i < landGrid.length; i++) {
          const [lat, lon] = landGrid[i];
          const p = project(lat, lon, rotLon, cx, cy, R);
          if (!p.visible) continue;
          const nx = (p.x - cx) / R, ny = (p.y - cy) / R;
          const diff = nx * LIGHT[0] + ny * LIGHT[1] + p.z * LIGHT[2];
          let s = 0.10 + 0.58 * (diff > 0 ? diff : 0) + 0.28 * p.z;
          if (s > 1) s = 1;
          const idx = (s * 31) | 0;
          if (idx !== lastIdx) { ctx.fillStyle = LAND_LUT[idx]; lastIdx = idx; }
          ctx.fillRect(p.x - dotSize / 2, p.y - dotSize / 2, dotSize, dotSize);
        }
      }

      // Night-side shading — darkens the far-from-light side of everything
      // painted so far (ocean, graticule, land). Arcs and ports draw after
      // this, staying bright so they read as emissive.
      const shade = ctx.createRadialGradient(hx, hy, R * 0.5, hx, hy, R * 1.62);
      shade.addColorStop(0, 'rgba(2,8,20,0)');
      shade.addColorStop(0.55, 'rgba(2,8,20,0)');
      shade.addColorStop(1, 'rgba(2,8,20,0.34)');
      ctx.fillStyle = shade;
      ctx.beginPath();
      ctx.arc(cx, cy, R, 0, Math.PI * 2);
      ctx.fill();

      // Trade-route arcs — great-circles lifted off the surface like flight
      // paths, each with a comet trail and an arrival ripple at the
      // destination port.
      arcs.forEach((arc) => {
        const u = (t - arc.delay) % CYCLE; // seconds into the current cycle (negative before first departure)
        if (u < 0) return;
        const phase = u / CYCLE;
        const n = arc.pts.length - 1;
        const lifted = arc.pts.map(([lat, lon], k) =>
          projectLifted(lat, lon, rotLon, cx, cy, R, Math.sin(k / n * Math.PI) * arc.altPeak));

        // Static dashed full arc (front-side only)
        ctx.strokeStyle = 'rgba(127,179,213,0.20)';
        ctx.lineWidth = 0.8;
        ctx.setLineDash([2, 5]);
        ctx.beginPath();
        let started = false;
        for (const p of lifted) {
          if (p.visible) {
            if (!started) { ctx.moveTo(p.x, p.y); started = true; }
            else ctx.lineTo(p.x, p.y);
          } else { started = false; }
        }
        ctx.stroke();
        ctx.setLineDash([]);

        // Comet trail — transparent tail fading up to a bright head
        const headIdx = Math.min(n, Math.floor(phase * n));
        const tailIdx = Math.max(0, Math.floor((phase - 0.22) * n));
        const head = lifted[headIdx];
        if (headIdx > tailIdx && head.visible) {
          const grad = ctx.createLinearGradient(lifted[tailIdx].x, lifted[tailIdx].y, head.x, head.y);
          grad.addColorStop(0, 'rgba(127,179,213,0)');
          grad.addColorStop(1, 'rgba(214,238,252,0.9)');
          ctx.strokeStyle = grad;
          ctx.lineWidth = 1.6;
          ctx.lineCap = 'round';
          ctx.beginPath();
          let ss = false;
          for (let k = tailIdx; k <= headIdx; k++) {
            const p = lifted[k];
            if (p.visible) {
              if (!ss) { ctx.moveTo(p.x, p.y); ss = true; }
              else ctx.lineTo(p.x, p.y);
            } else { ss = false; }
          }
          ctx.stroke();

          // Leading dot
          ctx.fillStyle = '#dff1fc';
          ctx.shadowColor = '#7FB3D5';
          ctx.shadowBlur = 10;
          ctx.beginPath();
          ctx.arc(head.x, head.y, 2.5, 0, Math.PI * 2);
          ctx.fill();
          ctx.shadowBlur = 0;
        }

        // Arrival ripple at the destination, just after each hand-off.
        // Skipped during the first cycle — nothing has arrived yet.
        if (t - arc.delay >= CYCLE && u < 0.9) {
          const tp = offices[arc.targetIdx];
          const p = project(tp[0], tp[1], rotLon, cx, cy, R);
          if (p.visible) {
            const k = u / 0.9;
            ctx.strokeStyle = `rgba(170,215,245,${0.45 * (1 - k)})`;
            ctx.lineWidth = 1.1;
            ctx.beginPath();
            ctx.arc(p.x, p.y, 3 + k * 15, 0, Math.PI * 2);
            ctx.stroke();
          }
        }
      });

      // Office ports — expanding sonar rings instead of a blobby halo;
      // Piraeus (index 0, HQ) reads strongest.
      offices.forEach(([lat, lon, code], i) => {
        const p = project(lat, lon, rotLon, cx, cy, R);
        if (!p.visible) return;
        const limb = 0.35 + p.z * 0.65; // dim markers approaching the edge
        const isHQ = i === 0;

        // Two staggered rings per port
        for (let ring = 0; ring < 2; ring++) {
          const rp = (t * 0.42 + i * 0.31 + ring * 0.5) % 1;
          const ra = (1 - rp) * (isHQ ? 0.5 : 0.3) * limb;
          if (ra < 0.02) continue;
          ctx.strokeStyle = `rgba(159,208,238,${ra})`;
          ctx.lineWidth = isHQ ? 1.2 : 1;
          ctx.beginPath();
          ctx.arc(p.x, p.y, 2.5 + rp * (isHQ ? 17 : 11), 0, Math.PI * 2);
          ctx.stroke();
        }

        // Core
        ctx.fillStyle = isHQ ? '#ffffff' : '#cfe6f5';
        ctx.shadowColor = '#7FB3D5';
        ctx.shadowBlur = isHQ ? 10 : 6;
        ctx.beginPath();
        ctx.arc(p.x, p.y, isHQ ? 2.8 : 2.1, 0, Math.PI * 2);
        ctx.fill();
        ctx.shadowBlur = 0;

        // Label
        ctx.fillStyle = `rgba(207,230,245,${(isHQ ? 0.5 : 0.32) + p.z * 0.5})`;
        ctx.font = isHQ ? '600 9.5px "Geist Mono", monospace' : '9px "Geist Mono", monospace';
        ctx.fillText(code, p.x + (isHQ ? 9 : 7), p.y + 3);
      });

      // Globe edge — faint full ring plus a rim-light along the lit limb
      ctx.strokeStyle = 'rgba(127,179,213,0.20)';
      ctx.lineWidth = 1;
      ctx.beginPath();
      ctx.arc(cx, cy, R, 0, Math.PI * 2);
      ctx.stroke();
      const rim = ctx.createLinearGradient(cx - 0.654 * R, cy - 0.756 * R, cx + 0.39 * R, cy + 0.45 * R);
      rim.addColorStop(0, 'rgba(176,218,248,0.55)');
      rim.addColorStop(0.45, 'rgba(176,218,248,0.10)');
      rim.addColorStop(0.75, 'rgba(176,218,248,0)');
      ctx.strokeStyle = rim;
      ctx.lineWidth = 1.4;
      ctx.beginPath();
      ctx.arc(cx, cy, R - 0.5, 0, Math.PI * 2);
      ctx.stroke();

      // Soft scrim behind the left-side headline so the text keeps contrast
      // against the brighter lit land.
      const scrim = ctx.createLinearGradient(0, 0, W * 0.58, 0);
      scrim.addColorStop(0, 'rgba(4,12,28,0.36)');
      scrim.addColorStop(1, 'rgba(4,12,28,0)');
      ctx.fillStyle = scrim;
      ctx.fillRect(0, 0, W * 0.58, H);

      // Honour reduced-motion: paint a single static frame instead of spinning
      if (!parked && !window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
        rafRef.current = requestAnimationFrame(draw);
      }
    };

    resize();
    window.addEventListener('resize', resize);
    // Re-measure when the canvas box itself changes without a window resize
    // (font-load reflow, mobile URL-bar collapse, late layout).
    const ro = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(resize) : null;
    if (ro) ro.observe(canvas);
    // Park the loop while the hero is scrolled out of view — no reason to
    // burn frames behind the rest of the page.
    const io = typeof IntersectionObserver !== 'undefined' ? new IntersectionObserver((entries) => {
      const vis = entries.some(e => e.isIntersecting);
      if (vis === !parked) return;
      parked = !vis;
      cancelAnimationFrame(rafRef.current);
      if (!parked) rafRef.current = requestAnimationFrame(draw);
    }) : null;
    if (io) io.observe(canvas);

    rafRef.current = requestAnimationFrame(draw);

    return () => {
      cancelAnimationFrame(rafRef.current);
      window.removeEventListener('resize', resize);
      if (ro) ro.disconnect();
      if (io) io.disconnect();
    };
  }, []);

  return (
    <div className="hero-anim">
      <canvas ref={canvasRef} className="hero-globe-canvas"></canvas>
      <div className="hero-readout mono">
        <span className="hero-readout-line"><span className="hero-readout-dim">LAT</span> 37.9420° N</span>
        <span className="hero-readout-line"><span className="hero-readout-dim">LON</span> 23.6464° E</span>
        <span className="hero-readout-line"><span className="hero-readout-dim">PIR</span> Piraeus, GR</span>
        <span className="hero-readout-line"><span className="hero-readout-dim">TEL</span> <a href="tel:+302104200051" className="hero-readout-tel">+30 210 4200 051</a></span>
        <span className="hero-readout-line hero-readout-live"><span className="live-dot"></span>Vessel desk · 24 / 7</span>
      </div>
      <svg className="hero-waves" viewBox="0 0 1440 120" preserveAspectRatio="none">
        <path className="hero-wave-1" d="M0,60 Q180,30 360,60 T720,60 T1080,60 T1440,60 V120 H0 Z" fill="rgba(127,179,213,0.05)"/>
        <path className="hero-wave-2" d="M0,80 Q180,50 360,80 T720,80 T1080,80 T1440,80 V120 H0 Z" fill="rgba(127,179,213,0.07)"/>
        <path className="hero-wave-3" d="M0,100 Q180,75 360,100 T720,100 T1080,100 T1440,100 V120 H0 Z" fill="rgba(10,31,61,0.5)"/>
      </svg>
    </div>
  );
}

/* ---------------- Hero ---------------- */
function Hero({ lang, navigate }) {
  // `lang` here is the content-language key (already converted upstream — 'en' or 'gr').
  // Don't re-run routerLangToContent or 'gr' would fall through to 'en' and skip the Greek copy.
  const t = C[lang].hero;
  const routerLang = contentLangToRouter(lang);
  const buildPath = window.FL_ROUTER.buildPath;
  const [active, setActive] = useState(0);
  useEffect(() => { const i = setInterval(() => setActive(a => (a + 1) % t.rail.length), 2400); return () => clearInterval(i); }, [t.rail.length]);
  return (
    <section className="hero">
      <HeroBackdrop />
      <div className="hero-content">
        <div className="hero-top">
          <div>{t.eyebrow}</div>
          <div className="live"><span className="live-dot"></span>{t.live}</div>
        </div>
        <h1>
          {t.title_a} <span className="serif">{t.title_b}</span> {t.title_c}
        </h1>
        <p className="lede">{t.lede}</p>
        <div className="hero-actions">
          <a href={buildPath(routerLang, 'services')} onClick={(e) => { e.preventDefault(); navigate('services'); }} className="btn btn-light">
            {t.cta_secondary}
            <svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3 8h10m0 0L9 4m4 4l-4 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/></svg>
          </a>
          {/* Mobile twin of the hero-rail portal link — the rail is hidden ≤1100px,
              so this copy carries the portal CTA on tablet/phone (hidden on desktop via CSS). */}
          <a
            href="https://cp.frontline-ltd.com/login.php"
            className="rail-portal hero-portal-mobile"
            target="_blank"
            rel="noopener noreferrer"
            aria-label="Connect to client portal (opens in a new tab)"
            title="Connect to client portal"
          >
            <span className="rail-portal-dot" aria-hidden="true"></span>
            <span className="rail-portal-label">Connect to Portal</span>
            <svg width="12" height="12" viewBox="0 0 16 16" fill="none" aria-hidden="true">
              <path d="M3 8h10m0 0L9 4m4 4l-4 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
          </a>
        </div>
      </div>
      <div className="hero-rail">
        {t.rail.map((r, i) => (
          <a
            key={i}
            href={buildPath(routerLang, 'services')}
            onClick={(e) => { e.preventDefault(); navigate('services'); }}
            className={`rail-item ${i === active ? 'active' : ''}`}
            onMouseEnter={() => setActive(i)}
          >{String(i + 1).padStart(2, '0')} · {r}</a>
        ))}
        <a
          href="https://cp.frontline-ltd.com/login.php"
          className="rail-portal"
          target="_blank"
          rel="noopener noreferrer"
          aria-label="Connect to client portal (opens in a new tab)"
          title="Connect to client portal"
        >
          <span className="rail-portal-dot" aria-hidden="true"></span>
          <span className="rail-portal-label">Connect to Portal</span>
          <svg width="12" height="12" viewBox="0 0 16 16" fill="none" aria-hidden="true">
            <path d="M3 8h10m0 0L9 4m4 4l-4 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        </a>
      </div>
      <div className="hero-meta">
        {t.meta.map((m, i) => (
          <div key={i} className="meta-item">
            <div className="num">{m.num}{m.sub && <span className="serif" style={{ fontSize: 18, marginLeft: 6 }}>{m.sub}</span>}</div>
            <div className="lab">{m.label}</div>
          </div>
        ))}
      </div>
    </section>
  );
}

/* ---------------- Why ---------------- */
function ValueIcon({ n }) {
  // simple geometric glyphs — no AI ship art
  const paths = {
    '01': <><circle cx="18" cy="18" r="14" stroke="currentColor" strokeWidth="1.5"/><circle cx="18" cy="18" r="3" fill="currentColor"/></>,
    '02': <><rect x="4" y="14" width="28" height="14" stroke="currentColor" strokeWidth="1.5"/><path d="M4 22h28M14 14v14" stroke="currentColor" strokeWidth="1.5"/></>,
    '03': <><path d="M6 12l12 6 12-6M6 12v14l12 6M30 12v14l-12 6" stroke="currentColor" strokeWidth="1.5" fill="none"/></>,
    '04': <><path d="M6 30V12l8-4 8 4v18" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinejoin="round"/><path d="M22 30V18h8v12" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinejoin="round"/><path d="M3 30h30" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/><rect x="9" y="14" width="2.5" height="3" fill="currentColor"/><rect x="16.5" y="14" width="2.5" height="3" fill="currentColor"/><rect x="9" y="20" width="2.5" height="3" fill="currentColor"/><rect x="16.5" y="20" width="2.5" height="3" fill="currentColor"/><rect x="25" y="21" width="2.5" height="3" fill="currentColor"/></>,
    '05': <><rect x="6" y="6" width="24" height="24" stroke="currentColor" strokeWidth="1.5"/><path d="M11 14h14M11 18h14M11 22h8" stroke="currentColor" strokeWidth="1.5"/></>,
    '06': <><path d="M6 28L18 6l12 22" stroke="currentColor" strokeWidth="1.5" fill="none"/><path d="M12 28l6-11 6 11" stroke="currentColor" strokeWidth="1.5" fill="none"/></>,
  };
  return <svg className="value-glyph" viewBox="0 0 36 36" fill="none">{paths[n]}</svg>;
}

function Why({ lang, navigate }) {
  const t = C[lang].why;
  const go = (action) => {
    if (!action) return;
    if (action.page) {
      if (navigate) navigate(action.page);
      else if (window.__fl_setPage) window.__fl_setPage(action.page);
      return;
    }
    if (action.scrollTo) {
      const el = document.querySelector(action.scrollTo);
      if (!el) return;
      const top = el.getBoundingClientRect().top + window.pageYOffset - 80;
      window.scrollTo({ top, behavior: 'smooth' });
    }
  };
  return (
    <section className="section section-light">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
            <h2>{t.title_a}<br/>{t.title_b}<br/><span className="serif">{t.title_c}</span></h2>
          </div>
          <p className="desc right">{t.desc}</p>
        </div>
        <div className="values reveal">
          {t.values.map((v, i) => (
            <div key={i} className={`value ${v.action ? 'value--interactive' : ''}`}>
              <ValueIcon n={v.n} />
              <div className="value-num mono">{v.n}</div>
              <h3>{v.t}</h3>
              <p>{v.p}</p>
              {v.action && (
                <button
                  type="button"
                  className="value-cta"
                  onClick={() => go(v.action)}
                  aria-label={v.action.label + ' — ' + v.t}
                >
                  <span>{v.action.label}</span>
                  <svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true">
                    <path d="M3 8h10m0 0L9 4m4 4l-4 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/>
                  </svg>
                </button>
              )}
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ---------------- Audience ---------------- */
function Audience({ lang }) {
  const t = C[lang].audience;
  const [tab, setTab] = useState(0);
  const cur = t.tabs[tab];
  return (
    <section className="section section-bg">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
            <h2>{t.title_a} <span className="serif">{t.title_b}</span><br/>{t.title_c}</h2>
          </div>
          <p className="desc right">{t.desc}</p>
        </div>
        <div className="audience reveal">
          <div className="aud-tabs">
            {t.tabs.map((tb, i) => (
              <button key={tb.id} className={`aud-tab ${i === tab ? 'active' : ''}`} onClick={() => setTab(i)}>
                <span>{String(i + 1).padStart(2, '0')} &nbsp; {tb.label}</span>
                <span className="arr">→</span>
              </button>
            ))}
          </div>
          <div className="aud-panel" key={tab}>
            <div className="aud-panel-content">
              <h3>{cur.h}</h3>
              <p className="pitch">{cur.p}</p>
              <ul>{cur.points.map((p, i) => <li key={i}>{p}</li>)}</ul>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ---------------- Services ---------------- */
function ServiceIcon({ n }) {
  const ps = {
    '01': <><path d="M4 24h32M4 24c0-6 4-10 10-10h12c6 0 10 4 10 10M10 14V8M30 14V8" stroke="currentColor" strokeWidth="1.5" fill="none"/></>,
    '02': <><rect x="6" y="14" width="28" height="18" stroke="currentColor" strokeWidth="1.5" fill="none"/><path d="M6 22h28M14 14V8h12v6" stroke="currentColor" strokeWidth="1.5" fill="none"/></>,
    '03': <><path d="M4 26l16-12 16 12M4 32h32M10 26v6M30 26v6M20 14V6" stroke="currentColor" strokeWidth="1.5" fill="none"/></>,
    '04': <><circle cx="20" cy="20" r="14" stroke="currentColor" strokeWidth="1.5" fill="none"/><path d="M20 6v28M6 20h28" stroke="currentColor" strokeWidth="1.2"/></>,
    '05': <><path d="M8 8h24v8H8zM8 24h24v8H8z" stroke="currentColor" strokeWidth="1.5" fill="none"/><circle cx="14" cy="12" r="1.5" fill="currentColor"/><circle cx="14" cy="28" r="1.5" fill="currentColor"/></>,
    '06': <><path d="M6 16h28v16H6zM6 16l14-10 14 10" stroke="currentColor" strokeWidth="1.5" fill="none"/></>,
    '07': <><path d="M20 6l12 4v10c0 8-5 14-12 16-7-2-12-8-12-16V10z" stroke="currentColor" strokeWidth="1.5" fill="none"/></>,
    '08': <><path d="M8 8h18l8 8v18H8z" stroke="currentColor" strokeWidth="1.5" fill="none"/><path d="M26 8v8h8M14 22h12M14 28h8" stroke="currentColor" strokeWidth="1.5"/></>,
  };
  return <svg className="svc-icon" viewBox="0 0 40 40" fill="none">{ps[n]}</svg>;
}

function Services({ lang }) {
  const t = C[lang].services;
  const [openSubs, setOpenSubs] = React.useState({});
  const moreLabel = lang === 'el' ? 'Διαβάστε περισσότερα' : 'Read more';
  const lessLabel = lang === 'el' ? 'Λιγότερα' : 'Show less';
  return (
    <section className="section section-light">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
          </div>
          <p className="desc right">{t.desc}</p>
        </div>
        <div className="svc-grid reveal">
          {t.items.map((s) => {
            const isOpen = !!openSubs[s.n];
            return (
            <div key={s.n} className={`svc-card ${s.subs ? 'svc-card-has-subs' : ''} ${isOpen ? 'is-open' : ''}`}>
              <span className="svc-num mono">{s.n}</span>
              <ServiceIcon n={s.n} />
              <h3>{s.t}{s.sub && <span className="svc-sub mono"> · {s.sub}</span>}</h3>
              <p>{s.p}</p>
              {s.subs && isOpen && (
                <ul className="svc-subs">
                  {s.subs.map((sb, i) => (
                    <li key={i}><span className="svc-sub-t">{sb.t}</span><span className="svc-sub-p">{sb.p}</span></li>
                  ))}
                </ul>
              )}
              {s.subs ? (
                <button type="button" className="svc-readmore mono" onClick={() => setOpenSubs(o => ({ ...o, [s.n]: !o[s.n] }))} aria-expanded={isOpen}>
                  {isOpen ? lessLabel : moreLabel} <svg width="9" height="9" viewBox="0 0 16 16" style={{transform: isOpen ? 'rotate(90deg)' : 'none', transition: 'transform 200ms ease'}}><path d="M3 8h10m0 0L9 4m4 4l-4 4" stroke="currentColor" strokeWidth="1.4" fill="none" strokeLinecap="round"/></svg>
                </button>
              ) : null}
            </div>
            );
          })}
        </div>
      </div>
    </section>
  );
}

/* ---------------- Departments ---------------- */
function DeptIcon({ n }) {
  const paths = {
    '01': <><circle cx="18" cy="18" r="12" stroke="currentColor" strokeWidth="1.4" fill="none"/><path d="M18 6v24M6 18h24" stroke="currentColor" strokeWidth="1.4"/></>, // logistics — compass
    '02': <><path d="M4 24h28M4 24l8-14M32 24l-8-14M12 10h12" stroke="currentColor" strokeWidth="1.4" fill="none"/><circle cx="18" cy="10" r="2" fill="currentColor"/></>, // air export
    '03': <><rect x="6" y="8" width="24" height="20" stroke="currentColor" strokeWidth="1.4"/><path d="M6 14h24M11 20h6M11 24h10" stroke="currentColor" strokeWidth="1.4"/></>, // customs — stamped doc
    '04': <><circle cx="18" cy="18" r="12" stroke="currentColor" strokeWidth="1.4" fill="none"/><path d="M6 18c4-3 8-3 12 0s8 3 12 0" stroke="currentColor" strokeWidth="1.4" fill="none"/><path d="M18 6v24" stroke="currentColor" strokeWidth="1.4"/></>, // third country — globe
    '05': <><rect x="8" y="6" width="20" height="24" stroke="currentColor" strokeWidth="1.4"/><path d="M12 12h12M12 16h12M12 20h8M12 24h6" stroke="currentColor" strokeWidth="1.4"/></>, // accounting — ledger
    '06': <><circle cx="18" cy="13" r="5" stroke="currentColor" strokeWidth="1.4" fill="none"/><path d="M8 30c2-6 6-9 10-9s8 3 10 9" stroke="currentColor" strokeWidth="1.4" fill="none"/></>, // HR — person
    '07': <><path d="M4 22q4-3 7 0t7 0 7 0 7 0M4 26q4-3 7 0t7 0 7 0 7 0" stroke="currentColor" strokeWidth="1.4" fill="none"/><rect x="10" y="10" width="16" height="8" stroke="currentColor" strokeWidth="1.4"/><path d="M14 10v-3M22 10v-3" stroke="currentColor" strokeWidth="1.4"/></>, // sea & road — wave + truck
    '08': <><path d="M18 4v18M11 15l7 7 7-7" stroke="currentColor" strokeWidth="1.4" fill="none"/><path d="M6 28h24" stroke="currentColor" strokeWidth="1.4"/></>, // import — arrow down to baseline
    '09': <><rect x="6" y="14" width="20" height="14" stroke="currentColor" strokeWidth="1.4"/><path d="M26 18l4-4v10l-4-4" stroke="currentColor" strokeWidth="1.4" fill="none"/><circle cx="13" cy="28" r="2" fill="currentColor"/><circle cx="22" cy="28" r="2" fill="currentColor"/><path d="M10 14v-4h6l2 4" stroke="currentColor" strokeWidth="1.4" fill="none"/></>, // on-board delivery — truck/forklift
  };
  return <svg className="dept-glyph" viewBox="0 0 36 36" fill="none">{paths[n]}</svg>;
}

function Departments({ lang }) {
  const t = C[lang].departments;
  const [hover, setHover] = useState(null);
  return (
    <section className="section section-dark depts-section">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
            <h2>{t.title_a}<br/><span className="serif">{t.title_b}</span></h2>
          </div>
          <p className="desc right">{t.desc}</p>
        </div>
        <div className="depts reveal">
          {t.items.map((d, i) => (
            <div
              key={i}
              className={`dept ${hover === i ? 'is-hover' : ''}`}
              onMouseEnter={() => setHover(i)}
              onMouseLeave={() => setHover(null)}
            >
              <div className="dept-num mono">{d.n}</div>
              <div className="dept-icon"><DeptIcon n={d.n} /></div>
              <div className="dept-name">{d.t}</div>
              <div className="dept-desc"><p>{d.p}</p></div>
              <div className="dept-corner"></div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ---------------- Timeline ---------------- */
function Timeline({ lang }) {
  const t = C[lang].history;
  return (
    <section className="section section-bg">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
            <h2>{t.title_a} <span className="serif">{t.title_b}</span></h2>
          </div>
          <p className="desc right">{t.desc}</p>
        </div>
        <div className="timeline-flow reveal in">
          <div className="timeline-spine" aria-hidden="true"></div>
          {t.cards.map((c, i) => (
            <div key={i} className={`tl-item ${i % 2 === 0 ? 'tl-left' : 'tl-right'}`}>
              <div className="tl-node" aria-hidden="true"></div>
              <div className="tl-card">
                <div className="timeline-year mono">{c.y}</div>
                <h4>{c.t}</h4>
                <p>{c.p}</p>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ---------------- Network map ---------------- */
const PINS = [
  { code: 'GR', name: 'Piraeus', x: 555, y: 195 },
  { code: 'NL', name: 'Rotterdam', x: 510, y: 145 },
  { code: 'JP', name: 'Tokyo', x: 870, y: 195 },
  { code: 'CN', name: 'Shanghai', x: 825, y: 220 },
  { code: 'KR', name: 'Busan', x: 850, y: 200 },
  { code: 'SG', name: 'Singapore', x: 790, y: 285 },
  { code: 'MY', name: 'Kuala Lumpur', x: 780, y: 280 },
];
function NetworkMap({ lang }) {
  const t = C[lang].network;
  const [hover, setHover] = useState(null);
  return (
    <section className="network">
      <div className="container">
        <div className="network-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
            <h2>{t.title_a}<br/><span className="serif">{t.title_b}</span></h2>
          </div>
          <p style={{ fontSize: 17, color: 'rgba(255,255,255,0.78)', lineHeight: 1.6, maxWidth: '52ch', justifySelf: 'end' }}>{t.desc}</p>
        </div>
        <div className="network-stats reveal">
          {t.stats.map((s, i) => (
            <div key={i} className="network-stat">
              <div className="num"><span className="serif">{s.n}</span></div>
              <div className="lab mono">{s.l}</div>
            </div>
          ))}
        </div>
        <div className="map-wrap reveal">
          <svg className="map-svg" viewBox="0 0 1000 500" preserveAspectRatio="xMidYMid meet">
            <defs>
              <pattern id="dots" width="14" height="14" patternUnits="userSpaceOnUse">
                <circle cx="2" cy="2" r="1" fill="rgba(127,179,213,0.18)"/>
              </pattern>
            </defs>
            {/* abstract continent outlines as soft polygons */}
            <g fill="rgba(127,179,213,0.06)" stroke="rgba(127,179,213,0.15)" strokeWidth="0.6">
              <path d="M120 130 L260 110 L320 150 L300 220 L240 260 L160 240 L120 200 Z"/>
              <path d="M460 110 L620 100 L640 180 L600 230 L520 240 L470 200 Z"/>
              <path d="M520 240 L600 240 L640 320 L580 380 L500 360 L470 280 Z"/>
              <path d="M680 130 L900 120 L920 220 L850 260 L780 280 L720 230 Z"/>
              <path d="M780 280 L860 280 L880 320 L800 340 L760 320 Z"/>
              <path d="M260 320 L340 320 L380 380 L320 420 L260 400 Z"/>
            </g>
            <rect width="1000" height="500" fill="url(#dots)"/>
            {/* connection arcs */}
            <g stroke="rgba(127,179,213,0.35)" strokeWidth="0.8" fill="none" strokeDasharray="3 4">
              {PINS.slice(1).map((p, i) => (
                <path key={i} d={`M555 195 Q ${(555+p.x)/2} ${Math.min(p.y, 195) - 60} ${p.x} ${p.y}`}/>
              ))}
            </g>
            {PINS.map((p, i) => (
              <g key={i} transform={`translate(${p.x} ${p.y})`} onMouseEnter={() => setHover(i)} onMouseLeave={() => setHover(null)} style={{ cursor: 'pointer' }}>
                <circle r="14" className="map-pulse" />
                <circle r="5" className="map-dot" />
                <text x="10" y="-8" fill="white" fontFamily="Geist Mono, monospace" fontSize="10" letterSpacing="0.16em">{p.code}</text>
              </g>
            ))}
          </svg>
          {hover !== null && (
            <div className="map-tooltip visible" style={{ left: `${PINS[hover].x / 1000 * 100}%`, top: `${PINS[hover].y / 500 * 100}%` }}>
              <strong>{PINS[hover].name}</strong>
              <div className="meta mono">{t.countries.find(c => c.code === PINS[hover].code)?.name}</div>
            </div>
          )}
        </div>
        <div className="country-list reveal">
          {t.countries.map((c, i) => (
            <div key={i} className="country">
              <div className="flag mono">{c.code}</div>
              <h4>{c.name}</h4>
              <div className="city">{c.city}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ---------------- ESG ---------------- */
function ESG({ lang }) {
  const t = C[lang].esg;
  return (
    <section className="section section-light">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
            <h2>{t.title_a}<br/><span className="serif">{t.title_b}</span></h2>
          </div>
          <p className="desc right">{t.desc}</p>
        </div>
        <div className="esg-grid reveal">
          {t.cards.map((c, i) => (
            <div key={i} className="esg-card">
              <span className="badge mono">{c.badge}</span>
              <h3>{c.t}</h3>
              <p>{c.p}</p>
              <div className="certs">{c.tags.map((tag, j) => <span key={j} className="cert-tag mono">{tag}</span>)}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ---------------- Team ---------------- */
function Team({ lang }) {
  const t = C[lang].team;
  return (
    <section className="section section-bg">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
            <h2>{t.title_a}</h2>
          </div>
          <p className="desc right">{t.desc}</p>
        </div>
        <div className="team-grid reveal">
          {t.members.map((m, i) => (
            <div key={i} className="team-card">
              <div className="team-photo">
                <div className="ph-label mono">PHOTO · {m.i}</div>
                <div className="initials">{m.i}</div>
              </div>
              <div className="team-info">
                <h4>{m.n}</h4>
                <div className="role mono">{m.r}</div>
              </div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ---------------- News ---------------- */
function News({ lang }) {
  const t = C[lang].news;
  return (
    <section className="section section-light">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
            <h2>{t.title_a}</h2>
          </div>
          <p className="desc right">{t.desc}</p>
        </div>
        <div className="news-grid reveal">
          {t.items.map((n, i) => (
            <article key={i} className={`news-card ${i === 0 ? 'featured' : ''}`}>
              <div className="img">{n.img ? <img src={n.img} alt={n.t} loading="lazy"/> : <div className="ph-label mono">IMG · {n.tag}</div>}</div>
              <div className="body">
                <div className="meta mono">
                  {n.date && <><span>{n.date}</span><span>·</span></>}
                  <span>{n.tag}</span>
                  {n.live && <span className="live-pill">● LIVE</span>}
                </div>
                <h3>{n.t}</h3>
                {n.p && <p>{n.p}</p>}
                {n.p && <div className="read-more mono">Read more →</div>}
              </div>
            </article>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ---------------- Testimonials ---------------- */
function Testimonials({ lang }) {
  const t = C[lang].testimonials;
  return (
    <section className="section section-warm">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
            <h2>{t.title_a}<br/><span className="serif">{t.title_b}</span></h2>
          </div>
          <p className="desc right">{t.desc}</p>
        </div>
        <div className="testimonials testimonials-google reveal">
          {t.items.map((q, i) => {
            const initial = (q.a || '?').trim().charAt(0).toUpperCase();
            const rating = q.rating || 5;
            return (
              <div key={i} className="testi">
                <div className="testi-head">
                  <div className="testi-avatar" aria-hidden="true">{initial}</div>
                  <div className="testi-author">
                    <strong>{q.a}</strong>
                    <span className="testi-source mono">
                      {q.r}
                      {q.source === 'Google' && (
                        <span className="g-mark" aria-label="Google">
                          <svg viewBox="0 0 24 24" width="12" height="12" aria-hidden="true">
                            <path d="M21.6 12.227c0-.708-.063-1.39-.18-2.045H12v3.868h5.382a4.6 4.6 0 0 1-1.995 3.018v2.51h3.227c1.886-1.737 2.986-4.296 2.986-7.351z" fill="#4285F4"/>
                            <path d="M12 22c2.7 0 4.964-.895 6.614-2.422l-3.227-2.51c-.895.6-2.04.955-3.387.955-2.605 0-4.81-1.76-5.596-4.123H3.064v2.59A9.996 9.996 0 0 0 12 22z" fill="#34A853"/>
                            <path d="M6.404 13.9a6.005 6.005 0 0 1 0-3.8V7.51H3.064a10.001 10.001 0 0 0 0 8.98l3.34-2.59z" fill="#FBBC05"/>
                            <path d="M12 5.977c1.468 0 2.786.504 3.823 1.495l2.864-2.864C16.96 2.99 14.696 2 12 2 8.064 2 4.66 4.255 3.064 7.51l3.34 2.59C7.19 7.737 9.395 5.977 12 5.977z" fill="#EA4335"/>
                          </svg>
                          Google
                        </span>
                      )}
                    </span>
                  </div>
                  {q.isNew && <span className="testi-new mono">NEW</span>}
                </div>
                <blockquote>{q.q}</blockquote>
                <div className="testi-meta">
                  <div className="testi-rating" aria-label={`${rating} out of 5 stars`}>
                    <span className="testi-rating-num mono">{rating}/5</span>
                    <span className="testi-stars" aria-hidden="true">
                      {Array.from({length: 5}).map((_, s) => (
                        <svg key={s} viewBox="0 0 24 24" width="11" height="11" fill={s < rating ? '#E0A726' : 'rgba(10,31,61,0.15)'}>
                          <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
                        </svg>
                      ))}
                    </span>
                  </div>
                  <div className="testi-date mono">{q.d}</div>
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </section>
  );
}

/* ---------------- Services Teaser (replaces old mission line) ---------------- */
function Mission({ lang, navigate, compact }) {
  const t = C[lang].mission;
  const go = (e) => {
    e.preventDefault();
    if (navigate) navigate('services');
    else if (window.__fl_setPage) window.__fl_setPage('services');
  };
  if (compact) {
    return (
      <section className="mission-services mission-services--compact">
        <div className="container reveal">
          <div className="section-eyebrow mono">{t.eyebrow}</div>
          <h2 className="mission-services-headline">
            {t.title_a} <span className="serif">{t.title_b}</span>
          </h2>
          <p className="mission-services-lede">{t.desc}</p>
          <a
            href={buildPath(lang, 'services')}
            onClick={go}
            className="btn btn-primary"
          >
            {t.cta}
            <svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true">
              <path d="M3 8h10m0 0L9 4m4 4l-4 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
          </a>
        </div>
      </section>
    );
  }
  return (
    <section className="mission-services">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
            <h2>{t.title_a}<br/><span className="serif">{t.title_b}</span></h2>
          </div>
          <p className="desc right">{t.desc}</p>
        </div>
        <ul className="mission-services-grid reveal">
          {t.items.map((it, i) => (
            <li key={i} className="mission-svc">
              <span className="mission-svc-num mono">{it.n}</span>
              <span className="mission-svc-t">{it.t}</span>
            </li>
          ))}
        </ul>
        <div className="mission-services-cta reveal">
          <a
            href={buildPath(lang, 'services')}
            onClick={go}
            className="btn btn-primary"
          >
            {t.cta}
            <svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true">
              <path d="M3 8h10m0 0L9 4m4 4l-4 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
          </a>
          <p className="mission-services-note mono">{t.note}</p>
        </div>
      </div>
    </section>
  );
}

/* ---------------- Certifications & Memberships ---------------- */
function Certifications({ lang }) {
  const isEl = lang === 'gr';
  const eyebrow = isEl ? 'ΠΙΣΤΟΠΟΙΗΣΕΙΣ & ΣΥΝΕΡΓΑΣΙΕΣ' : 'CERTIFICATIONS & MEMBERSHIPS';
  const title_a = isEl ? 'Διαπιστευμένοι.' : 'Accredited.';
  const title_b = isEl ? 'Επαληθευμένοι.' : 'Verified.';
  const desc = isEl
    ? 'Λειτουργούμε σύμφωνα με τα διεθνή πρότυπα ποιότητας και ασφάλειας της αλυσίδας εφοδιασμού — πιστοποιημένοι από αναγνωρισμένους φορείς και ενεργά μέλη των βασικών διεθνών ενώσεων μεταφορών.'
    : 'We operate to international quality and supply-chain-security standards — certified by recognised bodies and active members of the principal global freight associations.';
  const items = [
    {
      src: '/assets/cert-lrqa-iso9001.png',
      alt: 'LRQA Certified — ISO 9001',
      label: isEl ? 'ISO 9001 — Πιστοποίηση LRQA' : 'ISO 9001 — Certified by LRQA',
      caption: 'UKAS 0001',
    },
    {
      src: '/assets/cert-customs-iata-fiata-aeo.png',
      alt: 'IATA, FIATA, AEO and EU Directorate General Customs and Taxation memberships',
      label: isEl ? 'IATA · FIATA · AEO · EU Customs' : 'IATA · FIATA · AEO · EU Customs',
      caption: isEl ? 'Μέλη & εξουσιοδοτημένοι' : 'Members & authorised',
    },
  ];
  return (
    <section id="certifications" className="section section-light certs-strip" aria-labelledby="certs-heading">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{eyebrow}</div>
            <h2 id="certs-heading">{title_a}<br/><span className="serif">{title_b}</span></h2>
          </div>
          <p className="desc right">{desc}</p>
        </div>
        <div className="certs-row reveal">
          {items.map((it, i) => (
            <figure key={i} className="cert-block">
              <div className="cert-frame">
                <img src={it.src} alt={it.alt} loading="lazy" decoding="async" />
              </div>
              <figcaption>
                <span className="cert-label">{it.label}</span>
                <span className="cert-caption mono">{it.caption}</span>
              </figcaption>
            </figure>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ---------------- Ethics / Quality Policy ---------------- */
function Policy({ lang }) {
  const tQ = C[lang].policy;
  const tA = C[lang].policy_anti;
  const [active, setActive] = useState('quality');
  if (!tQ) return null;
  const t = active === 'quality' ? tQ : tA;
  const tabs = [
    { id: 'quality', label: lang === 'el' ? 'Πολιτική Ποιότητας' : 'Quality Policy', meta: 'ISO 9001:2015' },
    { id: 'anti', label: lang === 'el' ? 'Καταπολέμηση Διαφθοράς' : 'Anti-Bribery & Corruption', meta: lang === 'el' ? 'Μηδενική ανοχή' : 'Zero tolerance' },
  ];
  return (
    <section id="ethics-policy" className="section section-light policy-section" aria-labelledby="policy-heading">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{lang === 'el' ? 'Πολιτικές Εταιρείας' : 'Company Policies'}</div>
            <h2 id="policy-heading">{t.title_a}<br/><span className="serif">{t.title_b}</span></h2>
          </div>
          <p className="desc right">{t.intro}</p>
        </div>
        <div className="policy-tabs reveal" role="tablist" aria-label="Company policies">
          {tabs.map((tab) => (
            <button
              key={tab.id}
              role="tab"
              aria-selected={active === tab.id}
              className={`policy-tab ${active === tab.id ? 'is-active' : ''}`}
              onClick={() => setActive(tab.id)}
            >
              <span className="policy-tab-num mono">{tab.id === 'quality' ? '01' : '02'}</span>
              <span className="policy-tab-body">
                <span className="policy-tab-label">{tab.label}</span>
                <span className="policy-tab-meta mono">{tab.meta}</span>
              </span>
              <span className="policy-tab-arrow" aria-hidden="true">
                <svg width="14" height="14" viewBox="0 0 16 16"><path d="M3 8h10m0 0L9 4m4 4l-4 4" stroke="currentColor" strokeWidth="1.4" fill="none" strokeLinecap="round"/></svg>
              </span>
            </button>
          ))}
        </div>
        <article className="policy-doc" key={active}>
          <div className="policy-aside">
            <div className="policy-meta">
              <div className="policy-meta-row">
                <span className="mono">{t.meta_date_label}</span>
                <span>{t.meta_date_value}</span>
              </div>
              <div className="policy-meta-row">
                <span className="mono">{t.meta_sig_label}</span>
                <span>{t.meta_sig_value}</span>
              </div>
              <div className="policy-meta-row">
                <span className="mono">{lang === 'el' ? 'Πρότυπο' : 'Standard'}</span>
                <span>{active === 'quality' ? 'ISO 9001:2015' : (lang === 'el' ? 'UK Bribery Act' : 'UK Bribery Act')}</span>
              </div>
            </div>
          </div>
          <div className="policy-body">
            {active === 'quality' ? (
              <>
                <div className="policy-objectives">
                  <div className="section-eyebrow mono">{tQ.objectives_label}</div>
                  <ol className="policy-list">
                    {tQ.objectives.map((o, i) => (
                      <li key={i}><span className="policy-num mono">{String(i + 1).padStart(2, '0')}</span><span>{o}</span></li>
                    ))}
                  </ol>
                  <p className="policy-note">{tQ.objectives_note}</p>
                </div>
                <div className="policy-prose">
                  {tQ.body.map((p, i) => <p key={i}>{p}</p>)}
                </div>
              </>
            ) : (
              <div className="policy-sections">
                {tA.sections.map((s, i) => (
                  <div key={i} className="policy-sec">
                    <div className="policy-sec-head">
                      <span className="policy-num mono">{s.num}</span>
                      <h3 className="policy-sec-title">{s.title}</h3>
                    </div>
                    <div className="policy-sec-body">
                      {s.body.map((p, j) => <p key={j}>{p}</p>)}
                    </div>
                  </div>
                ))}
              </div>
            )}
            <p className="policy-closing">{t.closing}</p>
          </div>
        </article>
      </div>
    </section>
  );
}

/* ---------------- Contact ---------------- */
// Web3Forms public access key — safe in client code; sets which inbox gets
// submissions. Free key at https://web3forms.com.
const WEB3FORMS_ACCESS_KEY = '4497a57a-f8b3-4271-acc0-e6c34798e703';

function Contact({ lang }) {
  const t = C[lang].contact;
  const [status, setStatus] = useState('idle'); // idle | sending | success | error
  const onSubmit = async (e) => {
    e.preventDefault();
    if (status === 'sending') return;
    const form = e.currentTarget;
    const fd = new FormData(form);
    if (fd.get('company_website')) { setStatus('success'); form.reset(); return; } // honeypot
    setStatus('sending');
    try {
      const res = await fetch('https://api.web3forms.com/submit', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
        body: JSON.stringify({
          access_key: WEB3FORMS_ACCESS_KEY,
          from_name: 'FrontLine Website',
          subject: `New website enquiry - ${fd.get('name') || ''}${fd.get('interest') ? ` (${fd.get('interest')})` : ''}`,
          replyto: fd.get('email') || '',
          Name: fd.get('name') || '',
          Email: fd.get('email') || '',
          Company: fd.get('company') || '-',
          Phone: fd.get('phone') || '-',
          Interest: fd.get('interest') || '-',
          Message: fd.get('message') || '-',
          Language: lang,
        }),
      });
      const data = await res.json().catch(() => ({}));
      if (res.ok && data.success) { setStatus('success'); form.reset(); } else setStatus('error');
    } catch { setStatus('error'); }
  };
  return (
    <section className="section section-bg" id="contact-section">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <div className="section-eyebrow mono">{t.eyebrow}</div>
            <h2>{t.title_a} <span className="serif">{t.title_b}</span></h2>
          </div>
          <p className="desc right">{t.form.p}</p>
        </div>
        <div className="contact-grid reveal">
          <form className="contact-form" onSubmit={onSubmit}>
            <h3>{t.form.h}</h3>
            <p>{t.form.p}</p>
            <div className="form-row">
              <div className="form-field"><label className="mono">{t.form.labels.name}</label><input name="name" type="text" required /></div>
              <div className="form-field"><label className="mono">{t.form.labels.email}</label><input name="email" type="email" required /></div>
            </div>
            <div className="form-row">
              <div className="form-field"><label className="mono">{t.form.labels.company}</label><input name="company" type="text" /></div>
              <div className="form-field"><label className="mono">{t.form.labels.phone}</label><input name="phone" type="tel" /></div>
            </div>
            <div className="form-row">
              <div className="form-field full"><label className="mono">{t.form.labels.interest}</label>
                <select name="interest">{t.form.services.map((s, i) => <option key={i}>{s}</option>)}</select>
              </div>
            </div>
            <div className="form-row">
              <div className="form-field full"><label className="mono">{t.form.labels.message}</label><textarea name="message" rows="3"></textarea></div>
            </div>
            <div aria-hidden="true" style={{ position: 'absolute', left: '-9999px', width: '1px', height: '1px', overflow: 'hidden' }}>
              <label>Company website<input name="company_website" type="text" tabIndex={-1} autoComplete="off" /></label>
            </div>
            <div className="form-submit">
              <span className="form-status mono">{
                status === 'success' ? '✓ ' + t.form.sent :
                status === 'sending' ? t.form.sending :
                status === 'error' ? t.form.error :
                t.form.labels.status
              }</span>
              <button type="submit" className="btn btn-primary" disabled={status === 'sending'}>{status === 'sending' ? t.form.sending : t.form.labels.send} <svg width="14" height="14" viewBox="0 0 16 16"><path d="M3 8h10m0 0L9 4m4 4l-4 4" stroke="currentColor" strokeWidth="1.4" fill="none" strokeLinecap="round"/></svg></button>
            </div>
          </form>
          <div className="contact-map">
            <h3>{t.info.h}</h3>
            <div className="contact-info">
              <div className="contact-row"><span className="lab mono">{t.info.addr_lab}</span><span className="val">{t.info.addr_val}</span></div>
              <div className="contact-row"><span className="lab mono">{t.info.phone_lab}</span><span className="val">{(t.info.phone_vals || [t.info.phone_val]).map((p, i) => (<React.Fragment key={i}>{i > 0 && <br/>}<a href={`tel:${p.replace(/\s/g,'')}`}>{p}</a></React.Fragment>))}</span></div>
              <div className="contact-row"><span className="lab mono">{t.info.mail_lab}</span><a className="val" href={`mailto:${t.info.mail_val}`}>{t.info.mail_val}</a></div>
              <div className="contact-row"><span className="lab mono">{t.info.hours_lab}</span><span className="val">{t.info.hours_val}</span></div>
            </div>
            <div className="mini-map">
              <iframe
                src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3146.1904140057827!2d23.650695074942785!3d37.949339702086725!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x14a1bb85424a8b33%3A0xcaee24d2b5230fb6!2sFRONT%20LINE%20Forwarding%20%26%20Agency%20Ltd!5e0!3m2!1sen!2sgr!4v1778648969507!5m2!1sen!2sgr"
                title="FRONT LINE Forwarding & Agency Ltd — Piraeus HQ"
                loading="lazy"
                referrerPolicy="no-referrer-when-downgrade"
                allowFullScreen
              ></iframe>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ---------------- Footer ---------------- */
function Footer({ lang, navigate }) {
  const cl = routerLangToContent(lang);
  const t = C[cl].foot;
  const nav = C[cl].nav;
  const svc = C[cl].services.items.slice(0, 6);
  const buildPath = window.FL_ROUTER.buildPath;
  return (
    <footer>
      <div className="container">
        <div className="foot-top">
          <div className="foot-brand">
            <a className="brand" href={buildPath(lang, 'home')} aria-label={lang === 'el' ? 'FRONT LINE — Αρχική' : 'FRONT LINE — Home'} onClick={(e) => { e.preventDefault(); navigate('home'); }}>
              <img src="/assets/frontline-logo-light.png" alt="FRONT LINE Forwarding & Agency Ltd" width="600" height="200" loading="lazy" decoding="async" style={{ height: 50, width: 'auto', display: 'block' }} />
            </a>
            <p>{t.blurb}</p>
            <div className="foot-social">
              <a href="https://www.linkedin.com/company/front-line-forwarding-agency-ltd/" aria-label={lang === 'el' ? 'FRONT LINE στο LinkedIn' : 'FrontLine on LinkedIn'} rel="noopener" target="_blank"><svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M3.5 5h2.4v8H3.5zM4.7 1.8a1.4 1.4 0 1 1 0 2.8 1.4 1.4 0 0 1 0-2.8zM7.5 5h2.3v1.1c.3-.6 1.1-1.3 2.3-1.3 2.4 0 2.9 1.6 2.9 3.6V13h-2.4V8.9c0-1 0-2.2-1.4-2.2s-1.6 1-1.6 2.1V13H7.5z"/></svg></a>
              <a href="mailto:info@frontline-ltd.com" aria-label={lang === 'el' ? 'Email στο info desk' : 'Email us'}><svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.4" aria-hidden="true"><rect x="2" y="3.5" width="12" height="9"/><path d="M2 4l6 4 6-4"/></svg></a>
            </div>
          </div>
          <nav className="foot-col" aria-label={lang === 'el' ? 'Πλοήγηση υποσέλιδου' : 'Footer navigation'}>
            <h5 className="mono">{t.explore}</h5>
            <ul>
              {[['home', nav.home], ['about', nav.about], ['services', nav.services], ['network', nav.network], ['newsroom', nav.newsroom || 'Newsroom'], ['contact', nav.contact]].map(([k, l]) => (
                <li key={k}><a href={buildPath(lang, k)} onClick={(e) => { e.preventDefault(); navigate(k); }}>{l}</a></li>
              ))}
            </ul>
          </nav>
          <div className="foot-col">
            <h5 className="mono">{t.services}</h5>
            <ul>{svc.map((s, i) => <li key={i}><a href={buildPath(lang, 'services')} onClick={(e) => { e.preventDefault(); navigate('services'); }}>{s.t}</a></li>)}</ul>
          </div>
          <div className="foot-col">
            <h5 className="mono">{t.company}</h5>
            <ul>{t.legal.map((l, i) => <li key={i}><a href={buildPath(lang, 'contact')} onClick={(e) => { e.preventDefault(); navigate('contact'); }}>{l}</a></li>)}</ul>
          </div>
        </div>
        <div className="foot-bot">
          <div>{t.copyright}</div>
          <div className="foot-bot-links">
            {['PIRAEUS','LIMASSOL','ROTTERDAM','TOKYO','OSAKA','SEOUL','INCHEON','SHANGHAI','SINGAPORE'].map((office) => (
              <a key={office} href={buildPath(lang, 'network')} aria-label={`${office} office on FrontLine network page`} onClick={(e) => { e.preventDefault(); navigate('network'); }}>{office}</a>
            ))}
          </div>
        </div>
      </div>
    </footer>
  );
}

/* ---------------- Sub-pages (About, Services, Network, Contact) ---------------- */
function PageHero({ crumb, title, lede, lang }) {
  return (
    <section className="page-hero">
      <div className="container">
        <div className="breadcrumb mono">{crumb}</div>
        <h1>{title}</h1>
        <p className="lede">{lede}</p>
      </div>
    </section>
  );
}

function AboutPage({ lang }) {
  return (
    <div className="page active">
      <PageHero crumb={<><a onClick={() => {}}>HOME</a> &nbsp;/&nbsp; <span>{C[lang].nav.about.toUpperCase()}</span></>} title={<>Our road to <span className="serif">Excellence</span>.</>} lede="A forwarding company that grew from a single Piraeus office into a seven-country network — without losing the operating culture that started it." />
      <Mission lang={lang} />
      <Why lang={lang} />
      <Timeline lang={lang} />
      <Departments lang={lang} />
      <ESG lang={lang} />
    </div>
  );
}
function ServicesPage({ lang }) {
  return (
    <div className="page active">
      <PageHero crumb={<>HOME &nbsp;/&nbsp; <span>{C[lang].nav.services.toUpperCase()}</span></>} title={<>Eight services, <span className="serif">one partner.</span></>} lede="From the warehouse rack to the engine room. Each service runs on documented procedures — combined or standalone, the cargo moves the same way." />
      <Services lang={lang} />
      <Audience lang={lang} />
    </div>
  );
}
function NetworkPage({ lang }) {
  return (
    <div className="page active">
      <PageHero crumb={<>HOME &nbsp;/&nbsp; <span>{C[lang].nav.network.toUpperCase()}</span></>} title={<>Nine offices. <span className="serif">One operating culture.</span></>} lede="Own offices in the markets that move your cargo. Partners qualified by name where we don't have a flag — every link of the network operates against the same SOPs." />
      <NetworkMap lang={lang} />
    </div>
  );
}
function ContactPage({ lang }) {
  return (
    <div className="page active">
      <Contact lang={lang} />
    </div>
  );
}

/* ---------------- App ---------------- */
function App() {
  const { useRouter, useDocumentMeta, buildPath } = window.FL_ROUTER;
  const { lang, page, navigate, switchLang } = useRouter();
  const cl = routerLangToContent(lang);

  // Sync <title>, meta, OG, hreflang, canonical, html[lang] on every nav
  useDocumentMeta(lang, page);

  // Speaker-notes / parent host hook (kept for design-canvas embedding)
  useEffect(() => {
    try { window.parent && window.parent.postMessage({ slideIndexChanged: ['home','about','services','network','newsroom','contact'].indexOf(page) }, '*'); } catch (e) {}
  }, [page]);

  // Cross-page nav helper exposed to news/insights detail pages
  useEffect(() => { window.__fl_setPage = (p) => navigate(p); }, [navigate]);

  // reveal on scroll — observes existing AND newly-added .reveal nodes
  useEffect(() => {
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          e.target.classList.add('in');
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.1 });
    const observeAll = (root) => {
      const nodes = root.querySelectorAll ? root.querySelectorAll('.reveal:not(.in)') : [];
      nodes.forEach(el => io.observe(el));
      if (root.classList && root.classList.contains('reveal') && !root.classList.contains('in')) {
        io.observe(root);
      }
    };
    observeAll(document);
    const mo = new MutationObserver((muts) => {
      muts.forEach(m => m.addedNodes.forEach(n => { if (n.nodeType === 1) observeAll(n); }));
    });
    mo.observe(document.body, { childList: true, subtree: true });
    return () => { io.disconnect(); mo.disconnect(); };
  }, [page]);

  /* Localised breadcrumb "HOME" link, used on every sub-page hero */
  const HomeCrumb = ({ children }) => (
    <a href={buildPath(lang, 'home')} onClick={(e) => { e.preventDefault(); navigate('home'); }}>{children}</a>
  );

  return (
    <>
      <Splash />
      <Nav page={page} navigate={navigate} switchLang={switchLang} lang={lang} />
      <main id="main">
        {page === 'home' && (
          <article className="page active" data-screen-label="01 Home" aria-labelledby="hero-title">
            <Hero lang={cl} navigate={navigate} />
            <Why lang={cl} navigate={navigate} />
            <Mission lang={cl} navigate={navigate} compact={true} />
            {/* Testimonials section removed */}
            <News lang={cl} />
            <Certifications lang={cl} />
            <div className="home-newscta reveal">
              <div className="container">
                <a className="btn btn-primary" onClick={(e) => { e.preventDefault(); navigate('newsroom'); }} href={buildPath(lang, 'newsroom')}>
                  {lang === 'el' ? 'Δείτε το Newsroom' : 'Visit the FrontLine Newsroom'}
                  <svg width="14" height="14" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 8h10m0 0L9 4m4 4l-4 4" stroke="currentColor" strokeWidth="1.4" fill="none" strokeLinecap="round"/></svg>
                </a>
              </div>
            </div>
            <Policy lang={cl} />
          </article>
        )}
        {page === 'about' && (
          <article className="page active" data-screen-label="02 About">
            <PageHero crumb={<><HomeCrumb>{lang === 'el' ? 'ΑΡΧΙΚΗ' : 'HOME'}</HomeCrumb> &nbsp;/&nbsp; <span aria-current="page">{C[cl].nav.about.toUpperCase()}</span></>} title={lang === 'el' ? <>Ο δρόμος μας προς την <span className="serif">αριστεία</span>.</> : <>Our road to <span className="serif">Excellence</span>.</>} lede={lang === 'el' ? 'Μια διαμεταφορική που μεγάλωσε από ένα γραφείο στον Πειραιά σε ένα δίκτυο επτά χωρών — χωρίς να χάσει την κουλτούρα της.' : 'A forwarding company that grew from a single Piraeus office into a seven-country network — without losing the operating culture that started it.'} />
            <Timeline lang={cl} />
            <Departments lang={cl} />
            <ESG lang={cl} />
          </article>
        )}
        {page === 'services' && (
          <article className="page active" data-screen-label="03 Services">
            <PageHero crumb={<><HomeCrumb>{lang === 'el' ? 'ΑΡΧΙΚΗ' : 'HOME'}</HomeCrumb> &nbsp;/&nbsp; <span aria-current="page">{C[cl].nav.services.toUpperCase()}</span></>} title={lang === 'el' ? <>Οκτώ υπηρεσίες. <span className="serif">Ένας συνεργάτης.</span></> : <>Eight services, <span className="serif">one partner.</span></>} lede={lang === 'el' ? 'Από το ράφι της αποθήκης ώς το μηχανοστάσιο — κάθε υπηρεσία τρέχει με τεκμηριωμένες διαδικασίες.' : 'From the warehouse rack to the engine room. Each service runs on documented procedures — combined or standalone.'} />
            <Services lang={cl} />
            <Audience lang={cl} />
          </article>
        )}
        {page === 'network' && (
          <article className="page active" data-screen-label="04 Network">
            <PageHero crumb={<><HomeCrumb>{lang === 'el' ? 'ΑΡΧΙΚΗ' : 'HOME'}</HomeCrumb> &nbsp;/&nbsp; <span aria-current="page">{C[cl].nav.network.toUpperCase()}</span></>} title={lang === 'el' ? <>Εννέα γραφεία. <span className="serif">Μία κουλτούρα.</span></> : <>Nine offices. <span className="serif">One operating culture.</span></>} lede={lang === 'el' ? 'Δικά μας γραφεία σε επτά χώρες. Κάθε κρίκος του δικτύου τρέχει με τα ίδια SOPs.' : "Own offices across seven countries. Every link of the network operates against the same SOPs."} />
            {window.NetworkMapInteractive ? <window.NetworkMapInteractive lang={cl} /> : <NetworkMap lang={cl} />}
          </article>
        )}
        {page === 'newsroom' && window.NewsroomPage && <window.NewsroomPage lang={cl} navigate={navigate} />}
        {page === 'contact' && (
          <article className="page active" data-screen-label="05 Contact">
            <Contact lang={cl} />
          </article>
        )}
      </main>
      <Footer lang={lang} navigate={navigate} />
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
