// Just Travel — Footer (React via Babel)
// Loaded after landing-sections.jsx (uses global SIcon, Reveal) and before landing-app.jsx
// Implements the full site information architecture, grouped by section.

const { useState: useStateFt } = React;

/* ------------------------------------------------------------
   Footer information architecture.

   One row per destination, not per label. The previous version listed ~46
   links across six columns, but most were synonyms pointing at the same four
   targets (thirteen product links all went to /#produtos, six platform links
   all went to Whitelabel.html), which made the footer taller than some of the
   sections above it. Only the duplicates went.

   The columns now mirror NAV_TREE in landing-sections.jsx, group for group, so
   the two never drift again. What that rules out: no "Central de ajuda" (the
   site has a FAQ, not a help centre), no "Blog e Just Academy" as one row (the
   Academy is a separate destination and joins both here and in the navbar once
   NAV_HREF_ACADEMY has its URL), and no per-profile solution links, since the
   only published copy about profiles is Parceiros.html#programas.

   The legal trio (Termos, Privacidade, Cookies) stays in the bar below and is
   deliberately not in the navbar.
   ------------------------------------------------------------ */
const FOOTER_NAV = [
  {
    h: "Plataforma",
    items: [
      { label: "Conheça a plataforma", href: "Whitelabel.html" },
      { label: "IA, CRM e Omnicanal", href: "/#ia" },
      { label: "Preços e planos",     href: "Precos.html" },
    ],
  },
  {
    h: "Produtos",
    items: [
      { label: "Todos os produtos", href: "Produtos.html" },
      { label: "Ingressos",         href: "Produtos.html#ingressos" },
      { label: "Parques temáticos", href: "Produtos.html#parques" },
      { label: "Hospedagens",       href: "Produtos.html#hospedagens" },
      { label: "Seguro viagem",     href: "Produtos.html#seguros" },
    ],
  },
  {
    h: "Soluções e clientes",
    /* Cases de sucesso and Resultados (Cases.html) are out while that page is
       unpublished: it held only invented cases, so it was noindexed and pulled
       from the nav. Both return when real cases exist. */
    items: [
      { label: "Programas de parceria", href: "Parceiros.html#programas" },
      { label: "Just Travel vs. OTAs", href: "Comparativo.html" },
    ],
  },
  {
    h: "Recursos",
    items: [
      { label: "Blog",                     href: "Blog.html" },
      { label: "Segurança & Conformidade", href: "Seguranca.html" },
    ],
  },
  {
    h: "Empresa",
    items: [
      { label: "Sobre nós",        href: "Sobre.html" },
      { label: "Parceiros",        href: "Parceiros.html" },
      { label: "Trabalhe conosco", href: "Trabalhe-Conosco.html" },
      { label: "Contato",          href: "Agendar-Demo.html" },
    ],
  },
];

/* The social row. Each mark is the network's official one, from the shared set
   (landing-icons.jsx pulls the brand keys from simple-icons, since Material
   Symbols has no logos). They used to be drawn here by hand as stroked
   approximations, which left this row the only round-capped, hairline thing on a
   page whose glyphs are all filled.

   The careers page reads this same array for its channel row, where the marks are
   drawn large in each network's own colours: see CAR_CHANNEL_ART. That row keys
   off `label`, so the label is part of the contract here. */
const SOCIALS = [
  { label: "Instagram", icon: "instagram", href: "https://www.instagram.com/justtraveloficial" },
  { label: "LinkedIn",  icon: "linkedin",  href: "https://www.linkedin.com/company/justtraveloficial/" },
  { label: "YouTube",   icon: "youtube",   href: "https://www.youtube.com/@justtraveloficial" },
  { label: "WhatsApp",  icon: "whatsapp",  href: "https://api.whatsapp.com/send/?phone=5571996951307&text&type=phone_number&app_absent=0" },
  { label: "TikTok",    icon: "tiktok",    href: "https://www.tiktok.com/@justtravel.oficial" },
];

function FooterCol({ col }) {
  return (
    <nav className="ft-col" aria-label={col.h}>
      <h4 className="ft-col__h">{col.h}</h4>
      <ul className="ft-col__list">
        {col.items.map((it, i) => (
          <li key={i}><a href={it.href}>{it.label}</a></li>
        ))}
      </ul>
    </nav>
  );
}

/* ------------------------------------------------------------
   Conversion band capture field.

   One field, the way the Figma frame draws it: an address or a phone number,
   and a pill that starts the store. There is no backend to post to and none
   planned, so nothing here pretends to store anything. What a valid submit
   does depends on what was typed, because the two contacts have two different
   next steps and only one of them is something the visitor can finish alone:

     an e-mail   goes to the signup form as a best-effort prefill, which is the
                 "você já cria sua loja" half of the promise above the field;
     a phone     opens WhatsApp with the number already written into the
                 message, addressed to the number published in the contact
                 block below, which is the "o nosso time entra em contato"
                 half. The visitor stays in control: the message is theirs to
                 send, edit or abandon.

   Nothing is collected in between, which is the contract HS_Capture in
   landing-hero.jsx and HowLeadForm in landing-sections.jsx keep too.
   ------------------------------------------------------------ */
/* The three kit tiles the band carries on a narrow screen, left to right.
   One tile of each fill so no two of the same abut (ink, white, blue), and the
   blue one is the ring tile: a circle reads the same whichever way up it is,
   which is the only shape in the kit that cannot be put on its head. None of
   the three is rotated, because rotation in this kit is for the geometric tiles
   and never for a drawing (see HS_MOSAIC in landing-hero.jsx). */
const FT_CTA_TILES = ["passaporte", "triangulo", "brilho"];

const CTA_SIGNUP = "https://office-dashboard.justtraveltour.com/public-whitelabel/new/step-1";
const CTA_WHATSAPP = "5571996951307";

/* Enough digits to be a Brazilian number with or without the area code and the
   country prefix, once the punctuation people type is taken out. */
const CTA_PHONE_RE = /^\+?\d{10,13}$/;

function FooterStartForm() {
  const [error, setError] = useStateFt("");

  const handleSubmit = (e) => {
    e.preventDefault();
    const raw = (e.currentTarget.contato?.value || "").trim();

    if (raw.includes("@")) {
      if (!/.+@.+\..+/.test(raw)) {
        setError("Digite um e-mail válido, como nome@suaagencia.com.br");
        return;
      }
      window.location.href = `${CTA_SIGNUP}?email=${encodeURIComponent(raw)}`;
      return;
    }
    if (CTA_PHONE_RE.test(raw.replace(/[\s().-]/g, ""))) {
      const texto = "Olá! Quero criar a minha loja na Just Travel.\n\n" + `Telefone: ${raw}`;
      window.open(
        `https://api.whatsapp.com/send/?phone=${CTA_WHATSAPP}&text=${encodeURIComponent(texto)}`,
        "_blank", "noopener");
      return;
    }
    setError("Digite um e-mail ou um telefone com DDD para o time falar com você.");
  };

  return (
    <>
      {/* The red of the invalid state lives on the pill's hairline and not in
          the message below it, which is ink: the band's blue cannot carry red
          at the contrast 14px prose needs (see .ft-start__error). */}
      <form className={`ft-start ${error ? "is-invalid" : ""}`} noValidate onSubmit={handleSubmit}>
        <input
          className="ft-start__input"
          type="text" name="contato" autoComplete="email" required
          spellCheck={false}
          placeholder="Seu e-mail ou telefone" aria-label="Seu e-mail ou telefone"
          aria-invalid={error ? "true" : undefined}
          aria-describedby={error ? "ft-start-error" : undefined}
          onChange={() => { if (error) setError(""); }} />
        {/* The system's 44px pill, ink on the white field the way the Figma frame
            draws it: the primary blue inside a white pill would be the one
            thing on this band competing with the band's own blue. The fill is
            .ft-start__go and not .btn--ink on purpose, see the stylesheet. */}
        <button type="submit" className="btn btn--md ft-start__go">
          Começar grátis
          <span className="btn__arrow"><SIcon name="btnArrow" /></span>
        </button>
      </form>
      {error &&
      <p className="ft-start__error" id="ft-start-error" role="alert">
        <SIcon name="alert" size={15} />
        {error}
      </p>}
    </>);

}

/* CtaScreen (the scroll-tilted product mockup under the final CTA) was
   removed on request — see .ft-cta__inner's own padding-bottom below for
   the layout side of the same change. */

/* ------------------------------------------------------------
   Contact: the country carousel.

   The three countries used to be a two-column block of addresses, ~14 lines of
   prose competing with the link columns right above it. Here the country is the
   only thing on screen at rest: three giant display words on an auto-scrolling
   track, with one card below carrying the offices and the two ways to reach
   that office.

   Hover is the headline interaction, but it is not the only one: the words are
   real buttons, so focus and tap select a country too, and the track parks
   itself the moment a pointer or the keyboard is inside it (see
   .ft-carousel:hover / :focus-within in landing-styles.css). Brasil is selected
   at rest so the card is never an empty box, and so the prerendered HTML ships
   a full address for crawlers.
   ------------------------------------------------------------ */
const FT_EMAIL = "contato@justtraveltour.com";

const FT_COUNTRIES = [
  {
    id: "br",
    name: "Brasil",
    offices: [
      {
        tag: "Matriz",
        city: "Salvador, Bahia",
        /* The \u00a0 are non-breaking spaces, and they are load-bearing: two
           offices side by side give each address about half the card, so the
           lines wrap, and where they wrap is decided here rather than by
           wherever the greedy fill happens to land at the reader's width. A
           number stays with the word that gives it its meaning ("Loja 27",
           "CEP 41820-021", "Ste 200"), so the break falls on a comma. Written
           as escapes, not typed as the character, so the next person editing an
           address can see them. */
        lines: [
          "Condomínio Salvador Prime",
          "Avenida Tancredo Neves, 2227, Loja\u00a027, Mezanino",
          "Caminho das Árvores, Salvador\u00a0(BA), CEP\u00a041820-021",
        ],
        foto: "escritorio-salvador",
        alt: "Condomínio Salvador Prime, na Avenida Tancredo Neves, onde fica a matriz da Just Travel",
      },
      {
        tag: "Escritório",
        city: "São Paulo, Cubo Network",
        lines: ["Alameda Vicente Pinzon,\u00a054, Vila Olímpia", "São Paulo (SP), CEP\u00a004547-130"],
        foto: "escritorio-sao-paulo",
        alt: "Prédio do Cubo Network na Vila Olímpia, em São Paulo",
      },
    ],
    phone: { note: "WhatsApp", label: "(11) 4040-1070", href: "tel:+551140401070", icon: "whatsapp" },
  },
  {
    id: "us",
    name: "Estados Unidos",
    offices: [
      {
        tag: "Escritório",
        city: "Celebration, Flórida",
        lines: ["1420 Celebration Blvd, Ste\u00a0200", "Celebration, FL\u00a034747 United States"],
        foto: "escritorio-celebration",
        alt: "Prédio do escritório da Just Travel na 1420 Celebration Blvd, em Celebration, Flórida",
      },
    ],
    phone: { note: "Telefone", label: "(407) 504-0082", href: "tel:+14075040082", icon: "phone" },
  },
  {
    id: "pt",
    name: "Portugal",
    offices: [
      {
        tag: "Escritório",
        city: "Lispolis, Lisboa",
        lines: ["Estrada Paço do Lumiar\u00a044, Lisboa", "CEP\u00a01600-546"],
        foto: "escritorio-lisboa",
        alt: "Sede do Lispolis, o polo tecnológico em Lisboa onde fica o escritório da Just Travel",
      },
    ],
    phone: { note: "WhatsApp", label: "(11) 4040-1070", href: "tel:+551140401070", icon: "whatsapp" },
  },
];

/* The office rows carry the photograph of the building, the format
   Sobre.html draws (SBPaises in sobre-app.jsx) and the same masters under
   assets/photos/sobre/: the two places the site lists its addresses now answer
   in one shape, not one photographed and one iconographic.

   `foto` is nullable and that is a supported state, not a gap waiting to
   break: an office with no photograph yet renders the branded tile with the
   pin, the same way a product category with no usable photograph keeps its
   poster.

   The card's phone, envelope and WhatsApp mark still come from the shared set
   (landing-icons.jsx), which keeps WhatsApp as a hand-drawn brand glyph since
   the set carries no third-party logos. */

function FooterContact() {
  const [active, setActive] = useStateFt(FT_COUNTRIES[0].id);
  const country = FT_COUNTRIES.find((c) => c.id === active) || FT_COUNTRIES[0];

  /* The track is the same list twice so the -50% loop meets itself. The second
     pass is decoration: out of the tab order and out of the a11y tree, but
     still hoverable, so a word that scrolled past the seam keeps working. */
  const word = (c, clone) => (
    <button
      key={(clone ? "clone-" : "") + c.id}
      type="button"
      className={"ft-country" + (c.id === active ? " is-on" : "")}
      onMouseEnter={() => setActive(c.id)}
      onFocus={() => setActive(c.id)}
      onClick={() => setActive(c.id)}
      {...(clone
        ? { tabIndex: -1, "aria-hidden": "true" }
        : { "aria-pressed": c.id === active, "aria-controls": "ft-country-card" })}
    >
      {c.name}
    </button>
  );

  return (
    /* No visible heading: the country words are the heading. The landmark
       still needs a name for anyone navigating by region, so it carries one
       on the section itself. */
    <section className="ft-contact" aria-label="Contato">
      <div className="ft-carousel">
        <div className="ft-carousel__track">
          {FT_COUNTRIES.map((c) => word(c, false))}
          <span className="ft-carousel__clone" aria-hidden="true">
            {FT_COUNTRIES.map((c) => word(c, true))}
          </span>
        </div>
      </div>

      <div className="container">
        <div className="ft-card" id="ft-country-card" aria-live="polite">
          {/* keyed on the country so the entrance replays on every switch */}
          <div className="ft-card__inner" key={country.id}>
            <div className="ft-card__offices">
              {country.offices.map((o, i) => (
                <div className="ft-office" key={i}>
                  {o.foto ? (
                    <img
                      className="ft-office__foto"
                      src={`assets/photos/sobre/${o.foto}.webp`}
                      alt={o.alt}
                      width="240"
                      height="240"
                      loading="lazy"
                      decoding="async"
                    />
                  ) : (
                    <span className="ft-office__foto ft-office__foto--marca" aria-hidden="true">
                      <Icon name="pin" size={24} />
                    </span>
                  )}
                  <div className="ft-office__body">
                    <span className="ft-office__tag">{o.tag}</span>
                    <strong className="ft-office__city">{o.city}</strong>
                    <p className="ft-office__lines">
                      {o.lines.map((l, j) => (
                        <React.Fragment key={j}>{j > 0 && <br />}{l}</React.Fragment>
                      ))}
                    </p>
                  </div>
                </div>
              ))}
            </div>
            <div className="ft-card__reach">
              <a className="ft-reach" href={country.phone.href}>
                <span className="ft-reach__ico"><Icon name={country.phone.icon} size={18} /></span>
                <span className="ft-reach__txt">
                  <span className="ft-reach__k">{country.phone.note}</span>
                  <span className="ft-reach__v">{country.phone.label}</span>
                </span>
              </a>
              <a className="ft-reach" href={`mailto:${FT_EMAIL}`}>
                <span className="ft-reach__ico"><Icon name="mail" size={18} /></span>
                <span className="ft-reach__txt">
                  <span className="ft-reach__k">E-mail</span>
                  <span className="ft-reach__v">{FT_EMAIL}</span>
                </span>
              </a>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

function Footer({ variant }) {
  const [email, setEmail] = useStateFt("");
  const [sent, setSent] = useStateFt(false);
  const year = new Date().getFullYear();
  const isCareers = variant === "careers";

  return (
      <footer className="ft" id="footer">
      {/* ---- Conversion band ----
           Two variants: the careers band, and the "Comece hoje" band every
           other page carries, which is one design everywhere (the landing used
           to run a four-field form here and the rest of the site two buttons).
           The mosaic flanks are a pair of generated crops, see
           scripts/cta-flanks.mjs. */}
      {isCareers ?
      <div className="ft-cta ft-cta--careers">
        <div className="container ftc__inner">
          <Reveal as="div" className="ftc__visual" aria-hidden="true">
            <span className="ftc__square ftc__square--gray"></span>
            <span className="ftc__square ftc__square--tint"></span>
            <span className="ftc__card-back"></span>
            <span className="ftc__card">
              <img src="assets/logo-mark.png" alt="" className="ftc__logo" width="92" height="92" />
            </span>
          </Reveal>
          <Reveal as="div" className="ftc__copy" delay={80}>
            <h2 className="ftc__title">Venha para a Just Travel</h2>
            <p className="ftc__sub">O encontro entre você e a sua melhor versão é aqui. Construindo o futuro de quem vende viagens.</p>
          </Reveal>
        </div>
      </div> :
      <div className="ft-cta ft-cta--start">
        <div className="ft-cta__deco" aria-hidden="true">
          <span className="ft-cta__mos ft-cta__mos--l"></span>
          <span className="ft-cta__mos ft-cta__mos--r"></span>
          {/* Narrow screens drop the two crops and get the kit itself: three
              tiles across the top and one ring, both sized off the viewport.
              See the 640px query in landing-styles.css. */}
          <span className="ft-cta__ring"></span>
          <span className="ft-cta__tiles">
            {FT_CTA_TILES.map((tile) => (
              <img
                key={tile}
                className="ft-cta__tile"
                src={`assets/mosaico/${tile}.webp`}
                alt=""
                width="120"
                height="120"
                draggable={false}
                decoding="async" />
            ))}
          </span>
        </div>
        <div className="container ft-cta__inner">
          <Reveal as="div" className="ft-cta__copy">
            <span className="eyebrow">Comece hoje</span>
            <h2 className="ft-cta__title">Turbine seu faturamento com vendas online</h2>
            <p className="ft-cta__sub">O nosso time entra em contato o mais rápido possível e você já cria sua loja.</p>
          </Reveal>
          <Reveal as="div" className="ft-cta__act" delay={80}>
            <FooterStartForm />
            <div className="ft-cta__alt">
              <a className="btn btn--ghost btn--md ft-cta__demo" href="Agendar-Demo.html">
                Agendar demo
                <SIcon name="arrowRight" size={16} />
              </a>
            </div>
          </Reveal>
        </div>
      </div>
      }
      {/* ---- Main footer ---- */}
      <div className="container ft-main">
        {/* Brand + newsletter */}
        <div className="ft-brand">
          <a className="ft-brand__logo" href="/" aria-label="Just Travel, página inicial">
            <img src="assets/logo-mark.png" alt="" className="ft-brand__mark" width="30" height="28" />
            <span className="ft-brand__word">just travel</span>
          </a>
          <p className="ft-brand__tag">A travel tech que coloca a sua marca na frente. Tecnologia, inventário e inteligência para a sua agência vender mais e melhor.</p>

          <form
            className={`ft-news ${sent ? "is-sent" : ""}`}
            onSubmit={(e) => { e.preventDefault(); if (email) setSent(true); }}
            aria-live="polite"
          >
            <label className="ft-news__label" htmlFor="ft-news-email">Receba guias, webinars e novidades</label>
            {sent ? (
              <div className="ft-news__done">
                <SIcon name="check" size={18} />
                Pronto! Você está na lista.
              </div>
            ) : (
              <div className="ft-news__field">
                <input
                  id="ft-news-email"
                  type="email"
                  name="email"
                  autoComplete="email"
                  inputMode="email"
                  spellCheck={false}
                  required
                  placeholder="Seu e-mail profissional"
                  value={email}
                  onChange={(e) => setEmail(e.target.value)}
                />
                <button type="submit" aria-label="Inscrever">
                  <SIcon name="arrowRight" size={18} />
                </button>
              </div>
            )}
          </form>

          <div className="ft-social">
            {SOCIALS.map((s, i) => (
              <a key={i} href={s.href} className="ft-social__btn" aria-label={s.label}
                target="_blank" rel="noopener noreferrer">
                <Icon name={s.icon} size={19} />
              </a>
            ))}
          </div>
        </div>

        {/* Link columns */}
        <div className="ft-grid">
          {FOOTER_NAV.map((col, i) => <FooterCol key={i} col={col} />)}
        </div>
      </div>

      {/* ---- Contact: country carousel ---- */}
      <FooterContact />

      {/* ---- Legal bar ---- */}
      <div className="ft-legal">
        <div className="container ft-legal__inner">
          <div className="ft-legal__left">
            <span>© {year} Just Travel Viagens e Turismo LTDA · CNPJ 40.454.131/0001-63</span>
          </div>
          <nav className="ft-legal__links" aria-label="Legal">
            <a href="Termos.html">Termos de uso</a>
            <a href="Privacidade.html">Privacidade</a>
            <a href="Privacidade.html#lgpd">LGPD</a>
            <a href="Cookies.html">Cookies</a>
            <button type="button" className="ft-lang">
              <Icon name="globe" size={16} />
              Português (BR)
            </button>
          </nav>
        </div>
      </div>
      </footer>
  );
}

/* ------------------------------------------------------------
   Curtain reveal panel (Perk-style).
   Parked behind the page; the opaque content above is the "curtain"
   that lifts as you reach the bottom, unveiling the suitcase. A light
   parallax drifts the image up as it is exposed (rAF-throttled, GPU).
   ------------------------------------------------------------ */
function RevealFooter() {
  const mediaRef = React.useRef(null);

  React.useEffect(() => {
    const reduce = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (reduce) return;
    const panel = document.querySelector(".reveal-footer");
    let raf = null;
    const tick = () => {
      raf = null;
      const media = mediaRef.current;
      if (!panel || !media) return;
      const h = panel.offsetHeight || 1;
      const docH = document.documentElement.scrollHeight;
      const remaining = docH - (window.scrollY + window.innerHeight);
      // shown: 0 while fully covered by the curtain, 1 when fully unveiled
      const shown = Math.min(1, Math.max(0, 1 - remaining / h));
      const drift = (1 - shown) * 46;            // px the image drifts up as revealed
      media.style.transform = `translate3d(0, ${drift.toFixed(1)}px, 0)`;
      panel.style.setProperty("--shown", shown.toFixed(3));
    };
    const onScroll = () => { if (raf == null) raf = requestAnimationFrame(tick); };
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    onScroll();
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      if (raf != null) cancelAnimationFrame(raf);
    };
  }, []);

  return (
    <aside className="reveal-footer" aria-hidden="true">
      <div className="reveal-footer__media" ref={mediaRef}></div>
    </aside>
  );
}

/* ------------------------------------------------------------
   PageShell — the standard page frame. Every page renders through it so the
   whole site shares one chrome: navbar on top, the page content as the
   opaque "curtain", the footer as its bottom edge, and the suitcase reveal
   panel parked behind it.

   New page? Render <PageShell>…your sections…</PageShell> and the navbar,
   footer and suitcase reveal come with it. The `footer` prop picks the
   conversion band: "careers" for the careers page, omitted everywhere else,
   which is the "Comece hoje" band.
   ------------------------------------------------------------ */
function PageShell({ children, footer }) {
  return (
    <>
      <div className="curtain">
        <Navbar />
        {children}
        <Footer variant={footer} />
      </div>
      <RevealFooter />
    </>
  );
}

Object.assign(window, { Footer, RevealFooter, PageShell });
