// @ts-check

const SITE_CONFIG = window.SWIATOWID_SITE_CONFIG;

if (!SITE_CONFIG) {
  throw new Error('Missing SWIATOWID_SITE_CONFIG. Load scripts/site-config.js before scripts/site-chrome.jsx.');
}

/**
 * Resolve the initial language for the page. Precedence:
 *   1. URL query, supports `?lang=pl`, `?l=pl` and bare shorthand `?pl`.
 *   2. localStorage (the site's persisted preference).
 *   3. Default 'en'.
 *
 * If a language was set from the URL, this also writes it back to localStorage
 * so subsequent navigation in the same session keeps the choice.
 *
 * @param {Record<string, unknown>} supportedDict, keys are valid lang codes.
 * @returns {string}
 */
function resolveInitialLang(supportedDict) {
  let resolved = null;

  try {
    const params = new URLSearchParams(window.location.search);
    const explicit = (params.get('lang') || params.get('l') || '').toLowerCase();
    if (explicit && supportedDict[explicit]) {
      resolved = explicit;
    } else {
      // Bare-key shorthand: e.g. /?pl, /?uk
      for (const code of Object.keys(supportedDict)) {
        if (params.has(code)) { resolved = code; break; }
      }
    }
  } catch (e) {}

  if (resolved) {
    try { localStorage.setItem(SITE_CONFIG.langStorageKey, resolved); } catch (e) {}
    return resolved;
  }

  try {
    const stored = localStorage.getItem(SITE_CONFIG.langStorageKey);
    if (stored && supportedDict[stored]) return stored;
  } catch (e) {}

  return 'en';
}

/**
 * Update the URL's `?lang=` param without reloading, so the visible URL
 * matches the active language and is shareable. Removes the param when the
 * lang is the default ('en') to keep canonical URLs clean.
 *
 * @param {string} lang
 */
function syncLangToUrl(lang) {
  if (typeof window === 'undefined' || !window.history?.replaceState) return;
  try {
    const url = new URL(window.location.href);
    // Drop the bare-shorthand variant if present, to avoid two sources of truth.
    ['en','pl','de','es','fr'].forEach((c) => url.searchParams.delete(c));
    url.searchParams.delete('l');
    if (lang && lang !== 'en') {
      url.searchParams.set('lang', lang);
    } else {
      url.searchParams.delete('lang');
    }
    window.history.replaceState(null, '', url.toString());
  } catch (e) {}
}

/**
 * @typedef {'home' | 'capabilities' | 'oferta' | 'blog' | 'careers' | null | undefined} SiteNavSection
 */

/**
 * @typedef {{
 *   key: 'home' | 'capabilities' | 'blog' | 'careers',
 *   href: string,
 *   label: string,
 * }} SiteNavItem
 */

/**
 * @typedef {{
 *   t: (key: string) => string,
 *   activeSection?: SiteNavSection,
 *   LanguageSwitcherComponent?: React.ComponentType | null,
 * }} SiteNavBarProps
 */

/**
 * @typedef {{
 *   t: (key: string) => string,
 *   lang?: string,
 *   requestAccessHref?: string,
 * }} SiteFooterProps
 */

/**
 * @typedef {'intake' | 'careers' | 'privacy' | 'legal'} SiteContactKey
 */

/**
 * @typedef {{
 *   contactKey: SiteContactKey,
 *   subject?: string,
 * }} SiteContactHrefOptions
 */

/**
 * @typedef {{
 *   contactKey: SiteContactKey,
 *   subject?: string,
 *   className?: string,
 *   children?: React.ReactNode,
 * }} SiteContactLinkProps
 */

/**
 * @typedef {{
 *   contactKey: SiteContactKey,
 *   label: React.ReactNode,
 *   subject?: string,
 *   className?: string,
 * }} SiteContactButtonProps
 */

/**
 * @param {SiteContactHrefOptions} options
 * @returns {string}
 */
function buildContactHref({ contactKey, subject }) {
  const contact = SITE_CONFIG.contacts[contactKey];
  if (!contact) {
    throw new Error(`Unknown contact key: ${contactKey}`);
  }
  if (!subject) return contact.mailto;
  return `${contact.mailto}?subject=${encodeURIComponent(subject)}`;
}

/**
 * @param {SiteContactLinkProps} props
 */
function SiteContactLink({ contactKey, subject, className, children }) {
  const contact = SITE_CONFIG.contacts[contactKey];
  return (
    <a href={buildContactHref({ contactKey, subject })} className={className}>
      {children ?? contact.email}
    </a>
  );
}

/**
 * @param {SiteContactButtonProps} props
 */
function SiteContactButton({
  contactKey,
  label,
  subject,
  className = 'btn',
}) {
  return (
    <SiteContactLink contactKey={contactKey} subject={subject} className={className}>
      {label}
    </SiteContactLink>
  );
}

/**
 * @param {(key: string) => string} t
 * @returns {SiteNavItem[]}
 */
function getPrimaryNavItems(t) {
  return [
    { key: 'home', href: SITE_CONFIG.routes.home, label: t('navHome') },
    { key: 'capabilities', href: SITE_CONFIG.routes.capabilities, label: t('navOferta') },
    { key: 'blog', href: SITE_CONFIG.routes.blog, label: t('navBlog') },
    { key: 'careers', href: SITE_CONFIG.routes.careers, label: t('navCareers') },
    { key: 'kontakt', href: SITE_CONFIG.routes.kontakt, label: t('navKontakt') },
  ];
}

const THEME_STORAGE_KEY = 'swiatowid:theme';

function readStoredTheme() {
  try {
    const v = localStorage.getItem(THEME_STORAGE_KEY);
    if (v === 'dark' || v === 'bone' || v === 'steel' || v === 'blood') return v;
  } catch (e) {}
  return document.documentElement.getAttribute('data-theme') || 'bone';
}

function applyTheme(theme) {
  const html = document.documentElement;
  html.setAttribute('data-theme', theme);
  try { localStorage.setItem(THEME_STORAGE_KEY, theme); } catch (e) {}
  window.dispatchEvent(new CustomEvent('swiatowid:theme', { detail: theme }));
}

function ThemeToggle() {
  const [theme, setTheme] = React.useState(readStoredTheme);

  React.useEffect(() => {
    const onChange = (e) => setTheme(e.detail);
    window.addEventListener('swiatowid:theme', onChange);
    return () => window.removeEventListener('swiatowid:theme', onChange);
  }, []);

  const toggle = () => {
    const next = theme === 'dark' ? 'bone' : 'dark';
    setTheme(next);
    applyTheme(next);
  };

  const isDark = theme === 'dark';
  const labels = CHROME_ARIA[(document.documentElement.lang || 'en').slice(0, 2)] || CHROME_ARIA.en;
  const label = isDark ? labels.light : labels.dark;

  return (
    <button
      type="button"
      className="theme-toggle"
      onClick={toggle}
      aria-label={label}
      title={label}
    >
      <svg className="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
        <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79Z" />
      </svg>
      <svg className="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
        <circle cx="12" cy="12" r="4" />
        <path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" />
      </svg>
    </button>
  );
}

/**
 * @param {SiteNavBarProps} props
 */
function SiteNavBar({ t, activeSection = 'home', LanguageSwitcherComponent = null }) {
  const [menuOpen, setMenuOpen] = React.useState(false);
  const close = () => setMenuOpen(false);
  const navItems = getPrimaryNavItems(t);

  React.useEffect(() => {
    if (!menuOpen) return;
    const onKeyDown = (event) => {
      if (event.key === 'Escape') close();
    };
    document.addEventListener('keydown', onKeyDown);
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKeyDown);
      document.body.style.overflow = '';
    };
  }, [menuOpen]);

  return (
    <nav className={`top ${menuOpen ? 'menu-open' : ''}`}>
      <div className="brand">
        <a href={SITE_CONFIG.routes.home} className="brand-link" onClick={close}>
          <span className="brand-mark">
            <RotatingLogo size={26} color="var(--amber)" />
          </span>
          <span className="word">{SITE_CONFIG.brandName}</span>
        </a>
      </div>

      <div className="links">
        {navItems.map((item) => (
          <a key={item.key} href={item.href} className={item.key === activeSection ? 'active' : ''}>
            {item.label}
          </a>
        ))}
      </div>

      <div className="right">
        {LanguageSwitcherComponent ? <LanguageSwitcherComponent /> : null}
        <ThemeToggle />
        <a href={SITE_CONFIG.requestAccessHref} className="clearance" target="_blank" rel="noopener noreferrer">{t('navRequestAccess')}</a>
        <button
          type="button"
          className={`nav-burger ${menuOpen ? 'open' : ''}`}
          onClick={() => setMenuOpen((state) => !state)}
          aria-label={(CHROME_ARIA[(document.documentElement.lang || 'en').slice(0, 2)] || CHROME_ARIA.en).menu}
          aria-expanded={menuOpen}
          aria-controls="nav-drawer"
        >
          <span /><span /><span />
        </button>
      </div>

      <div id="nav-drawer" className={`nav-drawer ${menuOpen ? 'open' : ''}`} aria-hidden={!menuOpen}>
        {navItems.map((item) => (
          <a key={item.key} href={item.href} onClick={close} className={item.key === activeSection ? 'active' : ''}>
            {item.label}
          </a>
        ))}
        <a href={SITE_CONFIG.requestAccessHref} onClick={close} className="drawer-cta" target="_blank" rel="noopener noreferrer">
          {t('navRequestAccess')}
        </a>
      </div>
    </nav>
  );
}

/**
 * @param {SiteFooterProps} props
 */
function getNewsletterCopy(lang) {
  const dict = {
    en: {
      title: 'Stay in touch',
      description: 'Subscribe to the newsletter and stay up to date. We only send useful updates. We do not like spam either.',
      emailLabel: 'Email address',
      emailPlaceholder: 'Email address',
      submit: 'Subscribe',
      submitting: 'Saving...',
      success: 'Subscribed',
      successNote: 'Address saved. You will receive the next issue.',
      error: 'Check your email address and try again.',
      failed: 'We could not save your address. Please try again in a moment.',
      verify: 'Confirm you are not a bot to finish signing up.',
      fineprintLead: 'By joining the newsletter, you accept the',
      fineprintLink: 'Privacy Policy',
    },
    pl: {
      title: 'Pozostańmy w kontakcie',
      description: 'Zapisz się do newslettera i bądź na bieżąco. Wysyłamy tylko wartościowe informacje. My też nie lubimy spamu.',
      emailLabel: 'Adres e-mail',
      emailPlaceholder: 'Adres e-mail',
      submit: 'Zapisz się',
      submitting: 'Zapisywanie...',
      success: 'Zapisano',
      successNote: 'Adres zapisany. Kolejne wydanie trafi na Twoją skrzynkę.',
      error: 'Sprawdź adres e-mail i spróbuj ponownie.',
      failed: 'Nie udało się zapisać adresu. Spróbuj ponownie za chwilę.',
      verify: 'Potwierdź, że nie jesteś botem, aby dokończyć zapis.',
      fineprintLead: 'Dołączając do newslettera, akceptujesz postanowienia',
      fineprintLink: 'Polityki Prywatności',
    },
    de: {
      title: 'Bleiben wir in Kontakt',
      description: 'Abonnieren Sie den Newsletter und bleiben Sie auf dem Laufenden. Wir versenden nur nützliche Updates. Spam mögen wir genauso wenig.',
      emailLabel: 'E-Mail-Adresse',
      emailPlaceholder: 'E-Mail-Adresse',
      submit: 'Abonnieren',
      submitting: 'Wird gespeichert...',
      success: 'Eingetragen',
      successNote: 'Adresse gespeichert. Sie erhalten die nächste Ausgabe.',
      error: 'Prüfen Sie Ihre E-Mail-Adresse und versuchen Sie es erneut.',
      failed: 'Die Adresse konnte nicht gespeichert werden. Bitte versuchen Sie es gleich noch einmal.',
      verify: 'Bestätigen Sie, dass Sie kein Bot sind, um die Anmeldung abzuschließen.',
      fineprintLead: 'Mit der Anmeldung zum Newsletter akzeptieren Sie die',
      fineprintLink: 'Datenschutzerklärung',
    },
    es: {
      title: 'Sigamos en contacto',
      description: 'Suscríbete al boletín y mantente al día. Solo enviamos información útil. A nosotros tampoco nos gusta el spam.',
      emailLabel: 'Dirección de correo electrónico',
      emailPlaceholder: 'Dirección de correo electrónico',
      submit: 'Suscribirse',
      submitting: 'Guardando...',
      success: 'Suscrito',
      successNote: 'Dirección guardada. Recibirás el próximo número.',
      error: 'Comprueba tu dirección de correo electrónico e inténtalo de nuevo.',
      failed: 'No hemos podido guardar tu dirección. Inténtalo de nuevo en unos minutos.',
      verify: 'Confirma que no eres un bot para completar la suscripción.',
      fineprintLead: 'Al suscribirte al boletín, aceptas la',
      fineprintLink: 'Política de Privacidad',
    },
    fr: {
      title: 'Restons en contact',
      description: 'Abonnez-vous à la newsletter et restez informé. Nous n\'envoyons que des informations utiles. Nous non plus, nous n\'aimons pas le spam.',
      emailLabel: 'Adresse e-mail',
      emailPlaceholder: 'Adresse e-mail',
      submit: 'S\'abonner',
      submitting: 'Enregistrement...',
      success: 'Inscrit',
      successNote: 'Adresse enregistrée. Vous recevrez la prochaine édition.',
      error: 'Vérifiez votre adresse e-mail et réessayez.',
      failed: 'Nous n\'avons pas pu enregistrer votre adresse. Réessayez dans un instant.',
      verify: 'Confirmez que vous n\'êtes pas un robot pour finaliser l\'inscription.',
      fineprintLead: 'En vous inscrivant à la newsletter, vous acceptez la',
      fineprintLink: 'Politique de confidentialité',
    },
  };

  return dict[(lang || '').toLowerCase()] || dict.en;
}

const TURNSTILE_EXPLICIT_SRC = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';
let turnstileLoaderPromise = null;

function ensureTurnstileReady() {
  if (typeof window === 'undefined') return Promise.reject(new Error('no_window'));
  if (window.turnstile) return Promise.resolve(window.turnstile);
  if (turnstileLoaderPromise) return turnstileLoaderPromise;

  turnstileLoaderPromise = new Promise((resolve, reject) => {
    const existing = Array.from(document.querySelectorAll('script')).find((s) => s.src && s.src.indexOf('challenges.cloudflare.com/turnstile/v0/api.js') >= 0);
    if (existing) {
      existing.addEventListener('load', () => resolve(window.turnstile));
      existing.addEventListener('error', () => reject(new Error('turnstile_load_failed')));
      return;
    }
    const s = document.createElement('script');
    s.src = TURNSTILE_EXPLICIT_SRC;
    s.async = true;
    s.defer = true;
    s.onload = () => resolve(window.turnstile);
    s.onerror = () => reject(new Error('turnstile_load_failed'));
    document.head.appendChild(s);
  });

  return turnstileLoaderPromise;
}

function NewsletterForm({ lang = 'en' }) {
  const [email, setEmail] = React.useState('');
  // error: the address itself was refused; failed: anything else went wrong;
  // verify: Turnstile wants a click before it hands over a token.
  const [state, setState] = React.useState('idle'); // idle | loading | verify | ok | error | failed
  const copy = getNewsletterCopy(lang);
  const widgetHostRef = React.useRef(null);
  const widgetIdRef = React.useRef(null);
  const pendingResolveRef = React.useRef(null);
  const pendingRejectRef = React.useRef(null);
  const pendingTimeoutRef = React.useRef(null);

  const cfg = (SITE_CONFIG && SITE_CONFIG.newsletter) || {};
  // The production key only renders on swiatowid.com, so a dev host would wait
  // out the 12s token timeout on every signup. Cloudflare's always-pass test key
  // lets the form run locally; the POST still needs the Worker behind /api.
  const turnstileSiteKey = ['localhost', '127.0.0.1', '[::1]'].indexOf(location.hostname) >= 0
    ? '1x00000000000000000000AA'
    : (cfg.turnstileSiteKey || '').trim();

  React.useEffect(() => {
    let mounted = true;
    if (!turnstileSiteKey) return;
    ensureTurnstileReady()
      .then(() => {
        if (!mounted || !window.turnstile || !widgetHostRef.current || widgetIdRef.current) return;
        widgetIdRef.current = window.turnstile.render(widgetHostRef.current, {
          sitekey: turnstileSiteKey,
          // The widget runs only when execute() is called and stays out of sight
          // unless Cloudflare asks for a click. It used to sit in a hidden 1px
          // box: whenever a click was needed there was nothing to click, the
          // token never came and every such sign-up failed after 12 seconds.
          execution: 'execute',
          appearance: 'interaction-only',
          size: widgetHostRef.current.clientWidth >= 300 ? 'normal' : 'compact',
          theme: document.documentElement.getAttribute('data-theme') === 'bone' ? 'light' : 'dark',
          language: lang,
          'before-interactive-callback': () => {
            // A person needs time to click; the 12s budget is for the silent run.
            if (pendingTimeoutRef.current) clearTimeout(pendingTimeoutRef.current);
            pendingTimeoutRef.current = setTimeout(() => {
              const rej = pendingRejectRef.current;
              pendingResolveRef.current = null;
              pendingRejectRef.current = null;
              pendingTimeoutRef.current = null;
              if (rej) rej(new Error('turnstile_timeout'));
            }, 180000);
            setState('verify');
          },
          callback: (token) => {
            if (pendingTimeoutRef.current) {
              clearTimeout(pendingTimeoutRef.current);
              pendingTimeoutRef.current = null;
            }
            const resolve = pendingResolveRef.current;
            pendingResolveRef.current = null;
            pendingRejectRef.current = null;
            if (resolve) resolve(token || '');
          },
          'error-callback': () => {
            if (pendingTimeoutRef.current) {
              clearTimeout(pendingTimeoutRef.current);
              pendingTimeoutRef.current = null;
            }
            const reject = pendingRejectRef.current;
            pendingResolveRef.current = null;
            pendingRejectRef.current = null;
            if (reject) reject(new Error('turnstile_error'));
          },
          'expired-callback': () => {
            if (pendingTimeoutRef.current) {
              clearTimeout(pendingTimeoutRef.current);
              pendingTimeoutRef.current = null;
            }
            const reject = pendingRejectRef.current;
            pendingResolveRef.current = null;
            pendingRejectRef.current = null;
            if (reject) reject(new Error('turnstile_expired'));
          },
        });
      })
      .catch(() => {});

    return () => {
      mounted = false;
      if (pendingTimeoutRef.current) {
        clearTimeout(pendingTimeoutRef.current);
        pendingTimeoutRef.current = null;
      }
      pendingResolveRef.current = null;
      pendingRejectRef.current = null;
      if (window.turnstile && widgetIdRef.current) {
        try { window.turnstile.remove(widgetIdRef.current); } catch (_) {}
        widgetIdRef.current = null;
      }
    };
  }, [turnstileSiteKey]);

  async function getTurnstileToken() {
    if (!turnstileSiteKey) return '';
    await ensureTurnstileReady();
    if (!window.turnstile || widgetIdRef.current == null) throw new Error('turnstile_not_ready');

    return await new Promise((resolve, reject) => {
      pendingResolveRef.current = resolve;
      pendingRejectRef.current = reject;
      pendingTimeoutRef.current = setTimeout(() => {
        const rej = pendingRejectRef.current;
        pendingResolveRef.current = null;
        pendingRejectRef.current = null;
        pendingTimeoutRef.current = null;
        if (rej) rej(new Error('turnstile_timeout'));
      }, 12000);

      try {
        window.turnstile.reset(widgetIdRef.current);
        window.turnstile.execute(widgetIdRef.current);
      } catch (e) {
        if (pendingTimeoutRef.current) {
          clearTimeout(pendingTimeoutRef.current);
          pendingTimeoutRef.current = null;
        }
        pendingResolveRef.current = null;
        pendingRejectRef.current = null;
        reject(e || new Error('turnstile_execute_failed'));
      }
    });
  }

  async function handleSubmit(e) {
    e.preventDefault();
    if (state === 'loading' || state === 'ok') return;
    if (e.target.elements.company && e.target.elements.company.value) return;
    if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
      setState('error');
      return;
    }
    setState('loading');

    let turnstileToken = '';
    if (turnstileSiteKey) {
      try {
        turnstileToken = await getTurnstileToken();
        if (!turnstileToken) throw new Error('missing_token');
        setState('loading');
      } catch (_) {
        setState('failed');
        return;
      }
    }

    const payload = {
      email: email.trim(),
      ts: new Date().toISOString(),
      source: cfg.source || 'site-footer',
      turnstileToken,
    };

    try {
      window.dispatchEvent(new CustomEvent('swiatowid:newsletter-signup', { detail: payload }));
    } catch (_) {}

    if (cfg.endpoint) {
      try {
        const res = await fetch(cfg.endpoint, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(payload),
        });
        if (!res.ok) {
          const body = await res.json().catch(() => ({}));
          setState(body.error === 'invalid_email' ? 'error' : 'failed');
          return;
        }
      } catch (err) {
        setState('failed');
        return;
      }
    }

    setState('ok');
  }

  return (
    <form className="footer-newsletter-form" onSubmit={handleSubmit} noValidate>
      <label className="sr-only" htmlFor="footer-newsletter-email">{copy.emailLabel}</label>
      <div className="footer-newsletter-row">
        <input
          id="footer-newsletter-email"
          type="email"
          name="email"
          inputMode="email"
          autoComplete="email"
          placeholder={copy.emailPlaceholder}
          required
          value={email}
          onChange={(ev) => { setEmail(ev.target.value); if (state === 'error' || state === 'failed' || state === 'ok') setState('idle'); }}
          disabled={state === 'loading' || state === 'verify' || state === 'ok'}
        />
        <input
          type="text"
          name="company"
          tabIndex={-1}
          autoComplete="off"
          aria-hidden="true"
          style={{ position: 'absolute', left: '-9999px', width: 1, height: 1, opacity: 0 }}
        />
        <button type="submit" disabled={state === 'loading' || state === 'verify' || state === 'ok'}>
          {state === 'loading' || state === 'verify' ? copy.submitting : state === 'ok' ? copy.success : copy.submit}
        </button>
      </div>
      {turnstileSiteKey ? <div ref={widgetHostRef} className="footer-newsletter-ts" /> : null}

      <p className="footer-newsletter-fineprint">
        {state === 'error' || state === 'failed' || state === 'verify' ? (
          <span style={{ color: 'var(--amber)' }}>{state === 'error' ? copy.error : state === 'verify' ? copy.verify : copy.failed}</span>
        ) : state === 'ok' ? (
          <span style={{ color: 'var(--amber)' }}>{copy.successNote}</span>
        ) : (
          <>{copy.fineprintLead} <a href={SITE_CONFIG.routes.privacy}>{copy.fineprintLink}</a>.</>
        )}
      </p>
    </form>
  );
}

/**
 * Shared FAQ section, rendered identically on the home and subpages.
 * Each page passes its own translation function `t` (the FAQ copy lives in the
 * page i18n dictionaries under capFaq_* / capFaqTitleA|B / capFaqDesc).
 * Pass `contactHref` to show the "get in touch" link; `screenLabel` for the
 * homepage scroll-snap label.
 */
const SITE_FAQ_KEYS = [
  'capFaq_001', 'capFaq_002', 'capFaq_003', 'capFaq_004',
  'capFaq_005', 'capFaq_006', 'capFaq_007', 'capFaq_008',
];

function SiteFaqSection({ t, contactHref = `${SITE_CONFIG.routes.kontakt}#contact-form`, screenLabel = null }) {
  const [openIdx, setOpenIdx] = React.useState(-1);
  const sectionProps = { className: 'cap-faq', id: 'faq' };
  if (screenLabel) sectionProps['data-screen-label'] = screenLabel;
  return (
    <section {...sectionProps}>
      <div className="cap-faq-head">
        <h2>{t('capFaqTitleA').toUpperCase()}<br /><span className="thin">{t('capFaqTitleB').toUpperCase()}</span></h2>
        <p className="sec-desc">{t('capFaqDesc')}</p>
        {contactHref && (
          <a href={contactHref} style={{ display: 'inline-flex', alignItems: 'center', gap: '8px', marginTop: '24px', color: 'var(--amber)', textDecoration: 'none', fontFamily: 'var(--mono)', fontSize: '13px', letterSpacing: '0.1em', textTransform: 'uppercase', borderBottom: '1px solid var(--amber)', paddingBottom: '4px', transition: 'opacity 180ms' }} onMouseEnter={(e) => e.target.style.opacity = '0.7'} onMouseLeave={(e) => e.target.style.opacity = '1'}>
            {t('capFaqContact') || 'Get in touch'}
          </a>
        )}
      </div>
      <div className="cap-faq-list">
        {SITE_FAQ_KEYS.map((tk, i) => {
          const open = i === openIdx;
          return (
            <div className={`cap-faq-item ${open ? 'open' : ''}`} key={tk}>
              <button
                type="button"
                className="cap-faq-q"
                onClick={() => setOpenIdx(open ? -1 : i)}
                aria-expanded={open}
              >
                <span className="cap-faq-q-num">{String(i + 1).padStart(2, '0')}</span>
                <span className="cap-faq-q-text">{t(`${tk}_q`)}</span>
                <span className="cap-faq-q-chevron" aria-hidden="true">+</span>
              </button>
              <div className="cap-faq-a-wrap">
                <div className="cap-faq-a">{t(`${tk}_a`)}</div>
              </div>
            </div>
          );
        })}
      </div>
    </section>
  );
}

function SiteFooter({ t, lang = 'en', requestAccessHref = SITE_CONFIG.requestAccessHref }) {
  const year = new Date().getFullYear();
  const socials = (SITE_CONFIG && SITE_CONFIG.socials) || {};
  const newsletterCopy = getNewsletterCopy(lang);
  const headquartersLabel = HQ_LABEL[lang] || HQ_LABEL.en;

  return (
    <footer className="site-footer">
      <div className="site-footer-inner">
        <div className="footer-brand footer-brand-newsletter">
          <div className="footer-brand-row">
            <RotatingLogo size={40} interval={4000} />
            <span>{SITE_CONFIG.brandName}</span>
          </div>
          <div className="footer-newsletter-pitch">
            <div className="footer-col-head">{newsletterCopy.title}</div>
            <p>{newsletterCopy.description}</p>
          </div>
          <NewsletterForm lang={lang} />
        </div>

        <div className="footer-col">
          <div className="footer-col-head">{t('footerCompany')}</div>
          <ul>
            <li><a href={SITE_CONFIG.routes.home}>{t('navHome')}</a></li>
            <li><a href={SITE_CONFIG.routes.blog}>{t('navBlog')}</a></li>
            <li><a href={SITE_CONFIG.routes.careers}>{t('navCareers')}</a></li>
            <li><a href={SITE_CONFIG.routes.kontakt}>{t('navKontakt')}</a></li>
            <li><a href={requestAccessHref} target="_blank" rel="noopener noreferrer">{t('reqaCtaOpen')}</a></li>
          </ul>
        </div>

        <div className="footer-col">
          <div className="footer-col-head">{t('footerContact')}</div>
          <div className="footer-contact">
            <span className="footer-contact-k">{t('footerSocial')}</span>
            <span className="footer-contact-v footer-social-icons">
              {socials.linkedin && (
                <a href={socials.linkedin} target="_blank" rel="noopener noreferrer" aria-label="LinkedIn">
                  <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                    <path d="M19 0H5C2.239 0 0 2.239 0 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5V5c0-2.761-2.238-5-5-5zM8 19H5V8h3v11zM6.5 6.732c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zM20 19h-3v-5.604c0-3.368-4-3.113-4 0V19h-3V8h3v1.765c1.396-2.586 7-2.777 7 2.476V19z"/>
                  </svg>
                </a>
              )}
              {socials.x && (
                <a href={socials.x} target="_blank" rel="noopener noreferrer" aria-label="X (Twitter)">
                  <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                    <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
                  </svg>
                </a>
              )}
              <a href={SITE_CONFIG.routes.blog} aria-label="Medium" title="Medium">
                <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                  <path d="M13.54 12a6.8 6.8 0 0 1-6.77 6.82A6.8 6.8 0 0 1 0 12a6.8 6.8 0 0 1 6.77-6.82A6.8 6.8 0 0 1 13.54 12zM20.96 12c0 3.54-1.51 6.42-3.38 6.42-1.87 0-3.39-2.88-3.39-6.42s1.52-6.42 3.39-6.42 3.38 2.88 3.38 6.42M24 12c0 3.17-.53 5.75-1.19 5.75-.66 0-1.19-2.58-1.19-5.75s.53-5.75 1.19-5.75C23.47 6.25 24 8.83 24 12z"/>
                </svg>
              </a>
              <a href={SITE_CONFIG.routes.kontakt} aria-label="Email" title="Email">
                <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                  <path d="M1.5 8.67v8.58a3 3 0 0 0 3 3h15a3 3 0 0 0 3-3V8.67l-8.928 5.493a3 3 0 0 1-3.144 0L1.5 8.67Z"/>
                  <path d="M22.5 6.908V6.75a3 3 0 0 0-3-3h-15a3 3 0 0 0-3 3v.158l9.714 5.978a1.5 1.5 0 0 0 1.572 0L22.5 6.908Z"/>
                </svg>
              </a>
            </span>
          </div>
          <div className="footer-contact">
            <span className="footer-contact-k">{t('navCareers')}</span>
            <span className="footer-contact-v"><SiteContactLink contactKey="careers" /></span>
          </div>
          <div className="footer-contact">
            <span className="footer-contact-k">{t('footerHQ')}</span>
            <span className="footer-contact-v">{headquartersLabel}</span>
          </div>
        </div>
      </div>

      <div className="site-footer-bar">
        <div className="meta">
          <span>{SITE_CONFIG.brandName} © {year}</span>
        </div>
        <div className="legal-links">
          <a href={SITE_CONFIG.routes.privacy}>{t('footerPrivacy')}</a>
          <a href={SITE_CONFIG.routes.terms}>{t('footerTerms')}</a>
          <a href={SITE_CONFIG.routes.cookies}>{t('footerCookies')}</a>
          <button type="button" onClick={() => window.SwiatowidConsent && window.SwiatowidConsent.open()}>
            {COOKIE_SETTINGS_LABEL[lang] || COOKIE_SETTINGS_LABEL.en}
          </button>
        </div>
      </div>
    </footer>
  );
}

// Screen-reader labels for the nav controls, and the HQ line, per language.
const CHROME_ARIA = {
  en: { dark: 'Switch to dark mode', light: 'Switch to light mode', menu: 'Menu' },
  pl: { dark: 'Włącz tryb ciemny', light: 'Włącz tryb jasny', menu: 'Menu' },
  de: { dark: 'Dunkles Design einschalten', light: 'Helles Design einschalten', menu: 'Menü' },
  es: { dark: 'Activar el modo oscuro', light: 'Activar el modo claro', menu: 'Menú' },
  fr: { dark: 'Passer en mode sombre', light: 'Passer en mode clair', menu: 'Menu' },
};
const HQ_LABEL = {
  en: 'Warsaw · Krakow · Wroclaw',
  pl: 'Warszawa · Kraków · Wrocław',
  de: 'Warschau · Krakau · Breslau',
  es: 'Varsovia · Cracovia · Breslavia',
  fr: 'Varsovie · Cracovie · Wrocław',
};

// Reopens the cookie banner (scripts/cookies-consent.js) so a visitor can
// change or withdraw consent as easily as they gave it.
const COOKIE_SETTINGS_LABEL = {
  en: 'Cookie settings',
  pl: 'Ustawienia cookies',
  de: 'Cookie-Einstellungen',
  es: 'Configuración de cookies',
  fr: 'Paramètres des cookies',
};

// ── Request Access modal ──────────────────────────────────────────────
const REQUEST_ACCESS_AREAS = [
  'heavy_industry',
  'markets',
  'defense',
  'pharma',
  'general',
];

const RequestAccessContext = React.createContext({
  open: false,
  openModal: () => {},
  closeModal: () => {},
});

function useRequestAccess() {
  return React.useContext(RequestAccessContext);
}

function RequestAccessTriggerButton({ t, className = 'btn primary', children }) {
  return (
    <a
      href={SITE_CONFIG.requestAccessHref}
      target="_blank"
      rel="noopener noreferrer"
      className={className}
    >
      {children ?? (
        <>
          {t('reqaCtaOpen')}
        </>
      )}
    </a>
  );
}

function RequestAccessModal({ t }) {
  const { open, closeModal } = useRequestAccess();
  const [name, setName] = React.useState('');
  const [email, setEmail] = React.useState('');
  const [org, setOrg] = React.useState('');
  const [area, setArea] = React.useState('heavy_industry');
  const [message, setMessage] = React.useState('');
  const [submitted, setSubmitted] = React.useState(false);

  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') closeModal(); };
    document.addEventListener('keydown', onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKey);
      document.body.style.overflow = prev;
    };
  }, [open, closeModal]);

  React.useEffect(() => {
    if (open) setSubmitted(false);
  }, [open]);

  if (!open) return null;

  const onSubmit = (e) => {
    e.preventDefault();
    const subject = `${t('reqaMailSubjectPrefix')}, ${t(`reqaArea_${area}`)}`;
    const lines = [
      `${t('reqaFieldName')}: ${name}`,
      `${t('reqaFieldEmail')}: ${email}`,
      `${t('reqaFieldOrg')}: ${org}`,
      `${t('reqaFieldArea')}: ${t(`reqaArea_${area}`)}`,
      '',
      `${t('reqaFieldMessage')}:`,
      message,
    ];
    const body = lines.join('\n');
    const href = `mailto:${SITE_CONFIG.contacts.business.email}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
    window.location.href = href;
    setSubmitted(true);
  };

  const onBackdrop = (e) => {
    if (e.target === e.currentTarget) closeModal();
  };

  return (
    <div className="reqa-backdrop" onMouseDown={onBackdrop} role="dialog" aria-modal="true" aria-labelledby="reqa-title">
      <div className="reqa-modal">
        <button type="button" className="reqa-close" onClick={closeModal} aria-label={t('reqaClose')}>×</button>
        <div className="reqa-corner tl" />
        <div className="reqa-corner tr" />
        <div className="reqa-corner bl" />
        <div className="reqa-corner br" />

        <div className="reqa-head">
          <div className="reqa-kicker">{t('reqaKicker')}</div>
          <h2 id="reqa-title" className="reqa-title">{t('reqaTitle')}</h2>
          <p className="reqa-lede">{t('reqaLede')}</p>
        </div>

        <form className="reqa-form" onSubmit={onSubmit}>
          <div className="reqa-row">
            <label className="reqa-field">
              <span className="reqa-label">{t('reqaFieldName')}</span>
              <input
                type="text"
                value={name}
                onChange={(e) => setName(e.target.value)}
                required
                autoComplete="name"
              />
            </label>
            <label className="reqa-field">
              <span className="reqa-label">{t('reqaFieldEmail')}</span>
              <input
                type="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                required
                autoComplete="email"
              />
            </label>
          </div>

          <label className="reqa-field">
            <span className="reqa-label">{t('reqaFieldOrg')}</span>
            <input
              type="text"
              value={org}
              onChange={(e) => setOrg(e.target.value)}
              autoComplete="organization"
            />
          </label>

          <label className="reqa-field">
            <span className="reqa-label">{t('reqaFieldArea')}</span>
            <div className="reqa-select-wrap">
              <select value={area} onChange={(e) => setArea(e.target.value)} required>
                {REQUEST_ACCESS_AREAS.map((key) => (
                  <option key={key} value={key}>{t(`reqaArea_${key}`)}</option>
                ))}
              </select>
              <span className="reqa-select-caret" aria-hidden="true">▾</span>
            </div>
          </label>

          <label className="reqa-field">
            <span className="reqa-label">{t('reqaFieldMessage')}</span>
            <textarea
              value={message}
              onChange={(e) => setMessage(e.target.value)}
              rows={5}
              placeholder={t('reqaFieldMessagePh')}
            />
          </label>

          <div className="reqa-foot">
            <span className="reqa-routing">
              {t('reqaRoutedTo')} <b>{SITE_CONFIG.contacts.business.email}</b>
            </span>
            <button type="submit" className="btn primary">
              {submitted ? t('reqaSent') : t('reqaSend')}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

function RequestAccessProvider({ t, children }) {
  const [open, setOpen] = React.useState(false);
  const openModal = React.useCallback(() => setOpen(true), []);
  const closeModal = React.useCallback(() => setOpen(false), []);

  // Note: we no longer intercept '#request-access' anchors. All "Request
  // access" CTAs link directly to the Calendly URL (SITE_CONFIG.requestAccessHref).
  // The modal stays available for any code that calls openModal() directly.

  return (
    <RequestAccessContext.Provider value={{ open, openModal, closeModal }}>
      {children}
      <RequestAccessModal t={t} />
    </RequestAccessContext.Provider>
  );
}

Object.assign(window, {
  SITE_CONFIG,
  resolveInitialLang,
  syncLangToUrl,
  buildContactHref,
  SiteContactLink,
  SiteContactButton,
  SiteNavBar,
  SiteFooter,
  ThemeToggle,
  applyTheme,
  readStoredTheme,
  RequestAccessProvider,
  RequestAccessTriggerButton,
  RequestAccessModal,
  useRequestAccess,
  REQUEST_ACCESS_AREAS,
});
