// Tidal · Portal Genesis — Documentos do Manifesto
// Sub-abas do Manifesto: Crew List (ANVISA), DMS, Gangway.
// Todos derivam da MESMA lista "abordo" (/api/boarding/manifesto). Nada de módulo novo.
// Depende de: ui.jsx (useT, useMobile, Avatar, useToast) e anvisa-assets.js (window.ANVISA_ASSETS).

/* ════════════════════════════════════════════════════════════════════════
   ORDENAÇÃO — empresa → patente (Marinha Mercante)
   Portado do Cabin Management System (Renzo).
   ════════════════════════════════════════════════════════════════════════ */
const MD_COMPANY_ORDER = ["OSM","SEAGEMS","SUBSEA7","PRIO","KCC/PRIO","FUGRO","TECHNIP","Marfood","FAC","NORPEM","DeepSea","IHCARE","MARCENARIA","PLOTADORA"];

const MD_GENERIC_RANK = ["master","commandant","captain","comandante","chief officer","1st officer","imediato","oficial de náutica","2nd officer","3rd officer","dpo","dynamic positioning operator","chief engineer","chefe de máquinas","2nd engineer","subchefe","sub-chefe","3rd engineer","4th engineer","electrician","electrical officer","eletricista","bosun","boatswain","mestre","able seaman","able bodied","marinheiro","ordinary seaman","moço","crane operator","guindasteiro","motorman","motor man","oiler","lubrificador","fitter","mecânico","camp boss","comissário chefe","head cook","chief cook","cozinheiro chefe","maritime cook","cozinheiro","cook assistant","assistente de cozinha","baker","confeiteiro","padeiro","steward","comissário","messman","arrumador","almoxarife","medic","paramedic","nurse","enfermeiro","médico","instructor","professor","oim","offshore installation manager","offshore manager","gerente offshore","company man","company representative","representante","shift supervisor","supervisor de turno","superintendent","rov supervisor","supervisor de rov","supervisora de rov","rov pilot","rov operator","operador de rov","operadora de rov","launch supervisor","supervisor de lançamento","supervisora de lançamento","laying engineer","laying eng","engenheiro de lançamento","engenheira de lançamento","launch engineer","engenheiro de operações","engenheira de operações","operations engineer","launch operator","operador de lançamento","operadora de lançamento","surveyor","survey technician","associate survey technician","supervisor","technician","técnico","técnica","tec.","tsp","tst","trainee","estagiário","supernumerary"];

const MD_COMPANY_RANK = { "SEAGEMS":[ "oim","offshore installation manager", "shift supervisor","supervisor de turno", "launch supervisor","supervisor de lançamento","supervisora de lançamento", "laying engineer","laying eng","engenheiro de lançamento","engenheira de lançamento", "operations engineer","engenheiro de operações","engenheira de operações","launch engineer", "instructor","professor", "launch operator","operador de lançamento","operadora de lançamento", "trainee","estagiário" ] };

const mdCompanyIdx = (co) => { const i = MD_COMPANY_ORDER.indexOf(co); return i < 0 ? 900 + (co || "").charCodeAt(0) / 1000 : i; };
const mdRankIdx = (co, role) => {
  role = (role || "").toLowerCase();
  const list = MD_COMPANY_RANK[co];
  if (list) { for (let i = 0; i < list.length; i++) if (role.includes(list[i])) return i; }
  for (let i = 0; i < MD_GENERIC_RANK.length; i++) if (role.includes(MD_GENERIC_RANK[i])) return i;
  return 998;
};
const mdRankSort = (a, b) => {
  const ca = mdCompanyIdx(a.empresa), cb = mdCompanyIdx(b.empresa);
  if (ca !== cb) return ca - cb;
  const ra = mdRankIdx(a.empresa, a.funcao), rb = mdRankIdx(b.empresa, b.funcao);
  if (ra !== rb) return ra - rb;
  return (a.nome || "").localeCompare(b.nome || "");
};

/* ════════════════════════════════════════════════════════════════════════
   HELPERS
   ════════════════════════════════════════════════════════════════════════ */
const mdEsc = (s) => String(s == null ? "" : s).replace(/[&<>"']/g, c => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
const mdToday = () => new Date().toISOString().split("T")[0];
const mdBrDate = (iso) => { if (!iso) return ""; const [y, m, d] = String(iso).split("T")[0].split("-"); return d ? `${d}/${m}/${y}` : iso; };
const mdPK = (u) => u.genesis_id || String(u.id);
const mdIsoDay = (v) => v ? String(v).split("T")[0] : "";

// Carrega um script externo uma única vez
const mdLoadScript = (src) => new Promise((resolve, reject) => {
  const s = document.createElement("script");
  s.src = src; s.onload = () => resolve(true); s.onerror = () => reject(new Error("load fail: " + src));
  document.head.appendChild(s);
});

// Garante SheetJS (XLSX)
const mdEnsureXLSX = async () => {
  if (window.XLSX) return;
  await mdLoadScript("https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js");
};

// Garante a lib docx (UMD → window.docx), com fallback
const mdEnsureDocx = async () => {
  if (window.docx) return;
  const urls = [
    "https://cdn.jsdelivr.net/npm/docx@9.5.1/build/index.umd.js",
    "https://unpkg.com/docx@9.5.1/build/index.umd.js",
    "https://cdn.jsdelivr.net/npm/docx@8.5.0/build/index.js",
  ];
  for (const u of urls) {
    try { await mdLoadScript(u); if (window.docx) return; } catch (e) { /* tenta próxima */ }
  }
  if (!window.docx) throw new Error("Não foi possível carregar a biblioteca docx.");
};

// data:...;base64,XXXX → Uint8Array
const mdB64ToBytes = (dataURI) => {
  const b64 = String(dataURI).split(",")[1] || "";
  const bin = atob(b64);
  const bytes = new Uint8Array(bin.length);
  for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
  return bytes;
};

const mdDownloadBlob = (blob, filename) => {
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url; a.download = filename; document.body.appendChild(a); a.click();
  setTimeout(() => { URL.revokeObjectURL(url); a.remove(); }, 1200);
};

/* ════════════════════════════════════════════════════════════════════════
   MODAL simples (não há primitive de modal no Tidal)
   ════════════════════════════════════════════════════════════════════════ */
const MdModal = ({ open, onClose, title, children, maxWidth = 760 }) => {
  if (!open) return null;
  return (
    <div onClick={onClose} style={{
      position: "fixed", inset: 0, zIndex: 9000, background: "rgba(31,42,46,0.45)",
      display: "flex", alignItems: "flex-start", justifyContent: "center", padding: "5vh 16px", overflowY: "auto"
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        background: "var(--surface)", borderRadius: 22, width: "100%", maxWidth,
        boxShadow: "var(--shadow-lg)", border: "1px solid var(--line-soft)", animation: "slideIn .25s cubic-bezier(.2,.7,.3,1) both"
      }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "18px 22px", borderBottom: "1px solid var(--line-soft)" }}>
          <h3 className="t-h3" style={{ fontFamily: "var(--fs)", fontSize: 20, fontWeight: 400 }}>{title}</h3>
          <button className="btn ghost btn-sm" onClick={onClose}>✕</button>
        </div>
        <div style={{ padding: 22 }}>{children}</div>
      </div>
    </div>
  );
};

/* ════════════════════════════════════════════════════════════════════════
   CREW LIST — ANVISA Standard
   ════════════════════════════════════════════════════════════════════════ */
const CrewListAnvisa = ({ abordo = [], loading }) => {
  const tt = useT();
  const isEN = tt.lang === "en";
  const toast = useToast();
  const isMobile = useMobile();

  const [companyOrder, setCompanyOrder] = useState(null); // array de empresas (manual) | null
  const [personOrder, setPersonOrder] = useState({});     // { empresa: [keys] }
  const [exportOpen, setExportOpen] = useState(false);
  const [meta, setMeta] = useState({ port: "", date: mdToday(), flag: "Brasil / Brazil", from: "", local: "Macaé - RJ", localdate: mdToday(), sig: "ludovik" });
  const [rowDates, setRowDates] = useState({}); // { key: {jd,jp,ld,lp} }
  const [bulk, setBulk] = useState({ jd: "", jp: "", ld: "", lp: "" });

  // ── drag state (dois níveis) ──
  const dragType = useRef(null);      // 'company' | 'person'
  const dragCompany = useRef(null);   // empresa arrastada
  const dragPerson = useRef(null);    // { key, company }
  const [overCompany, setOverCompany] = useState(null);
  const [overPerson, setOverPerson] = useState(null);

  const COMP = (u) => u.empresa || "(sem empresa)";
  const byKey = {}; abordo.forEach(u => { byKey[mdPK(u)] = u; });

  // empresas presentes, na ordem padrão (hierarquia de empresa)
  const presentCompanies = [...new Set(abordo.map(COMP))];
  const defaultCompanyOrder = presentCompanies.slice().sort((a, b) => mdCompanyIdx(a) - mdCompanyIdx(b));
  // reconcilia ordem manual com o que está realmente a bordo (empresas novas entram no fim, na posição padrão)
  const compOrder = (() => {
    if (!companyOrder) return defaultCompanyOrder;
    const kept = companyOrder.filter(c => presentCompanies.includes(c));
    const added = defaultCompanyOrder.filter(c => !kept.includes(c));
    return [...kept, ...added];
  })();

  // pessoas de uma empresa, na ordem (manual reconciliada → senão hierarquia)
  const peopleOf = (c) => {
    const all = abordo.filter(u => COMP(u) === c);
    const def = all.slice().sort(mdRankSort).map(mdPK);
    const saved = personOrder[c];
    let keys = def;
    if (saved) {
      const present = all.map(mdPK);
      const kept = saved.filter(k => present.includes(k));
      const added = def.filter(k => !kept.includes(k));
      keys = [...kept, ...added];
    }
    const bk = {}; all.forEach(u => { bk[mdPK(u)] = u; });
    return keys.map(k => bk[k]).filter(Boolean);
  };

  const groups = compOrder.map(c => ({ company: c, people: peopleOf(c) }));
  const list = groups.flatMap(g => g.people);            // lista achatada (PDF/Excel/contagem)
  const hasManual = !!companyOrder || Object.keys(personOrder).length > 0;

  // valores efetivos de datas/lugares por pessoa (override do modal → senão embarque do perfil)
  const rd = (u) => {
    const k = mdPK(u);
    const o = rowDates[k] || {};
    return {
      jd: o.jd != null ? o.jd : mdIsoDay(u.embarque),
      jp: o.jp != null ? o.jp : (u.embark_port || ""),
      ld: o.ld != null ? o.ld : "",
      lp: o.lp != null ? o.lp : (u.disembark_port || ""),
    };
  };
  const setRD = (k, field, val) => setRowDates(s => ({ ...s, [k]: { ...rd(byKey[k]), ...s[k], [field]: val } }));

  // ── reordenar empresas ──
  const moveCompany = (drag, target) => {
    if (!drag || drag === target) return;
    let o = compOrder.slice().filter(x => x !== drag);
    const ti = o.indexOf(target);
    o.splice(ti < 0 ? o.length : ti, 0, drag);
    setCompanyOrder(o);
  };
  // ── reordenar pessoa DENTRO da própria empresa ──
  const movePerson = (c, dragK, targetK) => {
    if (!dragK || dragK === targetK) return;
    let o = peopleOf(c).map(mdPK).filter(x => x !== dragK);
    const ti = o.indexOf(targetK);
    o.splice(ti < 0 ? o.length : ti, 0, dragK);
    setPersonOrder(s => ({ ...s, [c]: o }));
  };

  const resetOrder = () => { setCompanyOrder(null); setPersonOrder({}); toast.push({ icon: "check", title: isEN ? "Default order restored." : "Ordem padrão restaurada." }); };

  const bulkFill = (overwrite) => {
    setRowDates(prev => {
      const next = { ...prev };
      list.forEach(u => {
        const k = mdPK(u); const cur = { ...rd(u), ...next[k] };
        if (bulk.jd && (overwrite || !cur.jd)) cur.jd = bulk.jd;
        if (bulk.jp && (overwrite || !cur.jp)) cur.jp = bulk.jp;
        if (bulk.ld && (overwrite || !cur.ld)) cur.ld = bulk.ld;
        if (bulk.lp && (overwrite || !cur.lp)) cur.lp = bulk.lp;
        next[k] = cur;
      });
      return next;
    });
    toast.push({ icon: "check", title: overwrite ? (isEN ? "All rows updated." : "Todas as linhas atualizadas.") : (isEN ? "Blanks filled." : "Lacunas preenchidas.") });
  };

  /* ---- PDF oficial (Padrão ANVISA) ---- */
  const exportPDF = () => {
    const A = window.ANVISA_ASSETS || {};
    const SIG = A.SIG || {};
    let body = list.map(u => {
      const d = rd(u);
      const emb = d.jd ? mdBrDate(d.jd) + (d.jp ? " " + mdEsc(d.jp) : "") : "CHECAR DATA";
      const des = d.ld ? mdBrDate(d.ld) + (d.lp ? " " + mdEsc(d.lp) : "") : "CHECAR DATA ---&gt;";
      return `<tr><td class="nm">${mdEsc(u.nome)}</td><td class="ct">${mdEsc(u.funcao || "")}</td><td class="ct">${mdEsc(u.nationality || "Brasileiro")}</td><td class="ct">${emb}</td><td class="ct">${des}</td></tr>`;
    }).join("");
    const pad = Math.max(0, (list.length <= 40 ? 40 : Math.ceil(list.length / 40) * 40) - list.length);
    for (let i = 0; i < pad; i++) body += '<tr><td>&nbsp;</td><td></td><td></td><td></td><td></td></tr>';

    const port = mdEsc(meta.port), date = mdEsc(mdBrDate(meta.date)), flag = mdEsc(meta.flag);
    const from = mdEsc(meta.from), local = mdEsc(meta.local), localdate = mdEsc(mdBrDate(meta.localdate));

    const w = window.open("", "_blank");
    w.document.write(`<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Crew List — Genesis I</title>
<style>
  @page{size:A4 portrait;margin:10mm 9mm;}
  *{box-sizing:border-box;font-family:Arial,Helvetica,sans-serif;}
  body{color:#000;font-size:10px;}
  .top{display:table;width:100%;margin-bottom:2px;}
  .top>div{display:table-cell;vertical-align:middle;text-align:center;}
  .top .side{width:120px;} .top .side img{height:88px;}
  .top .ctr b{display:block;font-size:12px;line-height:1.15;}
  .top .ctr .sub{display:block;font-size:8.5px;line-height:1.1;margin-bottom:2px;}
  .anvisa{text-align:center;margin:2px 0 0;} .anvisa img{height:34px;}
  .title{text-align:center;font-weight:bold;font-size:13px;margin:4px 0 6px;}
  table{width:100%;border-collapse:collapse;}
  .meta td{border:1px solid #000;padding:3px 6px;font-size:9px;vertical-align:middle;text-align:center;}
  .meta .lbl{font-weight:bold;}
  .data th{border:1px solid #000;padding:5px 4px;font-size:8.5px;vertical-align:middle;text-align:center;font-weight:normal;}
  .data th b{display:block;} .data th .en{display:block;font-weight:normal;}
  .data td{border:1px solid #000;padding:3px 6px;font-size:9px;height:17px;}
  .data td.ct{text-align:center;} .data .nm{text-align:left;}
  .foot{margin-top:14px;font-size:9.5px;text-align:center;line-height:1.45;}
  .foot .liab{font-weight:bold;} .foot .liab i{font-weight:bold;font-style:italic;}
  .sigwrap{margin-top:10px;text-align:center;} .sigwrap img{max-height:78px;}
  .sigline{border-top:1px solid #000;width:80%;margin:4px auto 0;padding-top:3px;}
  tr{page-break-inside:avoid;} thead{display:table-header-group;}
</style></head><body>
  <div class="top">
    <div class="side"><img src="${A.ARMS || ""}" alt=""></div>
    <div class="ctr">
      <b>REPÚBLICA FEDERATIVA DO BRASIL</b><span class="sub">(FEDERATIVE REPUBLIC OF BRAZIL)</span>
      <b>MARINHA DO BRASIL</b><span class="sub">(BRAZILIAN NAVY)</span>
      <b>DIRETORIA DE PORTOS E COSTAS</b><span class="sub">(DIRECTORATE OF HARBOURS AND COAST)</span>
    </div>
    <div class="side"><img src="${A.NAVY || ""}" alt=""></div>
  </div>
  <div class="anvisa"><img src="${A.ANVISA || ""}" alt="ANVISA"></div>
  <div class="title">LISTA DE TRIPULANTES / CREW LIST (Padrão ANVISA)</div>
  <table class="meta">
    <tr><td class="lbl" style="width:40%">1. Nome do Navio (Name of Ship)</td><td class="lbl" colspan="2" style="width:30%">2. Porto Cheg. / Part. (Arr./Dep. Port)</td><td class="lbl" colspan="2" style="width:30%">3. Data Cheg. / Part. (Arr/Dep. Date)</td></tr>
    <tr><td>Genesis I</td><td colspan="2">${port}</td><td colspan="2">${date}</td></tr>
    <tr><td class="lbl" colspan="2">4. Nacionalidade do Navio (Nationality of Ship)</td><td class="lbl" colspan="3">5. Porto de Procedência (Port arrived from)</td></tr>
    <tr><td colspan="2">${flag}</td><td colspan="3">${from}</td></tr>
  </table>
  <table class="data">
   <thead><tr>
    <th style="width:32%"><b>6. Nome e Sobrenome</b><span class="en">(Family name, given names)</span></th>
    <th style="width:16%"><b>7. Grau ou Função</b><span class="en">(Rank or Rating)</span></th>
    <th style="width:13%"><b>8. Nacionalidade</b><span class="en">(Nationality)</span></th>
    <th style="width:19.5%"><b>9. Data e lugar de Embarque</b><span class="en">(Date and place of Embark)</span></th>
    <th style="width:19.5%"><b>10. Data e lugar de Desembarque</b><span class="en">(Date and place of Disembark)</span></th></tr></thead>
   <tbody>${body}</tbody></table>
  <div class="foot">
    <p class="liab">Estou ciente de que responderei administrativa, civil ou penalmente pelos eventuais dados incorretos constantes da presente lista.</p>
    <p class="liab"><i>I am aware that i will be held liable before Administrative Law, Civil Law, or Criminal Law for any eventual incorrect data stated herein.</i></p>
    <p class="liab" style="margin-top:8px">Local: ${local}, ${localdate}</p>
    <div class="sigwrap">${SIG[meta.sig] ? `<img src="${SIG[meta.sig]}" alt="">` : ""}</div>
    <div class="sigline">Assinatura do Comandante ou Oficial Designado / Carimbo da Embarcação<br>(Signature of Captain or Official Authorized / Stamp of Vessel)</div>
  </div>
  <script>window.onload=function(){setTimeout(function(){window.print();},350);}<\/script>
  </body></html>`);
    w.document.close();
  };

  /* ---- Excel ---- */
  const exportExcel = async () => {
    await mdEnsureXLSX();
    const rows = list.map((u, i) => {
      const d = rd(u);
      return {
        "#": i + 1,
        "Nome e Sobrenome": u.nome || "",
        "Grau ou Função": u.funcao || "",
        "Empresa": u.empresa || "",
        "Nacionalidade": u.nationality || "Brasileiro",
        "Data de Embarque": d.jd ? mdBrDate(d.jd) : "",
        "Lugar de Embarque": d.jp || "",
        "Data de Desembarque": d.ld ? mdBrDate(d.ld) : "",
        "Lugar de Desembarque": d.lp || "",
      };
    });
    const ws = window.XLSX.utils.json_to_sheet(rows);
    ws["!cols"] = [4, 28, 20, 18, 14, 15, 16, 15, 16].map(w => ({ wch: w }));
    const wb = window.XLSX.utils.book_new();
    window.XLSX.utils.book_append_sheet(wb, ws, "Crew List");
    window.XLSX.writeFile(wb, `crewlist_anvisa_${mdToday()}.xlsx`);
  };

  // estilo base de input do modal — box-sizing resolve o estouro das caixas
  const inp = { width: "100%", boxSizing: "border-box", minWidth: 0 };
  const cols = isMobile ? "30px 1fr 1fr" : "34px 26px 1.6fr 1.1fr 0.9fr 1.1fr 1.1fr";

  // ── render ──
  let rowNum = 0;
  return (
    <div>
      <div className="section-h" style={{ marginBottom: 16 }}>
        <div>
          <div className="t-eyebrow" style={{ marginBottom: 6 }}>{isEN ? "ANVISA standard" : "Padrão ANVISA"}</div>
          <h2 style={{ fontFamily: "var(--fs)", fontWeight: 400 }}>Crew <em>List.</em> <span style={{ fontFamily: "var(--fm)", fontSize: 14, color: "var(--muted)" }}>({list.length})</span></h2>
        </div>
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
          {hasManual && <button className="btn-icone neutro" onClick={resetOrder} title={isEN ? "default order" : "voltar à ordem padrão"}>↺</button>}
          <button className="btn-icone" onClick={() => setExportOpen(true)} title={isEN ? "generate PDF / Excel" : "gerar PDF / Excel"}>⤓</button>
        </div>
      </div>

      <p style={{ fontSize: 12, color: "var(--muted)", marginBottom: 14 }}>
        {isEN
          ? "Drag the company header (⠿) to reorder companies; drag a person to reorder within their own company. New companies appear automatically."
          : "Arraste o cabeçalho da empresa (⠿) para reordenar empresas; arraste uma pessoa para reordenar dentro da própria empresa. Empresas novas aparecem automaticamente."}
        {hasManual && <strong style={{ color: "var(--sun)" }}> {isEN ? "⚠ Manual order active." : "⚠ Ordem manual ativa."}</strong>}
      </p>

      {loading ? (
        <div className="empty" style={{ padding: 50 }}>{isEN ? "loading…" : "carregando…"}</div>
      ) : !list.length ? (
        <div className="empty" style={{ padding: "50px 20px" }}>{isEN ? "No crew on board." : "Ninguém a bordo."}</div>
      ) : (
        <div style={{ background: "var(--surface)", border: "1px solid var(--line-soft)", borderRadius: 18, overflow: "hidden", boxShadow: "var(--shadow-sm)" }}>
          {/* header de colunas */}
          <div style={{ display: "grid", gridTemplateColumns: cols, padding: "10px 16px", background: "var(--cream-2)", fontFamily: "var(--fm)", fontSize: 10, letterSpacing: 1, textTransform: "uppercase", color: "var(--muted)" }}>
            <div>#</div>{!isMobile && <div></div>}
            <div>{isEN ? "Family name, given names" : "Nome e Sobrenome"}</div>
            <div>{isEN ? "Rank / Role" : "Grau / Função"}</div>
            {!isMobile && <><div>{isEN ? "Nationality" : "Nacionalidade"}</div><div>{isEN ? "Embark" : "Embarque"}</div><div>{isEN ? "Disembark" : "Desembarque"}</div></>}
          </div>

          {groups.map((g) => (
            <div key={g.company}>
              {/* cabeçalho da empresa — arrastável (reordena empresas) */}
              <div draggable
                onDragStart={() => { dragType.current = "company"; dragCompany.current = g.company; }}
                onDragOver={(e) => { if (dragType.current === "company") { e.preventDefault(); setOverCompany(g.company); } }}
                onDrop={(e) => { if (dragType.current === "company") { e.preventDefault(); moveCompany(dragCompany.current, g.company); } setOverCompany(null); dragType.current = null; dragCompany.current = null; }}
                onDragEnd={() => { setOverCompany(null); dragType.current = null; dragCompany.current = null; }}
                style={{ display: "flex", alignItems: "center", gap: 8, padding: "8px 16px", background: overCompany === g.company ? "var(--accent-soft)" : "var(--cream-3)", borderTop: "1px solid var(--line-soft)", cursor: "grab", fontFamily: "var(--fm)", fontSize: 11, fontWeight: 600, color: "var(--ink-2)", letterSpacing: 0.5 }}>
                <span style={{ color: "var(--muted-2)" }}>⠿</span>
                <span>{g.company}</span>
                <span style={{ color: "var(--muted-2)", fontWeight: 400 }}>· {g.people.length}</span>
              </div>

              {/* pessoas — arrastáveis só dentro da própria empresa */}
              {g.people.map((u) => {
                const k = mdPK(u); const d = rd(u); rowNum += 1; const n = rowNum;
                return (
                  <div key={k} draggable
                    onDragStart={(e) => { e.stopPropagation(); dragType.current = "person"; dragPerson.current = { key: k, company: g.company }; }}
                    onDragOver={(e) => { if (dragType.current === "person" && dragPerson.current && dragPerson.current.company === g.company) { e.preventDefault(); setOverPerson(k); } }}
                    onDrop={(e) => { if (dragType.current === "person" && dragPerson.current && dragPerson.current.company === g.company) { e.preventDefault(); movePerson(g.company, dragPerson.current.key, k); } setOverPerson(null); dragType.current = null; dragPerson.current = null; }}
                    onDragEnd={() => { setOverPerson(null); dragType.current = null; dragPerson.current = null; }}
                    style={{ display: "grid", gridTemplateColumns: cols, padding: "9px 16px", alignItems: "center", borderTop: "1px solid var(--line-soft)", fontSize: 13, background: overPerson === k ? "var(--accent-soft)" : (n % 2 ? "rgba(0,0,0,0.012)" : "transparent"), cursor: "grab" }}>
                    <div style={{ fontFamily: "var(--fm)", fontSize: 12, color: "var(--muted)" }}>{n}</div>
                    {!isMobile && <div style={{ color: "var(--muted-3)" }}>⠿</div>}
                    <div style={{ display: "flex", alignItems: "center", gap: 8, minWidth: 0 }}><Avatar user={u} size="sm" /><span style={{ fontWeight: 500, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{u.nome}</span></div>
                    <div style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{u.funcao || "—"}{isMobile && <div style={{ fontSize: 10.5, color: "var(--muted)", fontFamily: "var(--fm)" }}>{u.empresa}</div>}</div>
                    {!isMobile && <><div style={{ fontSize: 12, color: "var(--muted)" }}>{u.nationality || "Brasileiro"}</div>
                      <div style={{ fontFamily: "var(--fm)", fontSize: 11, color: d.jd ? "var(--ink-2)" : "var(--muted-3)" }}>{d.jd ? mdBrDate(d.jd) : "CHECK"}</div>
                      <div style={{ fontFamily: "var(--fm)", fontSize: 11, color: d.ld ? "var(--ink-2)" : "var(--muted-3)" }}>{d.ld ? mdBrDate(d.ld) : "—"}</div></>}
                  </div>
                );
              })}
            </div>
          ))}
        </div>
      )}

      {/* ── Modal de export ── */}
      <MdModal open={exportOpen} onClose={() => setExportOpen(false)} title={isEN ? "Generate Crew List" : "Gerar Crew List"} maxWidth={880}>
        <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "1fr 1fr", gap: 12, marginBottom: 18 }}>
          <div style={{ minWidth: 0 }}><label className="label">Porto Cheg./Part. (Arr./Dep. Port)</label><input className="input" style={inp} value={meta.port} onChange={e => setMeta({ ...meta, port: e.target.value })} placeholder="Porto do Açu" /></div>
          <div style={{ minWidth: 0 }}><label className="label">Data Cheg./Part.</label><input className="input" type="date" style={inp} value={meta.date} onChange={e => setMeta({ ...meta, date: e.target.value })} /></div>
          <div style={{ minWidth: 0 }}><label className="label">Nacionalidade do Navio (Flag)</label><input className="input" style={inp} value={meta.flag} onChange={e => setMeta({ ...meta, flag: e.target.value })} /></div>
          <div style={{ minWidth: 0 }}><label className="label">Porto de Procedência (From)</label><input className="input" style={inp} value={meta.from} onChange={e => setMeta({ ...meta, from: e.target.value })} /></div>
          <div style={{ minWidth: 0 }}><label className="label">Local (assinatura)</label><input className="input" style={inp} value={meta.local} onChange={e => setMeta({ ...meta, local: e.target.value })} /></div>
          <div style={{ minWidth: 0 }}><label className="label">Data (local)</label><input className="input" type="date" style={inp} value={meta.localdate} onChange={e => setMeta({ ...meta, localdate: e.target.value })} /></div>
        </div>

        <label className="label">Assinatura</label>
        <div style={{ display: "flex", gap: 8, marginBottom: 18, flexWrap: "wrap" }}>
          {["ludovik", "radek"].map(s => (
            <button key={s} className={meta.sig === s ? "btn btn-primary btn-sm" : "btn btn-sm"} onClick={() => setMeta({ ...meta, sig: s })} style={{ textTransform: "capitalize" }}>{s}</button>
          ))}
        </div>

        <label className="label">Datas e lugares de embarque/desembarque</label>
        <div style={{ background: "var(--cream-2)", borderRadius: 12, padding: 12, marginBottom: 10, display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(130px, 1fr))", gap: 8, alignItems: "end" }}>
          <div style={{ minWidth: 0 }}><label className="label" style={{ fontSize: 9 }}>Embarque (todos)</label><input className="input" type="date" style={{ ...inp, padding: "6px 8px", fontSize: 12 }} value={bulk.jd} onChange={e => setBulk({ ...bulk, jd: e.target.value })} /></div>
          <div style={{ minWidth: 0 }}><label className="label" style={{ fontSize: 9 }}>Lugar emb.</label><input className="input" style={{ ...inp, padding: "6px 8px", fontSize: 12 }} value={bulk.jp} onChange={e => setBulk({ ...bulk, jp: e.target.value })} placeholder="Açu" /></div>
          <div style={{ minWidth: 0 }}><label className="label" style={{ fontSize: 9 }}>Desemb. (todos)</label><input className="input" type="date" style={{ ...inp, padding: "6px 8px", fontSize: 12 }} value={bulk.ld} onChange={e => setBulk({ ...bulk, ld: e.target.value })} /></div>
          <div style={{ minWidth: 0 }}><label className="label" style={{ fontSize: 9 }}>Lugar desemb.</label><input className="input" style={{ ...inp, padding: "6px 8px", fontSize: 12 }} value={bulk.lp} onChange={e => setBulk({ ...bulk, lp: e.target.value })} /></div>
          <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
            <button className="btn btn-sm" onClick={() => bulkFill(false)}>{isEN ? "Fill blanks" : "Preencher vazios"}</button>
            <button className="btn btn-sm" onClick={() => bulkFill(true)}>{isEN ? "All" : "Todos"}</button>
          </div>
        </div>

        <div style={{ maxHeight: 260, overflowY: "auto", overflowX: "hidden", border: "1px solid var(--line-soft)", borderRadius: 12 }}>
          {list.map((u, i) => {
            const k = mdPK(u); const d = rd(u);
            return (
              <div key={k} style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr 1fr" : "minmax(0,1.4fr) minmax(0,1fr) minmax(0,0.9fr) minmax(0,1fr) minmax(0,0.9fr)", gap: 6, padding: "6px 10px", alignItems: "center", background: i % 2 ? "var(--cream-2)" : "transparent" }}>
                <div style={{ fontSize: 11, fontWeight: 600, minWidth: 0, gridColumn: isMobile ? "1 / -1" : "auto" }}>{u.nome}<div style={{ fontSize: 9, fontWeight: 400, color: "var(--muted)" }}>{u.funcao} · {u.empresa}</div></div>
                <input className="input" type="date" style={{ ...inp, padding: "4px 6px", fontSize: 10 }} value={d.jd} onChange={e => setRD(k, "jd", e.target.value)} />
                <input className="input" style={{ ...inp, padding: "4px 6px", fontSize: 10 }} placeholder="lugar emb." value={d.jp} onChange={e => setRD(k, "jp", e.target.value)} />
                <input className="input" type="date" style={{ ...inp, padding: "4px 6px", fontSize: 10 }} value={d.ld} onChange={e => setRD(k, "ld", e.target.value)} />
                <input className="input" style={{ ...inp, padding: "4px 6px", fontSize: 10 }} placeholder="lugar desemb." value={d.lp} onChange={e => setRD(k, "lp", e.target.value)} />
              </div>
            );
          })}
        </div>

        <div style={{ display: "flex", gap: 10, marginTop: 18, justifyContent: "flex-end", flexWrap: "wrap" }}>
          <button className="btn-tidal-sec" onClick={exportExcel}>📊 Excel</button>
          <button className="btn-tidal" onClick={exportPDF}>📄 PDF (ANVISA)</button>
        </div>
      </MdModal>
    </div>
  );
};

/* ════════════════════════════════════════════════════════════════════════
   GANGWAY — Visitors Record Book (.docx, client-side)
   ════════════════════════════════════════════════════════════════════════ */
// ─── Gangway Record Book como .doc via HTML (sem CDN — robusto na internet de bordo) ───
const mdGangwayDocHtml = (people, minRows = 80) => {
  const HDR = ["Visitor\u2019s Name", "Visitor\u2019s Company / business onboard", "Visitor\u2019s Pass No.", "Date / Time On", "Personal belongings checked Yes/No", "Visitor\u2019s Signature", "Date / Time Off", "Duty Crew Signature"];
  const named = (people || []).filter(p => (p.name || "").trim());
  const total = Math.max(named.length + 8, minRows);
  const rows = named.slice();
  while (rows.length < total) rows.push({ name: "", company: "" });
  const body = rows.map(p => `<tr><td class="nm">${mdEsc(p.name)}</td><td class="co">${mdEsc(p.company)}</td><td></td><td></td><td></td><td></td><td></td><td></td></tr>`).join("");
  const thead = `<tr>${HDR.map(h => `<th>${mdEsc(h)}</th>`).join("")}</tr>`;
  return `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40">
<head><meta charset="utf-8"><title>Gangway Visitors Record Book - Genesis I</title>
<!--[if gte mso 9]><xml><w:WordDocument><w:View>Print</w:View></w:WordDocument></xml><![endif]-->
<style>
@page { size: 29.7cm 21.0cm; mso-page-orientation: landscape; margin: 1.0cm 0.8cm; }
body { font-family: 'Times New Roman', serif; font-size: 11pt; }
.title { font-family: Arial, sans-serif; font-size: 17pt; font-weight: bold; text-align: center; margin: 0; }
.sub { font-family: Arial, sans-serif; font-size: 11pt; text-align: center; margin: 2px 0 0; }
.meta { font-family: Arial, sans-serif; font-size: 9pt; text-align: right; margin: 4px 0 6px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #000; padding: 5px 6px; font-size: 9.5pt; vertical-align: middle; height: 26pt; }
th { background: #E6E6E6; font-family: Arial, sans-serif; font-size: 8.5pt; text-align: center; }
td.nm { font-weight: bold; white-space: nowrap; }
td.co { font-size: 8.5pt; }
</style></head>
<body>
<p class="title">Gangway Visitors Record Book</p>
<p class="sub">MPSV Genesis I &nbsp;&middot;&nbsp; Marsec Level 1</p>
<p class="meta">Data / Date: ${mdEsc(mdToday())}</p>
<table><thead>${thead}</thead><tbody>${body}</tbody></table>
</body></html>`;
};


const GangwayRecordBook = ({ abordo = [] }) => {
  const tt = useT();
  const isEN = tt.lang === "en";
  const toast = useToast();
  const [scope, setScope] = useState("guest"); // guest | all
  const [busy, setBusy] = useState(false);

  const people = (scope === "guest" ? abordo.filter(u => u.role === "guest") : abordo)
    .map(u => ({ name: u.nome || "", company: u.empresa || "" }));

  const generate = () => {
    setBusy(true);
    try {
      const html = mdGangwayDocHtml(people);
      const blob = new Blob(["\ufeff", html], { type: "application/msword" });
      mdDownloadBlob(blob, `Gangway_Visitors_Genesis_${mdToday()}.doc`);
      toast.push({ icon: "check", title: isEN ? "Document generated." : "Documento gerado.", body: isEN ? "Opens in Word." : "Abre no Word." });
    } catch (e) {
      console.error(e);
      toast.push({ icon: "x", title: isEN ? "Failed to generate." : "Falha ao gerar.", body: e.message });
    } finally { setBusy(false); }
  };

  return (
    <div>
      <div className="section-h" style={{ marginBottom: 16 }}>
        <div>
          <div className="t-eyebrow" style={{ marginBottom: 6 }}>Marsec level 1 · .doc</div>
          <h2 style={{ fontFamily: "var(--fs)", fontWeight: 400 }}>Gangway <em>Visitors.</em></h2>
        </div>
        <button className="btn btn-primary btn-sm" disabled={busy} onClick={generate}>{busy ? (isEN ? "Generating…" : "Gerando…") : "⤓ " + (isEN ? "Generate .doc" : "Gerar .doc")}</button>
      </div>

      <div className="card soft" style={{ marginBottom: 16 }}>
        <label className="label">{isEN ? "Who goes in the book" : "Quem entra no livro"}</label>
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
          <button className={scope === "guest" ? "btn btn-primary btn-sm" : "btn btn-sm"} onClick={() => setScope("guest")}>{isEN ? "Visitors only (guests)" : "Só visitantes (guests)"}</button>
          <button className={scope === "all" ? "btn btn-primary btn-sm" : "btn btn-sm"} onClick={() => setScope("all")}>{isEN ? "Everyone on board" : "Todos a bordo"}</button>
        </div>
        <p style={{ fontSize: 12, color: "var(--muted)", marginTop: 10 }}>
          {isEN ? "A4 landscape · 10 per page · min. 10 pages · Mandatory Check every 25 rows. Date/Time, Pass No. and signatures left blank to fill by hand." : "A4 paisagem · 10 por página · mín. 10 páginas · Mandatory Check a cada 25 linhas. Data/Hora, Nº do crachá e assinaturas em branco para preencher à mão."}
        </p>
      </div>

      <div className="t-eyebrow" style={{ marginBottom: 10, color: "var(--muted)" }}>{people.length} {isEN ? "names will be pre-filled" : "nomes serão pré-preenchidos"}</div>
      {people.length === 0 ? (
        <div className="empty" style={{ padding: "40px 20px" }}>{scope === "guest" ? (isEN ? "No visitors (guests) on board — the book still generates blank." : "Nenhum visitante (guest) a bordo — o livro ainda gera em branco.") : (isEN ? "No one on board." : "Ninguém a bordo.")}</div>
      ) : (
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))", gap: 8 }}>
          {people.map((p, i) => (
            <div key={i} style={{ padding: "8px 12px", background: "var(--surface)", border: "1px solid var(--line-soft)", borderRadius: 12, fontSize: 12.5 }}>
              <div style={{ fontWeight: 500 }}>{p.name}</div>
              <div style={{ fontSize: 11, color: "var(--muted)" }}>{p.company || "—"}</div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

/* ════════════════════════════════════════════════════════════════════════
   DMS — Declaração Marítima de Saúde (Anexo III)
   Formulário preenchido pelo Comandante. Persiste em /api/dms (tabela dms_form).
   ════════════════════════════════════════════════════════════════════════ */
const DMS_DEFAULTS = () => ({
  deliveredAt: "Porto do Açu", deliveryDate: mdToday(),
  shipName: "Genesis I", imo: "9246114", flag: "Marshall Islands",
  masterName: "Radoslaw PRZEPIORKOWSKI", signer: "radek",
  fromPort: "Bacia de Campos/RJ", toPort: "Porto do Açu",
  gt: "5886", nt: "1765",
  sanitationValid: true, sanitationValidUntil: "2026-08-28",
  sanitationIssuedAt: "Porto do Açu/RJ", sanitationIssuedDate: "2026-03-03",
  reinspectionRequired: false,
  visitedAffectedArea: false, affectedAreaDetail: "",
  portsList: "Sem portos nos últimos 30 dias.",
  q1Deaths: false, q1DeathsCount: "",
  q2InfectiousCase: false,
  q3MoreIll: false, q3IllCount: "",
  q4IllNow: false, q5MedicConsulted: false, q6Conditions: false,
  q7SanitaryMeasure: false, q7Detail: "",
  q8Stowaways: false, q8Where: "",
  q9SickAnimal: false,
  signDate: mdToday(),
  medics: [],
});
const DMS_MASTERS = { radek: "Radoslaw PRZEPIORKOWSKI", ludovik: "LUDOVIC FRANCIS FRANCOIS CERAK" };
const dmsEmptyMedic = () => ({ name: "", classRating: "", age: "", sex: "", nationality: "", joinPort: "", illness: "", onsetDate: "", reported: "", disposal: "", drugs: "", comments: "" });
const DMS_INP = { width: "100%", boxSizing: "border-box", minWidth: 0 };

// ── helpers em escopo de módulo (NÃO recriar a cada render → evita perda de foco) ──
const DmsSection = ({ title, children }) => (
  <div className="card" style={{ marginBottom: 16 }}>
    <h3 style={{ fontFamily: "var(--fs)", fontSize: 18, fontWeight: 500, letterSpacing: "-0.3px", color: "var(--accent)", marginBottom: 14 }}>{title}</h3>
    {children}
  </div>
);
const DmsField = ({ label, value, onChange, type, ta, ph, max }) => (
  <div style={{ minWidth: 0, maxWidth: max }}>
    <label className="label">{label}</label>
    {ta
      ? <textarea className="input" rows={2} style={DMS_INP} value={value || ""} onChange={e => onChange(e.target.value)} placeholder={ph} />
      : <input className="input" type={type || "text"} style={DMS_INP} value={value || ""} onChange={e => onChange(e.target.value)} placeholder={ph} />}
  </div>
);
const DmsQRow = ({ n, q, toggle, children }) => (
  <div style={{ display: "flex", gap: 12, alignItems: "flex-start", justifyContent: "space-between", padding: "10px 0", borderTop: "1px solid var(--line-soft)", flexWrap: "wrap" }}>
    <div style={{ fontSize: 13, lineHeight: 1.45, flex: 1, minWidth: 200 }}><strong style={{ color: "var(--accent)" }}>({n})</strong> {q}{children}</div>
    {toggle}
  </div>
);

const DmsView = ({ abordo = [] }) => {
  const tt = useT();
  const isEN = tt.lang === "en";
  const toast = useToast();
  const isMobile = useMobile();

  const [dms, setDms] = useState(DMS_DEFAULTS());
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const hydrated = useRef(false);
  const saveTimer = useRef(null);

  // carrega do backend
  useEffect(() => {
    (async () => {
      try {
        const token = localStorage.getItem("genesis_token");
        const res = await fetch("/api/dms", { headers: { Authorization: `Bearer ${token}` } });
        if (res.ok) {
          const data = await res.json();
          if (data) setDms({ ...DMS_DEFAULTS(), ...data, medics: Array.isArray(data.medics) ? data.medics : [] });
        }
      } catch (e) { console.error(e); }
      finally { setLoading(false); setTimeout(() => { hydrated.current = true; }, 60); }
    })();
  }, []);

  // autosave (debounce 800ms)
  useEffect(() => {
    if (!hydrated.current) return;
    if (saveTimer.current) clearTimeout(saveTimer.current);
    saveTimer.current = setTimeout(async () => {
      setSaving(true);
      try {
        const token = localStorage.getItem("genesis_token");
        await fetch("/api/dms", { method: "PUT", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" }, body: JSON.stringify(dms) });
      } catch (e) { console.error(e); }
      finally { setSaving(false); }
    }, 800);
    return () => { if (saveTimer.current) clearTimeout(saveTimer.current); };
  }, [dms]);

  const set = (f, v) => setDms(s => ({ ...s, [f]: v }));
  const setSigner = (s) => setDms(d => ({ ...d, signer: s, masterName: DMS_MASTERS[s] || d.masterName }));
  const addMedic = () => setDms(d => ({ ...d, medics: [...(d.medics || []), dmsEmptyMedic()] }));
  const setMedic = (i, f, v) => setDms(d => { const m = (d.medics || []).slice(); m[i] = { ...m[i], [f]: v }; return { ...d, medics: m }; });
  const removeMedic = (i) => setDms(d => { const m = (d.medics || []).slice(); m.splice(i, 1); return { ...d, medics: m }; });
  const reset = () => { setDms(DMS_DEFAULTS()); toast.push({ icon: "check", title: isEN ? "DMS reset to defaults." : "DMS restaurado ao padrão." }); };

  const gridCols = isMobile ? "1fr" : "1fr 1fr";

  // toggle Sim/Não — retorna elementos com tipo estável (sem problema de remount)
  const yn = (field) => {
    const v = !!dms[field];
    return (
      <div style={{ display: "flex", gap: 6, flexShrink: 0 }}>
        <button className="btn btn-sm" onClick={() => set(field, true)} style={v ? { background: "var(--leaf)", color: "#fff", borderColor: "var(--leaf)" } : { color: "var(--muted)" }}>{v ? "●" : "○"} Sim/Yes</button>
        <button className="btn btn-sm" onClick={() => set(field, false)} style={!v ? { background: "var(--rose)", color: "#fff", borderColor: "var(--rose)" } : { color: "var(--muted)" }}>{!v ? "●" : "○"} Não/No</button>
      </div>
    );
  };

  /* ---- PDF oficial (Anexo III, 3 páginas) ---- */
  const exportPDF = () => {
    const A = window.ANVISA_ASSETS || {};
    const SIG = A.SIG || {};
    const d = dms;
    const sigImg = SIG[d.signer] || SIG.radek || "";
    const ynS = (v) => v ? "( x ) Sim/Yes ( ) Não/No" : "( ) Sim/Yes ( x ) Não/No";
    const ynPT = (v) => v ? "SIM" : "NÃO";
    const br = (iso) => mdBrDate(iso);

    const visible = Math.max(7, (d.medics || []).length);
    let medicRows = "";
    for (let i = 0; i < visible; i++) {
      const m = (d.medics || [])[i] || {};
      medicRows += `<tr><td>${mdEsc(m.name)}</td><td>${mdEsc(m.classRating)}</td><td>${mdEsc(m.age)}</td><td>${mdEsc(m.sex)}</td><td>${mdEsc(m.nationality)}</td><td>${mdEsc(m.joinPort)}</td><td>${mdEsc(m.illness)}</td><td>${mdEsc(m.onsetDate)}</td><td>${mdEsc(m.reported)}</td><td>${mdEsc(m.disposal)}</td><td>${mdEsc(m.drugs)}</td><td>${mdEsc(m.comments)}</td></tr>`;
    }

    const w = window.open("", "_blank");
    w.document.write(`<!DOCTYPE html><html><head><meta charset="UTF-8"><title>DMS — Genesis I</title>
<style>
  @page{size:A4 portrait;margin:10mm 12mm;}
  *{box-sizing:border-box;font-family:'Times New Roman',Times,serif;}
  body{color:#000;font-size:11px;}
  .pg{page-break-after:always;} .pg:last-child{page-break-after:auto;}
  .header{display:table;width:100%;margin-bottom:8px;}
  .header>div{display:table-cell;vertical-align:top;}
  .h-left{width:48%;} .h-left img.arms{height:48px;float:left;margin-right:8px;}
  .h-left .txt{font-size:10px;line-height:1.25;padding-top:4px;}
  .h-mid{width:8%;text-align:center;} .h-mid img{height:34px;margin-top:8px;}
  .h-right{width:44%;text-align:right;font-size:10px;line-height:1.3;padding-top:4px;}
  .h-right .anexo{font-size:11px;} .h-right .ttl{font-size:13px;font-weight:normal;margin-top:2px;} .h-right .sub{font-style:normal;margin-top:1px;}
  .cvbox{width:260px;border:1px solid #000;padding:8px 10px;margin:6px 0 8px auto;font-size:10px;text-align:center;line-height:1.6;}
  .intro{text-align:center;font-size:10px;margin:8px 0;line-height:1.4;}
  table.form{width:100%;border-collapse:collapse;}
  table.form td{border:1px solid #000;padding:6px 8px;font-size:10.5px;vertical-align:middle;}
  .qhead{text-align:center;font-size:12px;margin:6px 0 4px;line-height:1.2;} .qhead b{display:block;} .qhead i{font-weight:normal;display:block;}
  table.qst{width:100%;border-collapse:collapse;}
  table.qst td{border:1px solid #000;padding:6px 8px;font-size:10.5px;vertical-align:top;}
  .note{border:1px solid #000;padding:8px;font-size:10px;line-height:1.35;}
  .decl{border:1px solid #000;padding:8px;font-size:10px;line-height:1.4;border-top:none;}
  .decl .sigarea{position:relative;min-height:90px;margin-top:8px;}
  .decl .sigarea img.stamp{position:absolute;right:10px;top:-10px;max-height:96px;}
  table.med{width:100%;border-collapse:collapse;margin-top:6px;font-size:9px;}
  table.med th,table.med td{border:1px solid #000;padding:3px 4px;vertical-align:top;line-height:1.15;}
  table.med th{font-weight:normal;font-size:9px;}
  .anex-title{text-align:center;font-size:11px;margin:10px 0 4px;} .anex-title b{display:block;} .anex-title i{font-style:normal;display:block;}
</style></head><body>

  <div class="pg">
    <div class="header">
      <div class="h-left"><img class="arms" src="${A.DMS_ARMS || A.ARMS || ""}"><div class="txt">REPÚBLICA FEDERATIVA DO BRASIL<br>MINISTÉRIO DA SAÚDE<br>AGÊNCIA NACIONAL DE VIGILÂNCIA SANITÁRIA</div></div>
      <div class="h-mid"><img src="${A.DMS_ANVISA || A.ANVISA || ""}"></div>
      <div class="h-right"><div class="anexo">ANEXO III</div><div class="ttl">DECLARAÇÃO MARÍTIMA DE SAÚDE</div><div class="sub">Maritime Declarations of Health</div></div>
    </div>
    <div class="cvbox">CVPAF/_________ PP _________ Nº.<br>__________________________</div>
    <div class="intro">Para ser preenchida e entregue às autoridades pertinentes pelos comandantes das embarcações provenientes de portos estrangeiros.<br>To be completed and submitted to the competent authorities by the masters of ships arriving from foreign ports.</div>
    <table class="form">
      <tr><td style="width:65%">Entregue no porto de: ${mdEsc(d.deliveredAt)}</td><td>Data/ Date: ${br(d.deliveryDate)}</td></tr>
      <tr><td colspan="2">Nome da embarcação marítima: ${mdEsc(d.shipName)}</td></tr>
      <tr><td style="width:35%">Registro/No IMO: ${mdEsc(d.imo)}</td><td>Nacionalidade / Nationality: ${mdEsc(d.flag)}</td></tr>
      <tr><td colspan="2">Comandante da embarcação /Master's name: ${mdEsc(d.masterName)}</td></tr>
      <tr><td style="width:50%">Chegando de: ${mdEsc(d.fromPort)}</td><td>Indo para: ${mdEsc(d.toPort)}</td></tr>
      <tr><td>Tonelagem Bruta: ${mdEsc(d.gt)}</td><td>Tonelagem Liquida: ${mdEsc(d.nt)}</td></tr>
      <tr><td colspan="2">Certificado de Isenção de Controle/ Certificado de Controle Sanitário válido a bordo? Valid Sanitation Control Exemption/Control Certificate carried on board? ${ynS(d.sanitationValid)} VÁLIDO ATÉ: ${br(d.sanitationValidUntil)}</td></tr>
      <tr><td style="width:32%">Emitido em /Issued at: ${mdEsc(d.sanitationIssuedAt)}</td><td>Data Date: ${br(d.sanitationIssuedDate)} &nbsp;&nbsp; Exigência de reinspeção? Re-inspection required? ${ynS(d.reinspectionRequired)}</td></tr>
      <tr><td colspan="2">A embarcação esteve numa área afetada identificada pela Organização Mundial da Saúde? ${ynPT(d.visitedAffectedArea)}</td></tr>
      <tr><td colspan="2">Has ship/vessel visited an affected area identified by the World Health Organization?<br>${ynS(d.visitedAffectedArea)} Porto e data da visita à área afetada /Port and date of visit ${mdEsc(d.affectedAreaDetail)}</td></tr>
      <tr><td colspan="2">Lista de portos de escala a partir do início da viagem internacional ou nos últimos trinta dias, se este período for mais curto, com as datas de saída: /List ports of call from commencement of voyage with dates of departure, or within past thirty days, whichever is shorter: ${mdEsc(d.portsList)}</td></tr>
    </table>
  </div>

  <div class="pg">
    <div class="qhead"><b>QUESTÕES DE SAÚDE</b><i>Health questions</i></div>
    <table class="qst">
      <tr><td>(1) Houve a bordo algum óbito que não tenha sido causado por acidente? Has any person died on board during the voyage otherwise than as a result of accident?<br>${ynS(d.q1Deaths)}<br>*Se houve, coloque os detalhes na planilha anexa/*If yes, state particulars in attached schedule Número total de mortes /Total no. of deaths: ${mdEsc(d.q1DeathsCount)}</td></tr>
      <tr><td>(2) Há a bordo, ou houve durante a viagem internacional algum caso de doença com suspeita de ser infecciosa? Is there on board or has there been during the international voyage any case of disease which you suspect to be of an infectious nature?<br>${ynS(d.q2InfectiousCase)}<br>*Se houve, coloque os detalhes na planilha anexa./*If yes, state particulars in attached schedule.</td></tr>
      <tr><td>(3) O número total de passageiros doentes durante a viagem foi maior do que o normal/esperado? Has the total number of ill passengers during the voyage been greater than normal/expected?<br>${ynS(d.q3MoreIll)}<br>Quantos doentes? How many ill persons? ${mdEsc(d.q3IllCount)}</td></tr>
      <tr><td>(4) Há, no momento, alguma pessoa doente a bordo? Is there any ill person on board now? *Se sim, coloque os detalhes na planilha anexa. *If yes, state particulars in attached schedule. ${ynS(d.q4IllNow)}</td></tr>
      <tr><td>(5) Um médico foi consultado? Was a medical practitioner consulted?<br>${ynS(d.q5MedicConsulted)}<br>*Se sim, coloque os detalhes do tratamento ou orientação médica recebida na planilha anexa./*If yes, state particulars of medical treatment or advice provided in attached schedule.</td></tr>
      <tr><td>(6) Você tem conhecimento de alguma condição existente a bordo que possa levar a infecção ou disseminação de doenças? Are you aware of any condition on board which may lead to infection or spread of disease?<br>${ynS(d.q6Conditions)}<br>*Se sim, coloque os detalhes na planilha anexa./*If yes, state particulars in attached schedule.</td></tr>
      <tr><td>(7) Foi aplicada alguma medida sanitária a bordo (p.ex. quarentena, isolamento, desinfecção ou descontaminação)? Has any sanitary measure (e.g. quarantine, isolation, disinfection or decontamination) been applied on board?<br>${ynS(d.q7SanitaryMeasure)}<br>* Se sim, especificar o tipo, o lugar e a data./ * If yes, specify type, place and date: ${mdEsc(d.q7Detail)}</td></tr>
      <tr><td>(8) Algum clandestino foi encontrado a bordo? Have any stowaways been found on board?<br>${ynS(d.q8Stowaways)}<br>Se sim, onde eles embarcaram (se for conhecido)?* If yes, where did they join the ship (if known)? ${mdEsc(d.q8Where)}</td></tr>
      <tr><td>(9) Há algum animal doente a bordo? Is there a sick animal or pet on board?<br>${ynS(d.q9SickAnimal)}</td></tr>
    </table>
  </div>

  <div class="pg">
    <div class="note">
      Nota: Na falta de um médico, o comandante deve considerar os seguintes sintomas como base suficiente para suspeitar a presença de uma doença infecciosa:<br>
      (a) Febre, persistente por vários dias ou acompanhadas por:<br>
      &nbsp;&nbsp;(i) prostração; (ii) diminuição do nível de consciência; (iii) inflamação dos gânglios; (iv) icterícia; (v) tosse ou dispnéia; (vi) hemorragia não usual; ou (vii) paralisia.<br>
      (b) Com ou sem febre:<br>
      &nbsp;&nbsp;(i) qualquer erupção cutânea ou eritema agudo; (ii) vômitos intensos (não devido a náusea marítima); (iii) diarréia intensa; ou (iv) convulsões recorrentes.<br><br>
      Note: In the absence of a surgeon, the master should regard the following symptoms as grounds for suspecting the existence of a disease of an infectious nature: (a) Fever, persisting for several days or accompanied by (i) prostration; (ii) decreased consciousness; (iii) glandular swelling; (iv) jaundice; (v) cough or shortness of breath; (vi) unusual bleeding; or (vii) paralysis. (b) With or without fever: (i) any acute skin rash or eruption; (ii) severe vomiting (other than sea sickness); (iii) severe diarrhoea; or (iv) recurrent convulsions.
    </div>
    <div class="decl">
      Declaro que as informações e respostas às questões fornecidas na Declaração de Saúde (incluindo a planilha) são verdadeiras e corretas, segundo meu conhecimento e entendimento. /I hereby declare that the particulars and answers to the questions given in this Declaration of Health (including the schedule) are true and correct to the best of my knowledge and belief.
      <div class="sigarea">
        <div>Data/Date: &nbsp;&nbsp; <u>&nbsp;${br(d.signDate)}&nbsp;</u></div>
        <div style="margin-top:10px">Assinatura - Comandante/Signed - Máster: ____________________________________</div>
        <div style="margin-top:8px">Confirmação - Médico de bordo (se houver) /Countersigned - Ship's Surgeon (if carried): _____________________</div>
        ${sigImg ? `<img class="stamp" src="${sigImg}">` : ""}
      </div>
    </div>
    <div class="anex-title"><b>PLANILHA ANEXA AO MODELO DA DECLARAÇÃO MARÍTIMA DE SAÚDE</b><i>Attachment to Model of Maritime Declaration of Health</i></div>
    <table class="med">
      <thead><tr>
        <th>Nome<br>Name</th><th>Classe ou nível<br>Class or rating</th><th>Idade<br>Age</th><th>Sexo<br>Sex</th>
        <th>Nacionalidade<br>Nationality</th><th>Porto e data de embarque<br>Port, date joined ship</th>
        <th>Natureza da doença<br>Nature of illness</th><th>Data início dos sintomas<br>Date symptoms noted</th>
        <th>Notificado?<br>Reported?</th><th>Disposição do caso<br>Disposal of case</th>
        <th>Medicação/tratamento<br>Drugs / treatment</th><th>Comentários<br>Comments</th>
      </tr></thead>
      <tbody>${medicRows}</tbody>
    </table>
  </div>

  <script>window.onload=function(){setTimeout(function(){window.print();},400);}<\/script>
  </body></html>`);
    w.document.close();
  };

  /* ---- Excel (campos + casos médicos) ---- */
  const exportExcel = async () => {
    await mdEnsureXLSX();
    const X = window.XLSX;
    const wb = X.utils.book_new();
    const ynx = (v) => v ? "Sim" : "Não";
    const campos = [
      ["Entregue no porto de", dms.deliveredAt], ["Data", mdBrDate(dms.deliveryDate)],
      ["Embarcação", dms.shipName], ["IMO", dms.imo], ["Nacionalidade", dms.flag],
      ["Tonelagem Bruta (GT)", dms.gt], ["Tonelagem Líquida (NT)", dms.nt],
      ["Comandante", dms.masterName], ["Chegando de", dms.fromPort], ["Indo para", dms.toPort],
      ["Cert. sanitário válido", ynx(dms.sanitationValid)], ["Válido até", mdBrDate(dms.sanitationValidUntil)],
      ["Emitido em", dms.sanitationIssuedAt], ["Data emissão", mdBrDate(dms.sanitationIssuedDate)],
      ["Reinspeção exigida", ynx(dms.reinspectionRequired)],
      ["Esteve em área afetada (OMS)", ynx(dms.visitedAffectedArea)], ["Detalhe área afetada", dms.affectedAreaDetail],
      ["Portos de escala (30d)", dms.portsList],
      ["(1) Óbitos não acidentais", ynx(dms.q1Deaths)], ["Nº mortes", dms.q1DeathsCount],
      ["(2) Caso suspeito infeccioso", ynx(dms.q2InfectiousCase)],
      ["(3) Doentes acima do normal", ynx(dms.q3MoreIll)], ["Quantos doentes", dms.q3IllCount],
      ["(4) Doente a bordo agora", ynx(dms.q4IllNow)],
      ["(5) Médico consultado", ynx(dms.q5MedicConsulted)],
      ["(6) Condição que leve a infecção", ynx(dms.q6Conditions)],
      ["(7) Medida sanitária aplicada", ynx(dms.q7SanitaryMeasure)], ["Tipo/lugar/data", dms.q7Detail],
      ["(8) Clandestino encontrado", ynx(dms.q8Stowaways)], ["Onde embarcaram", dms.q8Where],
      ["(9) Animal doente", ynx(dms.q9SickAnimal)],
      ["Data da assinatura", mdBrDate(dms.signDate)], ["Comandante que assina", DMS_MASTERS[dms.signer] || dms.signer],
    ];
    const wsForm = X.utils.aoa_to_sheet([["Campo", "Valor"], ...campos]);
    wsForm["!cols"] = [{ wch: 36 }, { wch: 48 }];
    X.utils.book_append_sheet(wb, wsForm, "DMS");
    const medRows = (dms.medics || []).map(m => ({
      "Nome": m.name, "Classe/Rating": m.classRating, "Idade": m.age, "Sexo": m.sex, "Nacionalidade": m.nationality,
      "Porto/data emb.": m.joinPort, "Doença": m.illness, "Início sintomas": m.onsetDate, "Notificado?": m.reported,
      "Resolução": m.disposal, "Medicamentos": m.drugs, "Comentários": m.comments,
    }));
    const wsMed = X.utils.json_to_sheet(medRows.length ? medRows : [{ "Nome": "" }]);
    X.utils.book_append_sheet(wb, wsMed, "Casos médicos");
    X.writeFile(wb, `dms_genesis_${mdToday()}.xlsx`);
  };

  if (loading) return <div className="empty" style={{ padding: 50 }}>{isEN ? "loading…" : "carregando…"}</div>;

  return (
    <div>
      <div className="section-h" style={{ marginBottom: 16 }}>
        <div>
          <div className="t-eyebrow" style={{ marginBottom: 6 }}>{isEN ? "Maritime Declaration of Health · Annex III" : "Declaração Marítima de Saúde · Anexo III"}</div>
          <h2 style={{ fontFamily: "var(--fs)", fontSize: isMobile ? 24 : 30, letterSpacing: "-0.6px", lineHeight: 1.05, fontWeight: 400 }}>Declaração Marítima <em style={{ fontStyle: "italic", color: "var(--accent)" }}>de Saúde.</em></h2>
        </div>
        <div style={{ display: "flex", gap: 8, flexWrap: "wrap", alignItems: "center" }}>
          <span style={{ fontFamily: "var(--fm)", fontSize: 10.5, color: "var(--muted)" }}>{saving ? (isEN ? "saving…" : "salvando…") : (isEN ? "saved" : "salvo")}</span>
          <button className="btn-icone neutro sm" onClick={reset} title={isEN ? "reset to default" : "voltar ao padrão"}>↺</button>
          <button className="btn btn-sm" onClick={exportExcel}>📊 Excel</button>
          <button className="btn btn-primary btn-sm" onClick={exportPDF}>📄 PDF</button>
        </div>
      </div>
      <p style={{ fontSize: 12, color: "var(--muted)", marginBottom: 16 }}>
        {isEN ? "Fields save automatically. Default answers (\"Não/No\") match the normal case." : "Os campos são salvos automaticamente. As respostas padrão (\"Não/No\") correspondem ao caso normal."}
      </p>

      <DmsSection title={isEN ? "Voyage identification" : "Identificação da viagem"}>
        <div style={{ display: "grid", gridTemplateColumns: gridCols, gap: 12 }}>
          <DmsField label="Entregue no porto de" value={dms.deliveredAt} onChange={v => set("deliveredAt", v)} />
          <DmsField label="Data / Date" type="date" value={dms.deliveryDate} onChange={v => set("deliveryDate", v)} />
          <DmsField label="Chegando de" value={dms.fromPort} onChange={v => set("fromPort", v)} />
          <DmsField label="Indo para" value={dms.toPort} onChange={v => set("toPort", v)} />
        </div>
      </DmsSection>

      <DmsSection title={isEN ? "Vessel" : "Embarcação"}>
        <div style={{ display: "grid", gridTemplateColumns: gridCols, gap: 12 }}>
          <DmsField label="Nome da embarcação" value={dms.shipName} onChange={v => set("shipName", v)} />
          <DmsField label="Registro / IMO" value={dms.imo} onChange={v => set("imo", v)} />
          <DmsField label="Nacionalidade / Flag" value={dms.flag} onChange={v => set("flag", v)} />
          <DmsField label="Tonelagem Bruta (GT)" value={dms.gt} onChange={v => set("gt", v)} />
          <DmsField label="Tonelagem Líquida (NT)" value={dms.nt} onChange={v => set("nt", v)} />
          <DmsField label="Comandante / Master" value={dms.masterName} onChange={v => set("masterName", v)} />
        </div>
      </DmsSection>

      <DmsSection title={isEN ? "Sanitation certificate" : "Certificado Sanitário"}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, flexWrap: "wrap", marginBottom: 12 }}>
          <span style={{ fontSize: 13 }}>Certificado de Controle Sanitário válido a bordo?</span>{yn("sanitationValid")}
        </div>
        <div style={{ display: "grid", gridTemplateColumns: gridCols, gap: 12 }}>
          <DmsField label="Válido até" type="date" value={dms.sanitationValidUntil} onChange={v => set("sanitationValidUntil", v)} />
          <DmsField label="Emitido em / Issued at" value={dms.sanitationIssuedAt} onChange={v => set("sanitationIssuedAt", v)} />
          <DmsField label="Data de emissão" type="date" value={dms.sanitationIssuedDate} onChange={v => set("sanitationIssuedDate", v)} />
        </div>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, flexWrap: "wrap", marginTop: 12 }}>
          <span style={{ fontSize: 13 }}>Exigência de reinspeção?</span>{yn("reinspectionRequired")}
        </div>
      </DmsSection>

      <DmsSection title={isEN ? "Affected areas & ports of call" : "Áreas afetadas e portos de escala"}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, flexWrap: "wrap", marginBottom: 12 }}>
          <span style={{ fontSize: 13 }}>A embarcação esteve numa área afetada (OMS)?</span>{yn("visitedAffectedArea")}
        </div>
        {dms.visitedAffectedArea && <div style={{ marginBottom: 12 }}><DmsField label="Porto e data da visita" value={dms.affectedAreaDetail} onChange={v => set("affectedAreaDetail", v)} /></div>}
        <DmsField label="Lista de portos de escala (últimos 30 dias)" ta value={dms.portsList} onChange={v => set("portsList", v)} />
      </DmsSection>

      <DmsSection title={isEN ? "Health questions" : "Questões de Saúde"}>
        <DmsQRow n={1} q="Houve a bordo algum óbito que não tenha sido causado por acidente?" toggle={yn("q1Deaths")}>
          {dms.q1Deaths && <div style={{ marginTop: 8 }}><DmsField label="Nº total de mortes" value={dms.q1DeathsCount} onChange={v => set("q1DeathsCount", v)} max={220} /></div>}
        </DmsQRow>
        <DmsQRow n={2} q="Há a bordo, ou houve durante a viagem, algum caso de doença com suspeita de ser infecciosa?" toggle={yn("q2InfectiousCase")} />
        <DmsQRow n={3} q="O nº total de doentes durante a viagem foi maior do que o normal/esperado?" toggle={yn("q3MoreIll")}>
          {dms.q3MoreIll && <div style={{ marginTop: 8 }}><DmsField label="Quantos doentes" value={dms.q3IllCount} onChange={v => set("q3IllCount", v)} max={220} /></div>}
        </DmsQRow>
        <DmsQRow n={4} q="Há, no momento, alguma pessoa doente a bordo?" toggle={yn("q4IllNow")} />
        <DmsQRow n={5} q="Um médico foi consultado?" toggle={yn("q5MedicConsulted")} />
        <DmsQRow n={6} q="Você tem conhecimento de alguma condição existente a bordo que possa levar a infecção?" toggle={yn("q6Conditions")} />
        <DmsQRow n={7} q="Foi aplicada alguma medida sanitária a bordo?" toggle={yn("q7SanitaryMeasure")}>
          {dms.q7SanitaryMeasure && <div style={{ marginTop: 8 }}><DmsField label="Tipo, lugar e data" value={dms.q7Detail} onChange={v => set("q7Detail", v)} /></div>}
        </DmsQRow>
        <DmsQRow n={8} q="Algum clandestino foi encontrado a bordo?" toggle={yn("q8Stowaways")}>
          {dms.q8Stowaways && <div style={{ marginTop: 8 }}><DmsField label="Onde embarcaram" value={dms.q8Where} onChange={v => set("q8Where", v)} /></div>}
        </DmsQRow>
        <DmsQRow n={9} q="Há algum animal doente a bordo?" toggle={yn("q9SickAnimal")} />
      </DmsSection>

      <DmsSection title={isEN ? "Attached schedule — medical cases" : "Planilha anexa — casos médicos"}>
        <div style={{ marginBottom: 12 }}>
          <button className="btn-tidal-sec" onClick={addMedic}>＋ {isEN ? "Case" : "Caso"}</button>
        </div>
        {!(dms.medics || []).length ? (
          <div className="empty" style={{ padding: "24px 12px" }}>{isEN ? "No cases — the schedule prints blank (default)." : "Sem casos — a planilha sai em branco (padrão)."}</div>
        ) : (dms.medics || []).map((m, i) => (
          <div key={i} className="card sunk" style={{ marginBottom: 10, padding: 12 }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }}>
              <span style={{ fontFamily: "var(--fm)", fontSize: 11, color: "var(--muted)" }}>{isEN ? "Case" : "Caso"} {i + 1}</span>
              <button className="btn ghost btn-sm" onClick={() => removeMedic(i)}>✕</button>
            </div>
            <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr 1fr" : "repeat(4, 1fr)", gap: 8 }}>
              {[["name", "Nome"], ["classRating", "Classe/Rating"], ["age", "Idade"], ["sex", "Sexo"], ["nationality", "Nacionalidade"], ["joinPort", "Porto/data emb."], ["illness", "Doença"], ["onsetDate", "Início sintomas"], ["reported", "Notificado?"], ["disposal", "Resolução"], ["drugs", "Medicamentos"], ["comments", "Comentários"]].map(([f, lb]) => (
                <div key={f} style={{ minWidth: 0 }}>
                  <label className="label" style={{ fontSize: 9 }}>{lb}</label>
                  <input className="input" style={{ ...DMS_INP, padding: "5px 7px", fontSize: 11 }} value={m[f] || ""} onChange={e => setMedic(i, f, e.target.value)} />
                </div>
              ))}
            </div>
          </div>
        ))}
      </DmsSection>

      <DmsSection title={isEN ? "Signature" : "Assinatura"}>
        <div style={{ display: "grid", gridTemplateColumns: gridCols, gap: 12, marginBottom: 12 }}>
          <DmsField label="Data da assinatura" type="date" value={dms.signDate} onChange={v => set("signDate", v)} />
          <div style={{ minWidth: 0 }}>
            <label className="label">Comandante que assina</label>
            <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
              {["radek", "ludovik"].map(s => (
                <button key={s} className={dms.signer === s ? "btn btn-primary btn-sm" : "btn btn-sm"} onClick={() => setSigner(s)}>{DMS_MASTERS[s]}</button>
              ))}
            </div>
          </div>
        </div>
        {(window.ANVISA_ASSETS && window.ANVISA_ASSETS.SIG && window.ANVISA_ASSETS.SIG[dms.signer]) && (
          <div style={{ display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
            <span style={{ fontSize: 11, color: "var(--muted)" }}>{isEN ? "Signature preview:" : "Pré-visualização:"}</span>
            <img src={window.ANVISA_ASSETS.SIG[dms.signer]} style={{ maxHeight: 64, background: "#fff", padding: 4, border: "1px solid var(--line-soft)", borderRadius: 6 }} alt="" />
          </div>
        )}
      </DmsSection>
    </div>
  );
};

Object.assign(window, { CrewListAnvisa, GangwayRecordBook, DmsView, MdModal });
