// Just Travel — Sobre a empresa (React via Babel)
//
// Loaded after React UMD, landing-icons.jsx (Icon/SIcon), landing-sections.jsx
// (Navbar, Reveal) and landing-footer.jsx (PageShell). One global scope, so
// every top-level name here is prefixed SB_ / SBApp.
//
// The page replaced the document-shaped version that docs-app.jsx used to
// render under window.JT_DOC = "sobre". It follows the Figma frame
// "just-travel-sobre-a-empresa" (Content Landing page, node 236:6), which is a
// marketing page: a dark first fold, then light and dark bands alternating down
// to the investor strip.
//
// The frame also draws a navbar and a footer. Those are not rebuilt here: the
// site standard is PageShell, and its default footer band already carries the
// same "COMECE HOJE" CTA the frame ends on, with the copy every other page
// shares. Rebuilding it would fork one band per page.

const SB_HREF_START = "https://office-dashboard.justtraveltour.com/public-whitelabel/new/step-1";
const SB_HREF_DEMO = "Agendar-Demo.html";

/* --------------------------------------------------- countries + offices */

// One list for the whole first fold: the hero's badge row, the carousel and the
// office cards all read it, so a country cannot be announced in one place and
// missing from another. The addresses are the same ones FT_COUNTRIES publishes
// in the footer, which is the site's other copy of this data.
//
// `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 instead, the same
// way a product category with no usable photograph keeps its poster. Drop a
// master into media-src/sobre/escritorios/, add it to scripts/sobre-assets.mjs
// and set the slug here: nothing else moves.
const SB_PAISES = [
  {
    id: "br",
    nome: "Brasil",
    escritorios: [
      {
        tag: "Matriz",
        cidade: "Salvador, Bahia",
        // Broken by unit of meaning, not by length: the building, then the
        // street and where in it, then the district and the postcode. Written
        // as one long line it wrapped mid-avenue and orphaned the number.
        linhas: [
          "Condomínio Salvador Prime",
          "Avenida Tancredo Neves, 2227, Loja 27, Mezanino",
          "Caminho das Árvores, Salvador (BA), CEP 41820-021",
        ],
        foto: "escritorio-salvador",
        alt: "Condomínio Salvador Prime, na Avenida Tancredo Neves, onde fica a matriz da Just Travel",
      },
      {
        tag: "Escritório",
        cidade: "São Paulo, Cubo Network",
        linhas: ["Alameda Vicente Pinzon, 54, Vila Olímpia", "São Paulo (SP), CEP 04547-130"],
        foto: "escritorio-sao-paulo",
        alt: "Prédio do Cubo Network na Vila Olímpia, em São Paulo",
      },
    ],
  },
  {
    id: "us",
    nome: "Estados Unidos",
    escritorios: [
      {
        tag: "Escritório",
        cidade: "Celebration, Flórida",
        linhas: ["1420 Celebration Blvd, Ste 200", "Celebration, FL 34747, Estados Unidos"],
        foto: "escritorio-celebration",
        alt: "Prédio do escritório da Just Travel na 1420 Celebration Blvd, em Celebration, Flórida",
      },
    ],
  },
  {
    id: "pt",
    nome: "Portugal",
    escritorios: [
      {
        tag: "Escritório",
        cidade: "Lispolis, Lisboa",
        linhas: ["Estrada Paço do Lumiar 44, Lisboa", "CEP 1600-546"],
        foto: "escritorio-lisboa",
        alt: "Sede do Lispolis, o polo tecnológico em Lisboa onde fica o escritório da Just Travel",
      },
    ],
  },
];

/* ------------------------------------------------------------- quem somos */

const SB_PILARES = [
  {
    icon: "monitor",
    title: "Digitalização",
    body: "Plataforma white label completa para agências venderem hotéis, ingressos, carros, seguros e pacotes de forma 100% digital.",
  },
  {
    icon: "shuffle",
    title: "Desintermediação",
    body: "Venda direta, sem repasse de comissão a OTAs globais, devolvendo autonomia, competitividade e lucros ao agente de viagens parceiro.",
  },
  {
    icon: "users",
    title: "Democratização",
    body: "Tecnologia verdadeiramente acessível para quem opera no turismo, impulsionada por IA própria e automação de fluxos inteligente.",
  },
];

/* ---------------------------------------------------------------- números */

const SB_NUMEROS = [
  { v: "+R$ 580M", l: "Volume transacionado" },
  { v: "+1.000", l: "Agências parceiras" },
  { v: "110+", l: "Colaboradores" },
  { v: "3 Países", l: "Brasil, EUA e Portugal" },
  { v: "5 Anos", l: "De crescimento acelerado" },
];

/* ------------------------------------------------------------- trajetória */

// One list for the whole trajectory. It used to be two: a timeline of what
// happened each year and, four sections further down, a second pass over the
// same years carrying the figures. Two runs down the same axis made the page
// read as a timeline followed by a spreadsheet, so they are merged here and the
// figures are selected rather than exhausted.
//
// Per year:
//   fase     the movement the year belongs to, on every year: the stylesheet
//            reads it for the size of the year and the width of the frame, so
//            the hierarchy is declared here rather than inferred from the row's
//            position, which would break the moment a year is inserted.
//   abre     the phase label, set only on the year that opens one, so the rail
//            prints it once and the three movements read without becoming
//            three sub-sections.
//   foto     nullable, and a supported state: a year with no photograph gets
//            the branded plate, the same finished treatment an office without
//            one gets above. See scripts/sobre-assets.mjs for how to fill one.
//   metrics  first is the number that carries the year and is set large in the
//            brand blue; the rest sit under it at body weight. The founding
//            years carry fewer, which is what makes the progression visible
//            without a second heading announcing it. Figures that are context
//            rather than proof (the R$ 50 milhões projection, the R$ 360
//            milhões projection, the ranking place) stay in the prose, where
//            they cannot be mistaken for a result already delivered.
const SB_JORNADA = [
  {
    ano: "2020",
    fase: "fundacao",
    abre: "Fundação",
    title: "A origem da ideia",
    body: "No auge da pandemia, com o turismo parado, João Nou enxerga uma oportunidade latente: digitalizar as pequenas agências de viagens que ficaram sem assistência. A Just Travel nasce dessa leitura.",
    foto: null,
    metrics: [],
  },
  {
    ano: "2021",
    fase: "fundacao",
    title: "A V1 entra no ar",
    body: "Lançamento oficial da primeira versão da plataforma, com uma operação estruturada de forma 100% virtual e o CNPJ registrado em Salvador (BA) no dia 19 de janeiro.",
    foto: "2021-salvador",
    alt: "Condomínio Salvador Prime, na Avenida Tancredo Neves, onde fica a matriz da Just Travel",
    metrics: [
      { v: "R$ 90 mil", l: "transacionados até outubro" },
      { v: "8", l: "colaboradores" },
    ],
  },
  {
    ano: "2022",
    fase: "fundacao",
    title: "Aporte seed e reconhecimento",
    body: "Primeira rodada de investimento seed, capitaneada pela Bossa Invest e pelo Grupo Sai do Papel, e uma vaga entre os finalistas do Turistech, programa do Ministério do Turismo. O ano abre com uma projeção anualizada de R$ 50 milhões em transações.",
    foto: "2022-sao-paulo",
    alt: "Prédio do Cubo Network na Vila Olímpia, em São Paulo, onde a Just Travel mantém escritório",
    metrics: [
      { v: "R$ 1,2 milhão", l: "captados na rodada" },
      { v: "18", l: "colaboradores" },
    ],
  },
  {
    ano: "2023",
    fase: "aceleracao",
    abre: "Aceleração",
    title: "Crescimento de 300%",
    body: "O ano em que a operação vira escala: o faturamento cresce 300% e a base ultrapassa setecentas agências cadastradas na plataforma.",
    foto: null,
    metrics: [
      { v: "+R$ 150 milhões", l: "transacionados no período" },
      { v: "~700", l: "agências cadastradas" },
      { v: "63", l: "colaboradores" },
    ],
  },
  {
    ano: "2024",
    fase: "aceleracao",
    title: "Nova rodada e o hub de Lisboa",
    body: "Segunda rodada seed e a abertura do primeiro hub de operações internacionais, em Lisboa. A partir daqui a Just Travel deixa de ser uma operação apenas brasileira.",
    foto: "2024-lisboa",
    alt: "Sede do Lispolis, o polo tecnológico em Lisboa onde fica o escritório da Just Travel",
    metrics: [
      { v: "+R$ 200 milhões", l: "transacionados, 85% acima de 2023" },
      { v: "R$ 5 milhões", l: "captados na segunda rodada" },
      { v: "81", l: "colaboradores" },
    ],
  },
  {
    ano: "2025",
    fase: "escala",
    abre: "Escala internacional",
    title: "Internacionalização e Estados Unidos",
    body: "Lançamento do Just Travel 2.0 e expansão consolidada para os Estados Unidos, com quinze APIs globais integradas à plataforma, presença na VivaTech, em Paris, e projeção de R$ 360 milhões transacionados.",
    foto: "2025-celebration",
    alt: "Prédio do escritório da Just Travel na 1420 Celebration Blvd, em Celebration, Flórida",
    metrics: [
      { v: "+1.000", l: "agências parceiras" },
      { v: "15 APIs globais", l: "700 mil hotéis e 5 mil locações de carros" },
      { v: "110", l: "colaboradores" },
    ],
  },
  {
    ano: "2026",
    fase: "escala",
    title: "Operação em três países",
    body: "Times próprios no Brasil, nos Estados Unidos e em Portugal, atendimento ativo em oito países e a 42ª colocação no ranking das maiores empresas de turismo do Brasil.",
    foto: "2026-academy",
    alt: "Agências parceiras reunidas em um encontro da Just Travel Academy",
    metrics: [
      { v: "+R$ 580 milhões", l: "transacionados desde o início" },
      { v: "+2.000", l: "clientes atendidos" },
      { v: "+140", l: "colaboradores" },
    ],
  },
];

/* -------------------------------------------------------------- liderança */

// `bio` is optional on purpose. The frame carries a placeholder for two of the
// six cards (Victor Berman repeats Danilo Sampaio's paragraph, Pedro Neri
// repeats João Nou's, and the designer marked the second one in red), so those
// two ship without a paragraph rather than with a biography that belongs to
// somebody else. Fill them in and the card picks the text up with no other
// change.
//
// `valor` is the word the frame prints under the rule at the foot of each card.
const SB_LIDERANCA = [
  {
    nome: "João Nou",
    cargo: "CEO e cofundador",
    bio: "Mais de 20 anos como executivo no setor de turismo. Fundou sua primeira agência digital em 1997.",
    valor: "Visão",
    foto: "joao-nou",
  },
  {
    nome: "Fábio Barreto",
    cargo: "CIO e cofundador",
    bio: "Mais de 20 anos com inovação e empreendedorismo. Graduado em Tecnologia, pós em Inovação (UEFS).",
    valor: "Comprometimento",
    foto: "fabio-barreto",
  },
  {
    nome: "Diego Rydz",
    cargo: "CMO e cofundador",
    bio: "Mais de 20 anos em marketing digital e inbound. Bacharel em Marketing (UNIP), membro da GLA.",
    valor: "Visão",
    foto: "diego-rydz",
  },
  {
    nome: "Danilo Sampaio",
    cargo: "CFO e cofundador",
    bio: "Mais de 15 anos no mercado financeiro e consultoria estratégica. Economia (UFBA), MBA pela FGV.",
    valor: "Visão",
    foto: "danilo-sampaio",
  },
  {
    nome: "Victor Berman",
    cargo: "CCO e cofundador",
    bio: null,
    valor: "Visão",
    foto: "victor-berman",
  },
  {
    nome: "Pedro Neri",
    cargo: "CTO e cofundador",
    bio: null,
    valor: "Visão",
    foto: "pedro-neri",
  },
];

/* --------------------------------------------------------- reconhecimento */

// The Inova card carries a "sparkles" glyph rather than the frame's shield.
// The award is real and municipal, about innovation, but a shield beside the
// word "Certificação" reads as a security seal, and the site holds none: see
// the certification rule in CLAUDE.md.
const SB_AWARDS = [
  { icon: "trophy", title: "Ranking Exame Startups", sub: "Campeã no Nordeste" },
  { icon: "sparkles", title: "Certificação Inova", sub: "Prefeitura de Salvador" },
  { icon: "globe", title: "UNWTO SDGs Startup", sub: "Destaque de impacto global" },
  { icon: "chart", title: "Investidores anjo", sub: "Bossa Invest e Sai do Papel" },
];

/* --------------------------------------------------- conquistas e marcos */

// `arte` is the card's illustration and `plate` says whether it sits on the
// light-blue plate the frame paints behind the seed-rounds artwork. The first
// card pairs two marks (a trophy and the UNWTO seal) instead of one image.
const SB_CONQUISTAS = [
  {
    title: "Top 10 Turistech e semifinal UNWTO",
    body: "Reconhecida entre as 10 mais inovadoras do programa Turistech (Ministério do Turismo) e classificada para a semifinal da Organização Mundial do Turismo: validação institucional no primeiro ano de operação com capital externo.",
    marks: [
      { arte: "trofeu", alt: "", w: 480, h: 632, cls: "sb-conq__trofeu" },
      { arte: "unwto", alt: "Selo da Organização Mundial do Turismo", w: 80, h: 80, cls: "sb-conq__selo" },
    ],
  },
  {
    title: "3 rodadas seed consecutivas",
    body: "R$ 1,2M (2022), R$ 5M (2024) e uma terceira rodada (2025/2026), todas com participação recorrente do Grupo Sai do Papel e da SdP Capital, sinal de confiança mantida ao longo de múltiplos ciclos.",
    arte: "rodadas-seed",
    alt: "",
    w: 700,
    h: 700,
    plate: true,
  },
  {
    title: "Ranking Exame de Startups",
    body: "Reconhecida como uma das startups que mais cresceram no Nordeste em 2025, na categoria “Negócios em Expansão”, validação da revista de negócios mais tradicional do Brasil.",
    arte: "exame",
    alt: "Selo do Ranking Exame de Startups",
    w: 700,
    h: 466,
  },
  {
    title: "Certificação Inova Salvador",
    body: "Certificação de inovação concedida pela Prefeitura de Salvador, reconhecendo a Just Travel como empresa inovadora no ecossistema de tecnologia da capital baiana.",
    arte: "inova",
    alt: "Selo Inova Certificação Digital, da Prefeitura de Salvador",
    w: 700,
    h: 700,
  },
];

/* ------------------------------------------------------------ investidores */

// The list itself lives in landing-sections.jsx as INVESTORS, which this page
// has in scope, so the two bands render the same ten marks from the same asset
// folder. It used to be copied here, which is how a fund ends up in one band
// only. Each mark keeps its own dimensions (`w`/`h`, the trimmed exports' own):
// the band lines them up by height and lets the width follow, so a single
// declared size would squash the wide ones.

/* ============================================================
   1) Hero
   ============================================================ */
function SBHero() {
  return (
    <section className="sb-hero" id="top">
      <div className="sb-hero__panel">
        {/* Two radial blooms and the glow behind the photo are paint: bare
            spans, hidden from assistive tech, so nothing announces them. */}
        <span className="sb-hero__bloom sb-hero__bloom--a" aria-hidden="true" />
        <span className="sb-hero__bloom sb-hero__bloom--b" aria-hidden="true" />
        <div className="sb-hero__grid">
          <div className="sb-hero__copy">
            <Reveal>
              <span className="eyebrow sb-eyebrow">Tecnologia e DNA brasileiro</span>
            </Reveal>
            <Reveal delay={80}>
              <h1 className="sb-hero__title">
                A Just Travel está transformando o turismo com tecnologia, IA e{" "}
                <span className="sb-hero__title-accent">DNA brasileiro</span>
              </h1>
            </Reveal>
            <Reveal delay={160}>
              <p className="sb-hero__sub">
                Fundada em 2020, conectamos pequenas e médias agências de viagens a um
                ecossistema digital completo de vendas turísticas, com atuação internacional
                em expansão.
              </p>
            </Reveal>
          </div>

          <Reveal as="div" className="sb-hero__media" delay={120}>
            <span className="sb-hero__lit" aria-hidden="true" />
            <picture>
              <source srcSet="assets/photos/sobre/hero.avif" type="image/avif" />
              <img
                src="assets/photos/sobre/hero.webp"
                alt="Equipe da Just Travel reunida com a bandeira da empresa em frente ao globo do Universal Studios, em Orlando"
                width="1200"
                height="900"
                decoding="async"
              />
            </picture>
          </Reveal>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   2) Países + escritórios

   The same carousel the footer runs (FooterContact in landing-footer.jsx), so
   the two places the site lists its offices behave identically: giant display
   words on an auto-scrolling track, each a real button, answering with the
   offices of whichever country is selected. Hover is the headline interaction,
   but focus and tap select too, and the track parks the moment a pointer or the
   keyboard is inside it.

   What is this page's own is the card: the offices keep the photographed format
   the frame draws here, rather than the footer's icon-and-address rows.

   Brasil is selected at rest, so the card is never empty and the prerendered
   markup ships a full address.
   ============================================================ */
function SBPaises() {
  const [active, setActive] = React.useState(SB_PAISES[0].id);
  const pais = SB_PAISES.find((p) => p.id === active) || SB_PAISES[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 = (p, clone) => (
    <button
      key={(clone ? "clone-" : "") + p.id}
      type="button"
      className={"sb-pais" + (p.id === active ? " is-on" : "")}
      onMouseEnter={() => setActive(p.id)}
      onFocus={() => setActive(p.id)}
      onClick={() => setActive(p.id)}
      {...(clone
        ? { tabIndex: -1, "aria-hidden": "true" }
        : { "aria-pressed": p.id === active, "aria-controls": "sb-escritorios" })}
    >
      {p.nome}
    </button>
  );

  return (
    <section className="sb-paises" aria-label="Onde estamos">
      <div className="sb-carousel">
        <div className="sb-carousel__track">
          {SB_PAISES.map((p) => word(p, false))}
          <span className="sb-carousel__clone" aria-hidden="true">
            {SB_PAISES.map((p) => word(p, true))}
          </span>
        </div>
      </div>

      <div className="container">
        <div className="sb-escritorios" id="sb-escritorios" aria-live="polite">
          {/* keyed on the country so the entrance replays on every switch */}
          <ul className="sb-escritorios__list" key={pais.id}>
            {pais.escritorios.map((e) => (
              <li className="sb-escritorio" key={e.cidade}>
                {e.foto ? (
                  <img
                    className="sb-escritorio__foto"
                    src={`assets/photos/sobre/${e.foto}.webp`}
                    alt={e.alt}
                    width="240"
                    height="240"
                    loading="lazy"
                    decoding="async"
                  />
                ) : (
                  /* Branded tile, not an empty box: this office is waiting for
                     its photograph and the row still reads as finished. */
                  <span className="sb-escritorio__foto sb-escritorio__foto--marca" aria-hidden="true">
                    <Icon name="pin" size={26} />
                  </span>
                )}
                <div className="sb-escritorio__txt">
                  <span className="eyebrow sb-eyebrow sb-eyebrow--sm">{e.tag}</span>
                  <strong className="sb-escritorio__cidade">{e.cidade}</strong>
                  <p className="sb-escritorio__end">
                    {e.linhas.map((l, i) => (
                      <React.Fragment key={i}>{i > 0 && <br />}{l}</React.Fragment>
                    ))}
                  </p>
                </div>
              </li>
            ))}
          </ul>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   3) Quem somos
   ============================================================ */
function SBQuemSomos() {
  return (
    <section className="section section--alt sb-quem" id="quem-somos">
      <div className="container">
        <div className="sb-quem__split">
          <Reveal as="div" className="sb-quem__head">
            <span className="eyebrow">Quem somos</span>
            <h2 className="h-section">Uma travel tech com propósito</h2>
          </Reveal>
          <Reveal as="div" className="sb-quem__body" delay={80}>
            <p>
              Nascemos da percepção de que o mercado de turismo era dominado por soluções
              tecnológicas caras e inacessíveis para pequenos operadores.
            </p>
            <p>
              A Just Travel combina operação de viagens com tecnologia de ponta para
              digitalizar, desintermediar e democratizar o acesso ao turismo de forma
              escalável e transparente.
            </p>
          </Reveal>
        </div>

        <div className="sb-pilares">
          {SB_PILARES.map((p, i) => (
            /* Copy first in the source, glyph second: the tile reads title,
               text, illustration, and the grid puts the mark on the right. */
            <Reveal className="sb-pilar" key={p.title} delay={i * 80}>
              <div className="sb-pilar__copy">
                <h3 className="sb-pilar__title">{p.title}</h3>
                <p className="sb-pilar__body">{p.body}</p>
              </div>
              {/* Unsized: the stylesheet scales the glyph against the card. */}
              <span className="sb-pilar__ic">
                <Icon name={p.icon} size={null} />
              </span>
            </Reveal>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   4) Números
   ============================================================ */
function SBNumeros() {
  return (
    <section className="sb-band sb-band--black sb-numeros" id="numeros">
      <div className="container">
        <Reveal as="div" className="sect-head sb-head">
          <span className="eyebrow sb-eyebrow">Impacto real</span>
          <h2 className="h-section sb-head__title">Nossos números falam por nós</h2>
        </Reveal>

        <ul className="sb-numeros__row">
          {SB_NUMEROS.map((n, i) => (
            <Reveal as="li" className="sb-numero" key={n.l} delay={i * 90}>
              <span className="sb-numero__v">{n.v}</span>
              <span className="sb-numero__l">{n.l}</span>
            </Reveal>
          ))}
        </ul>
      </div>
    </section>
  );
}

/* ============================================================
   5) Trajetória

   One rail, one row per year, and the figures folded into the year they
   belong to. The vertical line is drawn once on the wrapper rather than per
   row, so it cannot show a seam between years, and it fades out under the
   closing block: the section ends on "so far", not on a full stop.

   The rows are not identical by design. `data-fase` carries the movement the
   year belongs to and the stylesheet reads it for the size of the year, the
   width of the photograph and the room around the row, so the three phases
   are felt as the page gets heavier rather than announced as three headings.
   ============================================================ */
function SBJornada() {
  return (
    <section className="section sb-jornada" id="trajetoria">
      <div className="container">
        <Reveal as="div" className="sb-jornada__head">
          <span className="eyebrow">Nossa trajetória</span>
          <h2 className="h-section">Uma história construída em movimento</h2>
          <p className="lead sb-jornada__sub">
            De 2020 até aqui, a Just Travel saiu de uma ideia registrada em Salvador para
            uma operação com times em três países e atendimento em oito.
          </p>
        </Reveal>

        <div className="sb-jornada__trilha">
          <ol className="sb-jornada__list">
            {SB_JORNADA.map((y, i) => (
              <Reveal
                as="li"
                className="sb-jornada__ano"
                data-fase={y.fase}
                data-abre={y.abre ? "" : null}
                key={y.ano}
                delay={Math.min(i, 3) * 70}
              >
                <div className="sb-jornada__rail">
                  {y.abre && <span className="sb-jornada__fase">{y.abre}</span>}
                  {/* The dot lives inside the year, not beside it: that is what
                      keeps it on the numeral's own centre line whether or not
                      the row opens a phase. Paint only, the year next to it is
                      the label, so nothing is announced twice. */}
                  <span className="sb-jornada__num">
                    <span className="sb-jornada__ponto" aria-hidden="true" />
                    {y.ano}
                  </span>
                </div>

                <div className="sb-jornada__conteudo">
                  <figure className="sb-jornada__foto">
                    {y.foto ? (
                      /* The dimensions are the ratio, not the file: every crop
                         comes out of the script at exactly 4:3, at whatever
                         size its master allowed, and the figure owns the box.
                         What the attributes are for here is reserving the right
                         shape before the bytes arrive. */
                      <img
                        src={`assets/photos/sobre/jornada/${y.foto}.webp`}
                        alt={y.alt}
                        width="1040"
                        height="780"
                        loading="lazy"
                        decoding="async"
                      />
                    ) : (
                      /* No photograph of this year yet. The branded plate is
                         the finished treatment, not an empty box, and the
                         numeral on it is decoration: the rail already carries
                         the year as text. */
                      <span className="sb-jornada__placa" aria-hidden="true">
                        {y.ano}
                      </span>
                    )}
                  </figure>

                  <div className="sb-jornada__texto">
                    <h3 className="sb-jornada__title">{y.title}</h3>
                    <p className="sb-jornada__body">{y.body}</p>
                    {y.metrics.length > 0 && (
                      <ul className="sb-jornada__metricas">
                        {y.metrics.map((m, j) => (
                          <li
                            className={
                              "sb-jornada__metrica" +
                              (j === 0 ? " sb-jornada__metrica--destaque" : "")
                            }
                            key={m.l}
                          >
                            <span className="sb-jornada__v">{m.v}</span>
                            <span className="sb-jornada__l">{m.l}</span>
                          </li>
                        ))}
                      </ul>
                    )}
                  </div>
                </div>
              </Reveal>
            ))}
          </ol>

          <Reveal as="div" className="sb-jornada__fim">
            <span className="sb-jornada__ponto sb-jornada__ponto--fim" aria-hidden="true" />
            <p className="sb-jornada__fim-title">E essa é só a nossa jornada até aqui.</p>
            <p className="sb-jornada__fim-sub">O futuro ainda reserva muitas conquistas.</p>
            <a className="btn btn--ghost btn--lg sb-jornada__cta" href={SB_HREF_DEMO}>
              Fale com nosso time
              <span className="btn__arrow"><Icon name="btnArrow" /></span>
            </a>
          </Reveal>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   6) Liderança
   ============================================================ */
function SBLideranca() {
  return (
    <section className="sb-band sb-band--soft sb-lideranca" id="lideranca">
      <div className="container">
        <Reveal as="div" className="sect-head sb-head">
          <span className="eyebrow sb-eyebrow">Liderança</span>
          <h2 className="h-section sb-head__title">Liderança com experiência e visão</h2>
        </Reveal>

        <ul className="sb-lider__grid">
          {SB_LIDERANCA.map((p, i) => (
            <Reveal as="li" className="sb-lider" key={p.nome} delay={(i % 3) * 90}>
              {/* The portraits are cut-outs; the gradient behind them is the
                  card's, so the photo sits on it rather than carrying its own
                  background, and is anchored to the bottom edge of the frame. */}
              <div className="sb-lider__frame">
                <img
                  className="sb-lider__foto"
                  src={`assets/photos/sobre/lideranca/${p.foto}.webp`}
                  alt={`${p.nome}, ${p.cargo} da Just Travel`}
                  width="700"
                  height="700"
                  loading="lazy"
                  decoding="async"
                />
              </div>
              <div className="sb-lider__txt">
                <span className="sb-lider__cargo">{p.cargo}</span>
                <h3 className="sb-lider__nome">{p.nome}</h3>
                {p.bio && <p className="sb-lider__bio">{p.bio}</p>}
                <span className="sb-lider__valor">{p.valor}</span>
              </div>
            </Reveal>
          ))}
        </ul>
      </div>
    </section>
  );
}

/* ============================================================
   7) Reconhecimento
   ============================================================ */
function SBReconhecimento() {
  return (
    <section className="section section--alt sb-awards" id="reconhecimento">
      <div className="container">
        <Reveal as="div" className="sect-head">
          <span className="eyebrow">Reconhecimento</span>
          <h2 className="h-section">Reconhecida pelo mercado</h2>
        </Reveal>

        <ul className="sb-awards__grid">
          {SB_AWARDS.map((a, i) => (
            <Reveal as="li" className="sb-award" key={a.title} delay={i * 80}>
              <span className="sb-award__ic">
                <Icon name={a.icon} size={null} />
              </span>
              <h3 className="sb-award__title">{a.title}</h3>
              <p className="sb-award__sub">{a.sub}</p>
            </Reveal>
          ))}
        </ul>
      </div>
    </section>
  );
}

/* ============================================================
   8) Conquistas e reconhecimentos
   ============================================================ */
function SBConquistas() {
  return (
    <section className="section section--alt sb-conq" id="conquistas">
      <div className="container">
        <Reveal as="div" className="sect-head">
          <span className="eyebrow">Conquistas e reconhecimentos</span>
          <h2 className="h-section">Marcos que validam a trajetória</h2>
        </Reveal>

        <ul className="sb-conq__grid">
          {SB_CONQUISTAS.map((c, i) => (
            <Reveal as="li" className="sb-conq__card" key={c.title} delay={(i % 2) * 90}>
              <div className={`sb-conq__arte ${c.plate ? "sb-conq__arte--plate" : ""}`}>
                {(c.marks || [c]).map((m) => (
                  <img
                    key={m.arte}
                    className={m.cls || "sb-conq__img"}
                    src={`assets/photos/sobre/conquistas/${m.arte}.webp`}
                    alt={m.alt}
                    width={m.w}
                    height={m.h}
                    loading="lazy"
                    decoding="async"
                  />
                ))}
              </div>
              <h3 className="sb-conq__title">{c.title}</h3>
              <p className="sb-conq__body">{c.body}</p>
            </Reveal>
          ))}
        </ul>
      </div>
    </section>
  );
}

/* ============================================================
   9) Investidores

   The landing carries a band with the same headline over the same list; this
   one renders it flat rather than as a marquee, because ten logos fit one row
   at this width and a loop would only move content that is already all on
   screen.
   ============================================================ */
function SBInvestidores() {
  return (
    <section className="sb-invest" id="investidores">
      <div className="container">
        <Reveal as="div" className="sb-invest__head">
          <h2 className="sb-invest__title">Nossos investidores</h2>
          <p className="sb-invest__sub">
            Já captamos <strong>+R$ 30 milhões</strong> para ajudar você a vender mais viagens.
          </p>
        </Reveal>

        <Reveal as="ul" className="sb-invest__row" delay={80}>
          {INVESTORS.map((inv) => (
            <li key={inv.file}>
              <img
                className="sb-invest__logo"
                src={`assets/logos/${inv.file}`}
                alt={inv.name}
                width={inv.w}
                height={inv.h}
                loading="lazy"
                decoding="async"
              />
            </li>
          ))}
        </Reveal>
      </div>
    </section>
  );
}

/* ============================================================ */
function SBApp() {
  return (
    <PageShell>
      <main>
        {/* Hero and the country marquee share one near-black shell, the way
            Seguranca.html's hero and compliance strip share theirs: the panel's
            rounded corners have to sit on the same dark ground the marquee
            runs across, not on the page's white. */}
        <div className="sb-top">
          <SBHero />
          <SBPaises />
        </div>
        <SBQuemSomos />
        <SBNumeros />
        <SBJornada />
        <SBLideranca />
        <SBReconhecimento />
        <SBConquistas />
        <SBInvestidores />
      </main>
    </PageShell>
  );
}

(function () {
  const el = document.getElementById("app");
  if (!el) return;
  ReactDOM.createRoot(el).render(<SBApp />);
})();
