{"id":12,"date":"2026-08-13T16:03:57","date_gmt":"2026-08-13T16:03:57","guid":{"rendered":"https:\/\/d7dsgn.com.br\/?page_id=12"},"modified":"2026-08-13T18:33:09","modified_gmt":"2026-08-13T18:33:09","slug":"admercearia","status":"publish","type":"page","link":"https:\/\/d7dsgn.com.br\/admercearia\/","title":{"rendered":"Sistema de Estoque AD Mercearia"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"12\" class=\"elementor elementor-12\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-94298bc e-flex e-con-boxed e-con e-parent\" data-id=\"94298bc\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-7f35054 elementor-widget elementor-widget-html\" data-id=\"7f35054\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"pt-BR\">\r\n<head>\r\n<meta charset=\"UTF-8\">\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\r\n<title>AD Mercearia \u00b7 Cadastro de Produtos<\/title>\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Zilla+Slab:wght@500;600;700&family=Work+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@500;600&display=swap\" rel=\"stylesheet\">\r\n<style>\r\n  :root{\r\n    --verde-avental:#141414;      \/* preto - cor principal *\/\r\n    --verde-claro:#C1440E;        \/* laranja escuro - texto\/r\u00f3tulos secund\u00e1rios *\/\r\n    --verde-suave:#FFF0E4;        \/* laranja bem claro - fundo das etiquetas *\/\r\n    --creme:#FFFFFF;\r\n    --creme-alt:#F4F4F4;\r\n    --mostarda:#E8590C;           \/* laranja principal - CTA *\/\r\n    --mostarda-escuro:#B8430A;    \/* laranja escuro - hover\/sombra de bot\u00e3o *\/\r\n    --vermelho:#141414;           \/* preto no lugar de vermelho (paleta restrita) *\/\r\n    --tinta:#141414;\r\n    --tinta-suave:#5C5C5C;\r\n    --linha:#E2E2E2;\r\n    --branco:#FFFFFF;\r\n    --sombra: 0 2px 0 rgba(0,0,0,0.05), 0 6px 16px rgba(0,0,0,0.08);\r\n  }\r\n  *{box-sizing:border-box;}\r\n  html,body{margin:0;padding:0;}\r\n  body{\r\n    background:var(--creme);\r\n    color:var(--tinta);\r\n    font-family:'Work Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\r\n    -webkit-font-smoothing:antialiased;\r\n    min-height:100vh;\r\n    background-image:\r\n      radial-gradient(rgba(20,20,20,0.035) 1px, transparent 1px);\r\n    background-size: 18px 18px;\r\n  }\r\n  h1,h2,h3{ font-family:'Zilla Slab', Georgia, serif; margin:0; }\r\n  .mono{ font-family:'IBM Plex Mono', 'Courier New', monospace; font-variant-numeric: tabular-nums; }\r\n\r\n  \/* ---------- topo ---------- *\/\r\n  header{\r\n    position:sticky; top:0; z-index:20;\r\n    background:var(--verde-avental);\r\n    color:var(--creme);\r\n    padding:14px 18px;\r\n    box-shadow: 0 4px 14px rgba(0,0,0,0.18);\r\n  }\r\n  .header-inner{\r\n    max-width:980px; margin:0 auto;\r\n    display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap;\r\n  }\r\n  .brand{ display:flex; align-items:center; gap:10px; }\r\n  .brand-badge{\r\n    width:42px; height:42px; border-radius:50%;\r\n    background:var(--mostarda); color:#FFFFFF;\r\n    display:flex; align-items:center; justify-content:center;\r\n    font-family:'Zilla Slab',serif; font-weight:700; font-size:15px; letter-spacing:.3px;\r\n    box-shadow: inset 0 0 0 2px rgba(0,0,0,0.15);\r\n  }\r\n  .brand h1{ font-size:19px; font-weight:600; letter-spacing:.2px; }\r\n  .brand span{ display:block; font-size:11.5px; color:#BFBFBF; font-weight:400; font-family:'Work Sans',sans-serif; }\r\n\r\n  nav.tabs{ display:flex; gap:6px; background:rgba(255,255,255,0.08); padding:4px; border-radius:12px; }\r\n  nav.tabs button{\r\n    appearance:none; border:none; background:transparent; color:#D6D6D6;\r\n    padding:10px 16px; border-radius:9px; font-size:14.5px; font-weight:600;\r\n    font-family:'Work Sans',sans-serif; cursor:pointer; transition:.15s;\r\n    white-space:nowrap;\r\n  }\r\n  nav.tabs button.active{ background:var(--mostarda); color:var(--verde-avental); }\r\n  nav.tabs button:not(.active):hover{ background:rgba(255,255,255,0.12); }\r\n\r\n  main{ max-width:980px; margin:0 auto; padding:22px 16px 90px; }\r\n  .view{ display:none; animation:fade .25s ease; }\r\n  .view.active{ display:block; }\r\n  @keyframes fade{ from{opacity:0; transform:translateY(4px);} to{opacity:1; transform:none;} }\r\n\r\n  .panel-title{ margin-bottom:4px; font-size:23px; color:var(--verde-avental); }\r\n  .panel-sub{ color:var(--tinta-suave); font-size:14px; margin:4px 0 20px; max-width:560px; line-height:1.5; }\r\n\r\n  \/* ---------- banner de edi\u00e7\u00e3o ---------- *\/\r\n  .edit-banner{\r\n    display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;\r\n    background:var(--verde-avental); color:#FFFFFF; padding:12px 16px; border-radius:12px;\r\n    margin-bottom:16px; font-size:14px; border-left:5px solid var(--mostarda);\r\n  }\r\n  .edit-banner strong{ color:var(--mostarda); }\r\n  .btn-on-dark{ background:transparent; color:#FFFFFF; border:1.5px solid #FFFFFF; padding:8px 13px; font-size:13px; }\r\n  .btn-on-dark:hover{ background:#FFFFFF; color:var(--verde-avental); }\r\n  .form-actions{ margin-top:20px; }\r\n\r\n  \/* ---------- cart\u00e3o \/ formul\u00e1rio ---------- *\/\r\n  .card{\r\n    background:var(--branco); border:1px solid var(--linha); border-radius:16px;\r\n    padding:20px; box-shadow:var(--sombra);\r\n  }\r\n  .grid2{ display:grid; grid-template-columns:1fr 1fr; gap:14px; }\r\n  @media (max-width:620px){ .grid2{ grid-template-columns:1fr; } }\r\n\r\n  .field{ margin-bottom:14px; }\r\n  .field label{\r\n    display:flex; align-items:center; gap:6px;\r\n    font-size:13px; font-weight:600; color:var(--verde-avental); margin-bottom:6px;\r\n  }\r\n  .field label .req{ color:var(--vermelho); font-weight:700; }\r\n  .field input{\r\n    width:100%; padding:13px 14px; border-radius:10px; border:1.5px solid var(--linha);\r\n    background:var(--creme-alt); font-size:16px; font-family:'IBM Plex Mono',monospace;\r\n    color:var(--tinta); transition:.15s;\r\n  }\r\n  .field input[type=\"text\"]{ font-family:'Work Sans',sans-serif; }\r\n  .field input:focus{ outline:none; border-color:var(--mostarda-escuro); background:var(--branco); box-shadow:0 0 0 3px rgba(228,167,48,0.25); }\r\n  .field .hint{ font-size:11.5px; color:#8A836F; margin-top:5px; }\r\n\r\n  .divider{ display:flex; align-items:center; gap:10px; margin:22px 0 14px; color:var(--tinta-suave); font-size:12.5px; font-weight:600; text-transform:uppercase; letter-spacing:.6px; }\r\n  .divider::before,.divider::after{ content:\"\"; flex:1; height:1px; background:var(--linha); }\r\n\r\n  \/* etiquetas de pr\u00e9-visualiza\u00e7\u00e3o *\/\r\n  .tags-wrap{ display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:12px; margin-top:6px; }\r\n  .tag{\r\n    position:relative; background:var(--verde-suave); border:1.5px dashed var(--verde-claro);\r\n    border-radius:10px 4px 4px 10px; padding:12px 12px 12px 22px; min-height:64px;\r\n  }\r\n  .tag::before{\r\n    content:\"\"; position:absolute; left:8px; top:50%; transform:translateY(-50%);\r\n    width:7px; height:7px; border-radius:50%; background:var(--creme); border:1.5px solid var(--verde-claro);\r\n  }\r\n  .tag .t-label{ font-size:11px; font-weight:600; color:var(--verde-claro); text-transform:uppercase; letter-spacing:.4px; }\r\n  .tag .t-value{ font-size:18px; font-weight:600; color:var(--verde-avental); margin-top:3px; }\r\n  .tag.empty .t-value{ color:#BDBDBD; font-weight:500; }\r\n  .tag.auto::after{\r\n    content:\"auto\"; position:absolute; right:8px; top:8px; font-size:9px; font-weight:700;\r\n    color:#FFFFFF; background:var(--mostarda); padding:2px 6px; border-radius:20px;\r\n  }\r\n\r\n  .msg{ margin-top:14px; padding:12px 14px; border-radius:10px; font-size:13.5px; font-weight:500; display:none; }\r\n  .msg.show{ display:block; }\r\n  .msg.error{ background:#141414; color:#FFFFFF; border:1px solid #141414; }\r\n  .msg.success{ background:var(--verde-suave); color:#141414; border:1px solid var(--mostarda); }\r\n\r\n  .btn{\r\n    appearance:none; border:none; cursor:pointer; font-family:'Work Sans',sans-serif;\r\n    font-weight:700; font-size:15.5px; border-radius:12px; padding:15px 22px;\r\n    transition:.15s; display:inline-flex; align-items:center; justify-content:center; gap:8px;\r\n  }\r\n  .btn-primary{ background:var(--mostarda); color:var(--verde-avental); width:100%; box-shadow:0 3px 0 var(--mostarda-escuro); }\r\n  .btn-primary:active{ transform:translateY(2px); box-shadow:0 1px 0 var(--mostarda-escuro); }\r\n  .btn-ghost{ background:transparent; color:var(--verde-avental); border:1.5px solid var(--verde-avental); padding:9px 14px; font-size:13.5px; }\r\n  .btn-danger{ background:transparent; color:#141414; border:1.5px solid #BDBDBD; padding:8px 12px; font-size:13px; }\r\n  .btn-danger:hover{ background:#141414; color:#FFFFFF; border-color:#141414; }\r\n  .btn-small{ padding:9px 13px; font-size:13px; }\r\n\r\n  \/* ---------- lista de produtos ---------- *\/\r\n  .toolbar{ display:flex; gap:10px; margin-bottom:16px; flex-wrap:wrap; align-items:center; justify-content:space-between; }\r\n  .search{\r\n    flex:1; min-width:200px; padding:12px 14px; border-radius:10px; border:1.5px solid var(--linha);\r\n    background:var(--branco); font-size:14.5px; font-family:'Work Sans',sans-serif;\r\n  }\r\n  .search:focus{ outline:none; border-color:var(--mostarda-escuro); }\r\n  .actions-mini{ display:flex; gap:8px; }\r\n\r\n  .prod-list{ display:flex; flex-direction:column; gap:12px; }\r\n  .prod-card{\r\n    background:var(--branco); border:1px solid var(--linha); border-radius:14px;\r\n    padding:16px 18px; box-shadow:var(--sombra); position:relative; overflow:hidden;\r\n  }\r\n  .prod-card::before{ content:\"\"; position:absolute; left:0; top:0; bottom:0; width:6px; background:var(--mostarda); }\r\n  .prod-head{ display:flex; justify-content:space-between; align-items:flex-start; gap:10px; margin-bottom:10px; padding-left:8px; }\r\n  .prod-actions{ display:flex; gap:8px; flex-shrink:0; }\r\n  .prod-head h3{ font-size:17px; color:var(--verde-avental); }\r\n  .prod-grid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); gap:10px 16px; padding-left:8px; }\r\n  .prod-item .k{ font-size:10.5px; text-transform:uppercase; letter-spacing:.4px; color:#8C8C8C; font-weight:600; }\r\n  .prod-item .v{ font-size:15.5px; font-weight:600; color:var(--tinta); margin-top:2px; }\r\n  .prod-item.lucro .v{ color:var(--mostarda); }\r\n  .prod-item.destaque-item .v{ color:var(--verde-avental); font-weight:700; }\r\n\r\n  \/* ---------- painel de estoque \/ compra ---------- *\/\r\n  .estoque-panel{\r\n    display:grid; grid-template-columns:1fr 1fr; gap:12px; margin:14px 8px 2px;\r\n    padding-top:14px; border-top:1px dashed var(--linha);\r\n  }\r\n  @media (max-width:520px){ .estoque-panel{ grid-template-columns:1fr; } }\r\n  .estoque-box{ background:var(--verde-suave); border-radius:10px; padding:10px 12px; }\r\n  .estoque-box label{ display:block; font-size:11.5px; font-weight:700; color:var(--verde-avental); margin-bottom:6px; }\r\n  .estoque-box label .hint-inline{ font-weight:400; color:var(--tinta-suave); font-size:10.5px; }\r\n  .estoque-controls{ display:flex; gap:8px; }\r\n  .estoque-controls input{\r\n    flex:1 1 auto; min-width:56px; padding:9px 10px; border-radius:8px; border:1.5px solid var(--linha);\r\n    background:#FFFFFF; font-family:'IBM Plex Mono',monospace; font-size:14.5px; color:var(--tinta);\r\n  }\r\n  .estoque-controls input:focus{ outline:none; border-color:var(--mostarda-escuro); box-shadow:0 0 0 3px rgba(232,89,12,0.18); }\r\n  .estoque-controls .btn{ flex:0 0 auto; width:auto; white-space:nowrap; }\r\n  .btn-compra{ background:var(--mostarda); color:#FFFFFF; box-shadow:0 3px 0 var(--mostarda-escuro); }\r\n  .btn-compra:active{ transform:translateY(2px); box-shadow:0 1px 0 var(--mostarda-escuro); }\r\n  .estoque-box .hint{ margin-top:6px; font-size:10.5px; color:#8C8C8C; }\r\n\r\n  \/* ---------- toast ---------- *\/\r\n  .toast{\r\n    position:fixed; left:50%; bottom:24px; transform:translateX(-50%) translateY(16px);\r\n    background:#141414; color:#FFFFFF; padding:12px 20px; border-radius:10px;\r\n    font-size:14px; font-weight:600; box-shadow:0 10px 24px rgba(0,0,0,0.28);\r\n    border-left:4px solid var(--mostarda); opacity:0; pointer-events:none; transition:.25s ease; z-index:60;\r\n    max-width:90vw; text-align:center;\r\n  }\r\n  .toast.show{ opacity:1; transform:translateX(-50%) translateY(0); }\r\n\r\n  .empty-state{ text-align:center; padding:60px 20px; color:var(--tinta-suave); }\r\n  .empty-state .ic{ font-size:38px; margin-bottom:10px; }\r\n  .empty-state h3{ color:var(--verde-avental); font-size:18px; margin-bottom:6px; }\r\n  .empty-state p{ font-size:13.5px; max-width:320px; margin:0 auto; line-height:1.5; }\r\n\r\n  \/* ---------- resumo ---------- *\/\r\n  .stats-grid{ display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:14px; }\r\n  .stat-card{\r\n    background:var(--branco); border:1px solid var(--linha); border-radius:14px;\r\n    padding:18px; box-shadow:var(--sombra);\r\n  }\r\n  .stat-card .k{ font-size:12px; font-weight:600; color:var(--verde-claro); text-transform:uppercase; letter-spacing:.4px; }\r\n  .stat-card .v{ font-size:24px; font-weight:700; color:var(--verde-avental); margin-top:6px; }\r\n  .stat-card .v.small{ font-size:16px; }\r\n  .stat-card.destaque{ background:var(--verde-avental); border-color:var(--verde-avental); }\r\n  .stat-card.destaque .k{ color:var(--mostarda); }\r\n  .stat-card.destaque .v{ color:var(--creme); }\r\n\r\n  .backup-row{ display:flex; gap:10px; margin-top:22px; flex-wrap:wrap; }\r\n  footer{ text-align:center; color:#A0A0A0; font-size:12px; padding:24px 0 10px; }\r\n\r\n  \/* ---------- login \/ autentica\u00e7\u00e3o ---------- *\/\r\n  #app-shell{ display:none; }\r\n  #auth-overlay{\r\n    position:fixed; inset:0; z-index:100; background:var(--verde-avental);\r\n    display:flex; align-items:center; justify-content:center; padding:20px;\r\n    background-image: radial-gradient(rgba(255,255,255,0.04) 1px, transparent 1px);\r\n    background-size: 18px 18px;\r\n  }\r\n  .auth-card{\r\n    background:#FFFFFF; border-radius:18px; width:100%; max-width:380px;\r\n    padding:32px 28px; box-shadow:0 20px 50px rgba(0,0,0,0.35);\r\n  }\r\n  .auth-badge{\r\n    width:56px; height:56px; border-radius:50%; background:var(--mostarda); color:#fff;\r\n    display:flex; align-items:center; justify-content:center; font-family:'Zilla Slab',serif;\r\n    font-weight:700; font-size:19px; margin:0 auto 14px;\r\n  }\r\n  .auth-card h2{ text-align:center; font-size:20px; color:#141414; margin-bottom:4px; }\r\n  .auth-sub{ text-align:center; font-size:13px; color:#6B6B6B; margin-bottom:22px; }\r\n  .auth-field{ margin-bottom:14px; }\r\n  .auth-field label{ display:block; font-size:12.5px; font-weight:700; color:#141414; margin-bottom:6px; }\r\n  .auth-field input{\r\n    width:100%; padding:13px 14px; border-radius:10px; border:1.5px solid var(--linha);\r\n    background:var(--creme-alt); font-size:15.5px; font-family:'Work Sans',sans-serif; color:#141414;\r\n  }\r\n  .auth-field input:focus{ outline:none; border-color:var(--mostarda); background:#fff; box-shadow:0 0 0 3px rgba(232,89,12,0.18); }\r\n  .auth-check{ display:flex; align-items:center; gap:8px; font-size:13px; color:#5C5C5C; margin:2px 0 18px; }\r\n  .auth-check input{ width:16px; height:16px; accent-color:var(--mostarda); }\r\n  .auth-msg{ font-size:13px; color:var(--mostarda-escuro); background:#FFF0E4; border:1px solid var(--mostarda); border-radius:8px; padding:9px 12px; margin-bottom:14px; display:none; }\r\n  .auth-msg.show{ display:block; }\r\n  .auth-switch{ text-align:center; margin-top:16px; font-size:12.5px; color:#6B6B6B; }\r\n  .auth-switch a{ color:var(--mostarda-escuro); font-weight:700; cursor:pointer; text-decoration:underline; }\r\n  .auth-view{ display:none; }\r\n  .auth-view.active{ display:block; }\r\n  .btn-on-dark-alt{\r\n    width:100%; margin-top:10px; background:#FFFFFF; color:#141414;\r\n    border:1.5px solid #141414; padding:13px 22px;\r\n  }\r\n  .btn-on-dark-alt:hover{ background:#141414; color:#FFFFFF; }\r\n\r\n  .btn-logout{\r\n    background:transparent; border:1.5px solid rgba(255,255,255,0.5); color:#EDEDED;\r\n    padding:8px 12px; font-size:12.5px; border-radius:9px;\r\n  }\r\n  .btn-logout:hover{ background:rgba(255,255,255,0.12); }\r\n\r\n  \/* ---------- \u00e1rea de impress\u00e3o ---------- *\/\r\n  #print-area{ display:none; }\r\n  @media print{\r\n    body{ background:#FFFFFF; }\r\n    body *{ visibility:hidden; }\r\n    #print-area, #print-area *{ visibility:visible; }\r\n    #print-area{\r\n      display:block; position:absolute; left:0; top:0; width:100%; padding:14px 20px; color:#000;\r\n    }\r\n    .print-head{ display:flex; align-items:baseline; justify-content:space-between; border-bottom:3px solid #000; padding-bottom:10px; margin-bottom:6px; }\r\n    .print-head h1{ font-family:'Zilla Slab',Georgia,serif; font-size:22px; color:#000; }\r\n    .print-head .brand-ad{ color:var(--mostarda); }\r\n    .print-head .data{ font-size:12px; color:#333; }\r\n    #print-area table{ width:100%; border-collapse:collapse; margin-top:10px; }\r\n    #print-area th{\r\n      text-align:left; font-size:10.5px; text-transform:uppercase; letter-spacing:.3px;\r\n      background:#141414; color:#fff; padding:7px 8px; border:1px solid #141414;\r\n    }\r\n    #print-area td{ font-size:12px; padding:6px 8px; border:1px solid #ccc; font-family:'IBM Plex Mono',monospace; }\r\n    #print-area td.nome-col{ font-family:'Work Sans',sans-serif; font-weight:600; }\r\n    #print-area tfoot td{ font-weight:700; border-top:2px solid #000; font-family:'Work Sans',sans-serif; }\r\n    #print-area .print-foot{ margin-top:16px; font-size:10.5px; color:#555; }\r\n  }\r\n<\/style>\r\n<\/head>\r\n<body>\r\n\r\n<!-- ===================== LOGIN \/ CRIA\u00c7\u00c3O DE CONTA ===================== -->\r\n<div id=\"auth-overlay\">\r\n  <div class=\"auth-card\">\r\n    <div class=\"auth-badge\">AD<\/div>\r\n\r\n    <!-- login -->\r\n    <div class=\"auth-view active\" id=\"auth-login\">\r\n      <h2>AD Mercearia<\/h2>\r\n      <p class=\"auth-sub\">Digite seu usu\u00e1rio e senha para continuar.<\/p>\r\n      <div class=\"auth-msg\" id=\"login-msg\"><\/div>\r\n      <div class=\"auth-field\">\r\n        <label>Usu\u00e1rio<\/label>\r\n        <input type=\"text\" id=\"login-user\" autocomplete=\"username\" placeholder=\"Seu usu\u00e1rio\">\r\n      <\/div>\r\n      <div class=\"auth-field\">\r\n        <label>Senha<\/label>\r\n        <input type=\"password\" id=\"login-pass\" autocomplete=\"current-password\" placeholder=\"Sua senha\">\r\n      <\/div>\r\n      <label class=\"auth-check\"><input type=\"checkbox\" id=\"login-remember\" checked> Manter conectado neste dispositivo<\/label>\r\n      <button class=\"btn btn-primary\" id=\"btn-login\">\u2713 Entrar<\/button>\r\n      <button class=\"btn btn-on-dark-alt\" id=\"link-goto-setup\">\uff0b Criar conta<\/button>\r\n      <div class=\"auth-switch\">Esqueceu a senha? <a id=\"link-forgot\" target=\"_blank\" rel=\"noopener\">Redefinir no WordPress<\/a><\/div>\r\n    <\/div>\r\n\r\n    <!-- cria\u00e7\u00e3o de usu\u00e1rio -->\r\n    <div class=\"auth-view\" id=\"auth-setup\">\r\n      <h2>Criar conta<\/h2>\r\n      <p class=\"auth-sub\">Escolha um usu\u00e1rio e senha para acessar o sistema.<\/p>\r\n      <div class=\"auth-msg\" id=\"setup-msg\"><\/div>\r\n      <div class=\"auth-field\">\r\n        <label>Usu\u00e1rio<\/label>\r\n        <input type=\"text\" id=\"setup-user\" autocomplete=\"off\" placeholder=\"Ex.: joao\">\r\n      <\/div>\r\n      <div class=\"auth-field\">\r\n        <label>E-mail<\/label>\r\n        <input type=\"email\" id=\"setup-email\" autocomplete=\"off\" placeholder=\"seu@email.com\">\r\n      <\/div>\r\n      <div class=\"auth-field\">\r\n        <label>Senha<\/label>\r\n        <input type=\"password\" id=\"setup-pass\" placeholder=\"M\u00ednimo 4 caracteres\">\r\n      <\/div>\r\n      <div class=\"auth-field\">\r\n        <label>Confirmar senha<\/label>\r\n        <input type=\"password\" id=\"setup-pass2\" placeholder=\"Repita a senha\">\r\n      <\/div>\r\n      <button class=\"btn btn-primary\" id=\"btn-setup\">\u2713 Criar e Entrar<\/button>\r\n      <div class=\"auth-switch\">J\u00e1 tem conta? <a id=\"link-goto-login\">Fazer login<\/a><\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<div id=\"app-shell\">\r\n<header>\r\n  <div class=\"header-inner\">\r\n    <div class=\"brand\">\r\n      <div class=\"brand-badge\">AD<\/div>\r\n      <div>\r\n        <h1>AD Mercearia<\/h1>\r\n        <span>Cadastro de produtos<\/span>\r\n      <\/div>\r\n    <\/div>\r\n    <nav class=\"tabs\">\r\n      <button class=\"tab-btn active\" data-view=\"cadastro\">Cadastro<\/button>\r\n      <button class=\"tab-btn\" data-view=\"produtos\">Produtos<\/button>\r\n      <button class=\"tab-btn\" data-view=\"resumo\">Resumo<\/button>\r\n    <\/nav>\r\n    <button class=\"btn btn-logout\" id=\"btn-logout\">Sair<\/button>\r\n  <\/div>\r\n<\/header>\r\n\r\n<main>\r\n\r\n  <!-- ===================== CADASTRO ===================== -->\r\n  <section id=\"view-cadastro\" class=\"view active\">\r\n    <h2 class=\"panel-title\">Cadastrar novo produto<\/h2>\r\n    <p class=\"panel-sub\">Preencha s\u00f3 o que voc\u00ea sabe. O que faltar \u00e9 calculado sozinho \u2014 acompanhe nas etiquetas abaixo.<\/p>\r\n\r\n    <div class=\"edit-banner\" id=\"edit-banner\" style=\"display:none;\">\r\n      <span>\u270f\ufe0f Editando: <strong class=\"edit-name\"><\/strong><\/span>\r\n      <button class=\"btn btn-on-dark btn-small\" id=\"btn-cancel-edit\">Cancelar edi\u00e7\u00e3o<\/button>\r\n    <\/div>\r\n\r\n    <div class=\"card\">\r\n      <div class=\"field\">\r\n        <label>Nome do produto <span class=\"req\">*<\/span><\/label>\r\n        <input type=\"text\" id=\"in-nome\" placeholder=\"Ex.: Arroz Tipo 1 5kg\">\r\n      <\/div>\r\n\r\n      <div class=\"grid2\">\r\n        <div class=\"field\">\r\n          <label>Pre\u00e7o de compra da caixa (R$)<\/label>\r\n          <input type=\"number\" inputmode=\"decimal\" step=\"0.01\" id=\"in-caixa\" placeholder=\"0,00\">\r\n        <\/div>\r\n        <div class=\"field\">\r\n          <label>Quantidade por caixa (un) <span class=\"req\">*<\/span><\/label>\r\n          <input type=\"number\" inputmode=\"numeric\" step=\"1\" id=\"in-qtd\" placeholder=\"0\">\r\n        <\/div>\r\n        <div class=\"field\">\r\n          <label>Pre\u00e7o unit\u00e1rio de compra (R$)<\/label>\r\n          <input type=\"number\" inputmode=\"decimal\" step=\"0.01\" id=\"in-unit\" placeholder=\"0,00\">\r\n        <\/div>\r\n        <div class=\"field\">\r\n          <label>% de lucro desejado<\/label>\r\n          <input type=\"number\" inputmode=\"decimal\" step=\"0.1\" id=\"in-lucro\" placeholder=\"Ex.: 30\">\r\n          <div class=\"hint\">digite s\u00f3 o n\u00famero, ex.: 30 para 30%<\/div>\r\n        <\/div>\r\n        <div class=\"field\">\r\n          <label>Pre\u00e7o de venda unit\u00e1rio (R$)<\/label>\r\n          <input type=\"number\" inputmode=\"decimal\" step=\"0.01\" id=\"in-vunit\" placeholder=\"0,00\">\r\n        <\/div>\r\n        <div class=\"field\">\r\n          <label>Pre\u00e7o de venda da caixa (R$)<\/label>\r\n          <input type=\"number\" inputmode=\"decimal\" step=\"0.01\" id=\"in-vcaixa\" placeholder=\"0,00\">\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <div class=\"divider\">Pr\u00e9-visualiza\u00e7\u00e3o calculada<\/div>\r\n      <div class=\"tags-wrap\" id=\"preview-tags\"><\/div>\r\n\r\n      <div class=\"msg\" id=\"form-msg\"><\/div>\r\n\r\n      <div class=\"form-actions\">\r\n        <button class=\"btn btn-primary\" id=\"btn-registrar\">\u2713 Registrar Produto<\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n\r\n  <!-- ===================== PRODUTOS ===================== -->\r\n  <section id=\"view-produtos\" class=\"view\">\r\n    <h2 class=\"panel-title\">Produtos registrados<\/h2>\r\n    <p class=\"panel-sub\">Lista de tudo que j\u00e1 foi cadastrado \u2014 sincronizada entre todos os dispositivos.<\/p>\r\n\r\n    <div class=\"toolbar\">\r\n      <input type=\"text\" class=\"search\" id=\"search-input\" placeholder=\"\ud83d\udd0d Buscar produto pelo nome...\">\r\n      <button class=\"btn btn-ghost\" id=\"btn-print\">\ud83d\udda8 Imprimir lista<\/button>\r\n    <\/div>\r\n\r\n    <div class=\"prod-list\" id=\"prod-list\"><\/div>\r\n    <div class=\"empty-state\" id=\"empty-state\" style=\"display:none;\">\r\n      <div class=\"ic\">\ud83e\uddfa<\/div>\r\n      <h3>Nenhum produto ainda<\/h3>\r\n      <p>V\u00e1 at\u00e9 a aba Cadastro e registre o primeiro produto da sua mercearia.<\/p>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- \u00e1rea usada apenas na impress\u00e3o (gerada via JS) -->\r\n  <div id=\"print-area\"><\/div>\r\n\r\n  <!-- ===================== RESUMO ===================== -->\r\n  <section id=\"view-resumo\" class=\"view\">\r\n    <h2 class=\"panel-title\">Informa\u00e7\u00f5es gerais<\/h2>\r\n    <p class=\"panel-sub\">Atualizado automaticamente conforme voc\u00ea cadastra produtos.<\/p>\r\n\r\n    <div class=\"stats-grid\" id=\"stats-grid\"><\/div>\r\n\r\n    <div class=\"divider\">Backup dos dados<\/div>\r\n    <p class=\"panel-sub\" style=\"margin-top:-8px;\">Os produtos ficam salvos no WordPress e sincronizam entre todos os dispositivos. Use o backup como uma c\u00f3pia extra de seguran\u00e7a.<\/p>\r\n    <div class=\"backup-row\">\r\n      <button class=\"btn btn-ghost\" id=\"btn-export\">\u2b07 Exportar backup (.json)<\/button>\r\n      <button class=\"btn btn-ghost\" id=\"btn-import\">\u2b06 Importar backup<\/button>\r\n      <input type=\"file\" id=\"file-import\" accept=\"application\/json\" style=\"display:none;\">\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <footer>AD Mercearia \u00b7 dados sincronizados com o WordPress \u00b7 requer internet<\/footer>\r\n<\/main>\r\n\r\n<div class=\"toast\" id=\"toast\"><\/div>\r\n<\/div><!-- \/#app-shell -->\r\n\r\n<script>\r\n(function(){\r\n  \"use strict\";\r\n  var produtos = [];\r\n  var editandoId = null;\r\n\r\n  \/\/ ---------- persist\u00eancia (produtos sincronizados via WordPress) ----------\r\n  var API_BASE = window.location.origin + '\/wp-json\/mercearia\/v1';\r\n  var SESSAO_KEY = \"mercearia_sessao\";\r\n  var meuToken = null;\r\n\r\n  function lerSessao(){\r\n    try{\r\n      var raw = sessionStorage.getItem(SESSAO_KEY) || localStorage.getItem(SESSAO_KEY);\r\n      return raw ? JSON.parse(raw) : null;\r\n    }catch(e){ return null; }\r\n  }\r\n  function salvarSessao(usuario, token, lembrar){\r\n    var dados = JSON.stringify({ usuario: usuario, token: token });\r\n    sessionStorage.setItem(SESSAO_KEY, dados);\r\n    if(lembrar) localStorage.setItem(SESSAO_KEY, dados);\r\n    meuToken = token;\r\n  }\r\n  function limparSessaoDados(){\r\n    sessionStorage.removeItem(SESSAO_KEY);\r\n    localStorage.removeItem(SESSAO_KEY);\r\n    meuToken = null;\r\n  }\r\n\r\n  async function apiFetch(caminho, opcoes){\r\n    opcoes = opcoes || {};\r\n    opcoes.headers = Object.assign({'Content-Type':'application\/json'}, opcoes.headers || {});\r\n    if(meuToken) opcoes.headers['X-Mercearia-Token'] = meuToken;\r\n    var resp = await fetch(API_BASE + caminho, opcoes);\r\n    if(resp.status === 401 || resp.status === 403){\r\n      limparSessaoDados();\r\n      mostrarTelaAuth();\r\n      mostrarAuthMsg('login-msg', 'Sua sess\u00e3o expirou. Fa\u00e7a login de novo.');\r\n      throw new Error('sessao-expirada');\r\n    }\r\n    return resp;\r\n  }\r\n\r\n  async function carregarProdutos(){\r\n    var resp = await apiFetch('\/produtos', { method:'GET' });\r\n    var data = await resp.json();\r\n    produtos = (data.produtos || []).map(function(p){\r\n      if(typeof p.estoque !== 'number' || isNaN(p.estoque)) p.estoque = 0;\r\n      return p;\r\n    });\r\n  }\r\n\r\n  function usuarioLogado(){\r\n    var s = lerSessao();\r\n    if(s && s.token){ meuToken = s.token; return s.usuario; }\r\n    return null;\r\n  }\r\n  function limparSessao(){\r\n    limparSessaoDados();\r\n  }\r\n\r\n  function mostrarAuthMsg(id, texto){\r\n    var el = document.getElementById(id);\r\n    el.textContent = texto;\r\n    el.classList.add('show');\r\n  }\r\n  function esconderAuthMsg(id){\r\n    document.getElementById(id).classList.remove('show');\r\n  }\r\n\r\n  async function abrirApp(){\r\n    document.getElementById('auth-overlay').style.display = 'none';\r\n    document.getElementById('app-shell').style.display = 'block';\r\n    mostrarCarregandoProdutos(true);\r\n    try{\r\n      await carregarProdutos();\r\n    }catch(e){ \/* apiFetch j\u00e1 trata sess\u00e3o expirada; outros erros seguem com lista vazia *\/ }\r\n    mostrarCarregandoProdutos(false);\r\n    renderPreview();\r\n    renderProdutos();\r\n    renderStats();\r\n  }\r\n\r\n  function mostrarCarregandoProdutos(carregando){\r\n    var el = document.getElementById('prod-list');\r\n    if(carregando){ el.innerHTML = '<p style=\"text-align:center; padding:40px 0; color:#8C8C8C;\">Carregando produtos\u2026<\/p>'; }\r\n  }\r\n\r\n  function mostrarTelaLogin(){\r\n    document.getElementById('auth-setup').classList.remove('active');\r\n    document.getElementById('auth-login').classList.add('active');\r\n    esconderAuthMsg('setup-msg'); esconderAuthMsg('login-msg');\r\n    document.getElementById('auth-overlay').style.display = 'flex';\r\n    document.getElementById('app-shell').style.display = 'none';\r\n  }\r\n\r\n  function mostrarTelaCadastroConta(){\r\n    document.getElementById('auth-login').classList.remove('active');\r\n    document.getElementById('auth-setup').classList.add('active');\r\n    esconderAuthMsg('setup-msg'); esconderAuthMsg('login-msg');\r\n    document.getElementById('auth-overlay').style.display = 'flex';\r\n    document.getElementById('app-shell').style.display = 'none';\r\n  }\r\n\r\n  function mostrarTelaAuth(){\r\n    mostrarTelaLogin();\r\n  }\r\n\r\n  function definirBotaoCarregando(btnId, carregando, textoNormal){\r\n    var btn = document.getElementById(btnId);\r\n    btn.disabled = carregando;\r\n    btn.textContent = carregando ? 'Aguarde\u2026' : textoNormal;\r\n  }\r\n\r\n  async function criarConta(){\r\n    esconderAuthMsg('setup-msg');\r\n    var user = document.getElementById('setup-user').value.trim();\r\n    var email = document.getElementById('setup-email').value.trim();\r\n    var pass = document.getElementById('setup-pass').value;\r\n    var pass2 = document.getElementById('setup-pass2').value;\r\n    if(!user){ mostrarAuthMsg('setup-msg', 'Digite um nome de usu\u00e1rio.'); return; }\r\n    if(!email){ mostrarAuthMsg('setup-msg', 'Digite um e-mail v\u00e1lido.'); return; }\r\n    if(pass.length < 4){ mostrarAuthMsg('setup-msg', 'A senha precisa ter pelo menos 4 caracteres.'); return; }\r\n    if(pass !== pass2){ mostrarAuthMsg('setup-msg', 'As senhas n\u00e3o s\u00e3o iguais.'); return; }\r\n\r\n    definirBotaoCarregando('btn-setup', true, '\u2713 Criar e Entrar');\r\n    try{\r\n      var resp = await fetch(API_BASE + '\/registrar', {\r\n        method: 'POST',\r\n        credentials: 'same-origin',\r\n        headers: {'Content-Type':'application\/json'},\r\n        body: JSON.stringify({usuario:user, email:email, senha:pass})\r\n      });\r\n      var data = await resp.json();\r\n      if(data.ok){\r\n        salvarSessao(data.usuario || user, data.token, true);\r\n        document.getElementById('setup-user').value = '';\r\n        document.getElementById('setup-email').value = '';\r\n        document.getElementById('setup-pass').value = '';\r\n        document.getElementById('setup-pass2').value = '';\r\n        await abrirApp();\r\n      }else{\r\n        mostrarAuthMsg('setup-msg', data.erro || 'N\u00e3o foi poss\u00edvel criar a conta.');\r\n      }\r\n    }catch(e){\r\n      mostrarAuthMsg('setup-msg', 'N\u00e3o consegui conectar ao WordPress. Confira sua internet e tente de novo.');\r\n    }\r\n    definirBotaoCarregando('btn-setup', false, '\u2713 Criar e Entrar');\r\n  }\r\n\r\n  async function fazerLogin(){\r\n    esconderAuthMsg('login-msg');\r\n    var user = document.getElementById('login-user').value.trim();\r\n    var pass = document.getElementById('login-pass').value;\r\n    var lembrar = document.getElementById('login-remember').checked;\r\n    if(!user || !pass){ mostrarAuthMsg('login-msg', 'Preencha usu\u00e1rio e senha.'); return; }\r\n\r\n    definirBotaoCarregando('btn-login', true, '\u2713 Entrar');\r\n    try{\r\n      var resp = await fetch(API_BASE + '\/login', {\r\n        method: 'POST',\r\n        credentials: 'same-origin',\r\n        headers: {'Content-Type':'application\/json'},\r\n        body: JSON.stringify({usuario:user, senha:pass, lembrar:lembrar})\r\n      });\r\n      var data = await resp.json();\r\n      if(data.ok){\r\n        salvarSessao(data.usuario || user, data.token, lembrar);\r\n        document.getElementById('login-pass').value = '';\r\n        await abrirApp();\r\n      }else{\r\n        mostrarAuthMsg('login-msg', data.erro || 'Usu\u00e1rio ou senha incorretos.');\r\n      }\r\n    }catch(e){\r\n      mostrarAuthMsg('login-msg', 'N\u00e3o consegui conectar ao WordPress. Confira sua internet e tente de novo.');\r\n    }\r\n    definirBotaoCarregando('btn-login', false, '\u2713 Entrar');\r\n  }\r\n\r\n  async function sair(){\r\n    try{\r\n      if(meuToken){\r\n        await fetch(API_BASE + '\/logout', { method:'POST', headers:{'X-Mercearia-Token': meuToken} });\r\n      }\r\n    }catch(e){ \/* mesmo se falhar, segue com o logout local *\/ }\r\n    limparSessao();\r\n    mostrarTelaAuth();\r\n  }\r\n\r\n  \/\/ ---------- utilidades ----------\r\n  function fmtR$(v){\r\n    if(v===null || v===undefined || isNaN(v)) return \"\u2014\";\r\n    return \"R$ \" + v.toLocaleString('pt-BR', {minimumFractionDigits:2, maximumFractionDigits:2});\r\n  }\r\n  function fmtPct(v){\r\n    if(v===null || v===undefined || isNaN(v)) return \"\u2014\";\r\n    return (v*100).toLocaleString('pt-BR', {minimumFractionDigits:1, maximumFractionDigits:1}) + \"%\";\r\n  }\r\n  function num(id){\r\n    var el = document.getElementById(id);\r\n    var v = el.value.trim();\r\n    if(v===\"\") return null;\r\n    var n = parseFloat(v.replace(\",\",\".\"));\r\n    return isNaN(n) ? null : n;\r\n  }\r\n\r\n  \/\/ ---------- c\u00e1lculo autom\u00e1tico (mesma l\u00f3gica da planilha) ----------\r\n  function calcular(inputs){\r\n    var qtd = inputs.qtd; \/\/ obrigat\u00f3rio\r\n    var unit = inputs.unit;\r\n    var caixa = inputs.caixa;\r\n    var lucro = inputs.lucro;\r\n    var vunit = inputs.vunit;\r\n    var vcaixa = inputs.vcaixa;\r\n\r\n    var srcUnit = unit !== null, srcCaixa = caixa !== null;\r\n    var srcLucro = lucro !== null, srcVunit = vunit !== null, srcVcaixa = vcaixa !== null;\r\n\r\n    if(unit===null && caixa!==null && qtd) unit = caixa\/qtd;\r\n    if(caixa===null && unit!==null && qtd) caixa = unit*qtd;\r\n\r\n    if(lucro===null){\r\n      if(vunit!==null && unit!==null && unit!==0) lucro = (vunit\/unit) - 1;\r\n      else if(vcaixa!==null && caixa!==null && caixa!==0) lucro = (vcaixa\/caixa) - 1;\r\n    }\r\n    if(vunit===null){\r\n      if(unit!==null && lucro!==null) vunit = unit*(1+lucro);\r\n      else if(vcaixa!==null && qtd) vunit = vcaixa\/qtd;\r\n    }\r\n    if(vcaixa===null){\r\n      if(vunit!==null && qtd) vcaixa = vunit*qtd;\r\n    }\r\n\r\n    return {\r\n      qtd: qtd, unit: unit, caixa: caixa, lucro: lucro, vunit: vunit, vcaixa: vcaixa,\r\n      autoUnit: !srcUnit, autoCaixa: !srcCaixa, autoLucro: !srcLucro, autoVunit: !srcVunit, autoVcaixa: !srcVcaixa\r\n    };\r\n  }\r\n\r\n  function lerFormulario(){\r\n    return {\r\n      nome: document.getElementById('in-nome').value.trim(),\r\n      caixa: num('in-caixa'),\r\n      qtd: num('in-qtd'),\r\n      unit: num('in-unit'),\r\n      lucro: (function(){ var l = num('in-lucro'); return l===null ? null : l\/100; })(),\r\n      vunit: num('in-vunit'),\r\n      vcaixa: num('in-vcaixa')\r\n    };\r\n  }\r\n\r\n  function renderPreview(){\r\n    var f = lerFormulario();\r\n    var c = calcular(f);\r\n    var tags = [\r\n      {label:\"Pre\u00e7o unit. compra\", value: fmtR$(c.unit), auto:c.autoUnit && c.unit!==null},\r\n      {label:\"Pre\u00e7o da caixa\", value: fmtR$(c.caixa), auto:c.autoCaixa && c.caixa!==null},\r\n      {label:\"% de lucro\", value: fmtPct(c.lucro), auto:c.autoLucro && c.lucro!==null},\r\n      {label:\"Venda unit\u00e1ria\", value: fmtR$(c.vunit), auto:c.autoVunit && c.vunit!==null},\r\n      {label:\"Venda da caixa\", value: fmtR$(c.vcaixa), auto:c.autoVcaixa && c.vcaixa!==null}\r\n    ];\r\n    var wrap = document.getElementById('preview-tags');\r\n    wrap.innerHTML = tags.map(function(t){\r\n      var empty = t.value === \"\u2014\";\r\n      return '<div class=\"tag'+(t.auto&&!empty?' auto':'')+(empty?' empty':'')+'\">' +\r\n             '<div class=\"t-label\">'+t.label+'<\/div>' +\r\n             '<div class=\"t-value mono\">'+t.value+'<\/div><\/div>';\r\n    }).join('');\r\n    return {f:f, c:c};\r\n  }\r\n\r\n  function mostrarMsg(texto, tipo){\r\n    var el = document.getElementById('form-msg');\r\n    el.textContent = texto;\r\n    el.className = 'msg show ' + tipo;\r\n  }\r\n  function esconderMsg(){\r\n    var el = document.getElementById('form-msg');\r\n    el.className = 'msg';\r\n  }\r\n\r\n  function limparFormulario(){\r\n    ['in-nome','in-caixa','in-qtd','in-unit','in-lucro','in-vunit','in-vcaixa'].forEach(function(id){\r\n      document.getElementById(id).value = '';\r\n    });\r\n    renderPreview();\r\n  }\r\n\r\n  async function registrar(){\r\n    var res = renderPreview();\r\n    var f = res.f, c = res.c;\r\n\r\n    if(!f.nome){ mostrarMsg('Digite o nome do produto.', 'error'); return; }\r\n    if(!c.qtd || c.qtd<=0){ mostrarMsg('Informe a quantidade por caixa.', 'error'); return; }\r\n    if(c.unit===null || c.caixa===null){ mostrarMsg('Informe pelo menos um pre\u00e7o de compra (da caixa ou unit\u00e1rio).', 'error'); return; }\r\n    if(c.lucro===null || c.vunit===null || c.vcaixa===null){ mostrarMsg('Informe a % de lucro ou um dos pre\u00e7os de venda.', 'error'); return; }\r\n\r\n    var dadosProduto = {\r\n      nome: f.nome,\r\n      qtd: c.qtd,\r\n      precoCaixaCompra: round2(c.caixa),\r\n      precoUnitCompra: round2(c.unit),\r\n      lucroPct: c.lucro,\r\n      precoUnitVenda: round2(c.vunit),\r\n      precoCaixaVenda: round2(c.vcaixa)\r\n    };\r\n\r\n    var btn = document.getElementById('btn-registrar');\r\n    var textoOriginal = btn.textContent;\r\n    btn.disabled = true;\r\n    btn.textContent = 'Salvando\u2026';\r\n\r\n    try{\r\n      if(editandoId){\r\n        await apiFetch('\/produtos\/' + editandoId, { method:'PUT', body: JSON.stringify(dadosProduto) });\r\n        mostrarMsg('\"'+f.nome+'\" foi atualizado com sucesso!', 'success');\r\n        editandoId = null;\r\n        atualizarModoFormulario();\r\n      }else{\r\n        await apiFetch('\/produtos', { method:'POST', body: JSON.stringify(dadosProduto) });\r\n        mostrarMsg('\"'+f.nome+'\" foi registrado com sucesso!', 'success');\r\n      }\r\n      await carregarProdutos();\r\n      limparFormulario();\r\n      renderProdutos();\r\n      renderStats();\r\n      setTimeout(esconderMsg, 3500);\r\n    }catch(e){\r\n      if(e.message !== 'sessao-expirada'){\r\n        mostrarMsg('N\u00e3o foi poss\u00edvel salvar. Confira sua internet e tente de novo.', 'error');\r\n      }\r\n    }\r\n    btn.disabled = false;\r\n    btn.textContent = textoOriginal;\r\n  }\r\n\r\n  function round2(v){ return v===null ? null : Math.round(v*100)\/100; }\r\n\r\n  \/\/ mant\u00e9m % de lucro, pre\u00e7o unit\u00e1rio de compra e pre\u00e7o de venda unit\u00e1rio\r\n  \/\/ coerentes entre si sempre que um deles \u00e9 editado diretamente\r\n  function sincronizarCampos(idAlterado){\r\n    var unit = num('in-unit');\r\n    var vunit = num('in-vunit');\r\n    var lucroPct = num('in-lucro');\r\n\r\n    if(idAlterado === 'in-vunit'){\r\n      if(unit !== null && unit !== 0 && vunit !== null){\r\n        document.getElementById('in-lucro').value = round2((vunit\/unit - 1) * 100);\r\n      }\r\n    }else if(idAlterado === 'in-lucro'){\r\n      if(unit !== null && lucroPct !== null){\r\n        document.getElementById('in-vunit').value = round2(unit * (1 + lucroPct\/100));\r\n      }\r\n    }else if(idAlterado === 'in-unit'){\r\n      if(lucroPct !== null && unit !== null){\r\n        document.getElementById('in-vunit').value = round2(unit * (1 + lucroPct\/100));\r\n      }else if(vunit !== null && unit !== null && unit !== 0){\r\n        document.getElementById('in-lucro').value = round2((vunit\/unit - 1) * 100);\r\n      }\r\n    }\r\n  }\r\n\r\n  function iniciarEdicao(id){\r\n    var p = produtos.find(function(x){ return x.id===id; });\r\n    if(!p) return;\r\n    document.getElementById('in-nome').value = p.nome;\r\n    document.getElementById('in-caixa').value = p.precoCaixaCompra !== null ? p.precoCaixaCompra : '';\r\n    document.getElementById('in-qtd').value = p.qtd !== null ? p.qtd : '';\r\n    document.getElementById('in-unit').value = p.precoUnitCompra !== null ? p.precoUnitCompra : '';\r\n    document.getElementById('in-lucro').value = p.lucroPct !== null ? round2(p.lucroPct*100) : '';\r\n    document.getElementById('in-vunit').value = p.precoUnitVenda !== null ? p.precoUnitVenda : '';\r\n    document.getElementById('in-vcaixa').value = p.precoCaixaVenda !== null ? p.precoCaixaVenda : '';\r\n    editandoId = id;\r\n    atualizarModoFormulario();\r\n    renderPreview();\r\n    esconderMsg();\r\n    switchView('cadastro');\r\n  }\r\n\r\n  function cancelarEdicao(){\r\n    editandoId = null;\r\n    limparFormulario();\r\n    atualizarModoFormulario();\r\n    esconderMsg();\r\n  }\r\n\r\n  function atualizarModoFormulario(){\r\n    var banner = document.getElementById('edit-banner');\r\n    var btn = document.getElementById('btn-registrar');\r\n    if(editandoId){\r\n      var p = produtos.find(function(x){ return x.id===editandoId; });\r\n      banner.style.display = 'flex';\r\n      banner.querySelector('.edit-name').textContent = p ? p.nome : '';\r\n      btn.textContent = '\u2713 Salvar Altera\u00e7\u00f5es';\r\n    }else{\r\n      banner.style.display = 'none';\r\n      btn.textContent = '\u2713 Registrar Produto';\r\n    }\r\n  }\r\n\r\n  function switchView(name){\r\n    document.querySelectorAll('.tab-btn').forEach(function(b){ b.classList.toggle('active', b.dataset.view===name); });\r\n    document.querySelectorAll('.view').forEach(function(v){ v.classList.remove('active'); });\r\n    document.getElementById('view-'+name).classList.add('active');\r\n    if(name === 'resumo') renderStats();\r\n  }\r\n\r\n  \/\/ ---------- lista de produtos ----------\r\n  function renderProdutos(filtro){\r\n    filtro = (filtro||'').toLowerCase();\r\n    var lista = produtos.filter(function(p){ return p.nome.toLowerCase().indexOf(filtro)>-1; });\r\n    var el = document.getElementById('prod-list');\r\n    var empty = document.getElementById('empty-state');\r\n\r\n    if(produtos.length===0){\r\n      el.innerHTML=''; empty.style.display='block'; return;\r\n    }\r\n    empty.style.display='none';\r\n\r\n    if(lista.length===0){\r\n      el.innerHTML = '<p style=\"color:#9B9382; font-size:14px; text-align:center; padding:30px 0;\">Nenhum produto encontrado para essa busca.<\/p>';\r\n      return;\r\n    }\r\n\r\n    el.innerHTML = lista.map(function(p){\r\n      return '<div class=\"prod-card\">' +\r\n        '<div class=\"prod-head\"><h3>'+escapeHtml(p.nome)+'<\/h3>' +\r\n        '<div class=\"prod-actions\">' +\r\n        '<button class=\"btn btn-ghost btn-small\" data-edit=\"'+p.id+'\">Editar<\/button>' +\r\n        '<button class=\"btn btn-danger\" data-del=\"'+p.id+'\">Excluir<\/button>' +\r\n        '<\/div><\/div>' +\r\n        '<div class=\"prod-grid\">' +\r\n          item('Estoque atual', (p.estoque||0)+' un.', false, true) +\r\n          item('Qtd\/caixa', p.qtd) +\r\n          item('Pre\u00e7o unit. compra', fmtR$(p.precoUnitCompra)) +\r\n          item('Pre\u00e7o da caixa', fmtR$(p.precoCaixaCompra)) +\r\n          item('% de lucro', fmtPct(p.lucroPct), true) +\r\n          item('Venda unit\u00e1ria', fmtR$(p.precoUnitVenda)) +\r\n          item('Venda da caixa', fmtR$(p.precoCaixaVenda)) +\r\n        '<\/div>' +\r\n        '<div class=\"estoque-panel\">' +\r\n          '<div class=\"estoque-box\">' +\r\n            '<label>Estoque <span class=\"hint-inline\">(un. \u2014 atualize ao vender)<\/span><\/label>' +\r\n            '<div class=\"estoque-controls\">' +\r\n              '<input type=\"number\" inputmode=\"numeric\" step=\"1\" min=\"0\" class=\"input-estoque\" data-id=\"'+p.id+'\" value=\"'+(p.estoque||0)+'\">' +\r\n              '<button class=\"btn btn-ghost btn-small\" data-save-estoque=\"'+p.id+'\">Salvar<\/button>' +\r\n            '<\/div>' +\r\n          '<\/div>' +\r\n          '<div class=\"estoque-box\">' +\r\n            '<label>Compra <span class=\"hint-inline\">(caixas compradas agora)<\/span><\/label>' +\r\n            '<div class=\"estoque-controls\">' +\r\n              '<input type=\"number\" inputmode=\"numeric\" step=\"1\" min=\"0\" class=\"input-compra\" data-id=\"'+p.id+'\" placeholder=\"0\">' +\r\n              '<button class=\"btn btn-compra btn-small\" data-add-compra=\"'+p.id+'\">+ Adicionar<\/button>' +\r\n            '<\/div>' +\r\n            '<div class=\"hint\">'+p.qtd+' un. por caixa \u2014 soma direto no estoque<\/div>' +\r\n          '<\/div>' +\r\n        '<\/div>' +\r\n      '<\/div>';\r\n    }).join('');\r\n\r\n    el.querySelectorAll('[data-edit]').forEach(function(btn){\r\n      btn.addEventListener('click', function(){\r\n        iniciarEdicao(Number(btn.getAttribute('data-edit')));\r\n      });\r\n    });\r\n\r\n    el.querySelectorAll('[data-del]').forEach(function(btn){\r\n      btn.addEventListener('click', async function(){\r\n        var id = Number(btn.getAttribute('data-del'));\r\n        var p = produtos.find(function(x){ return x.id===id; });\r\n        if(p && confirm('Excluir \"'+p.nome+'\"?')){\r\n          btn.disabled = true;\r\n          try{\r\n            await apiFetch('\/produtos\/' + id, { method:'DELETE' });\r\n            if(editandoId===id){ editandoId = null; limparFormulario(); atualizarModoFormulario(); }\r\n            await carregarProdutos();\r\n            renderProdutos(document.getElementById('search-input').value);\r\n            renderStats();\r\n          }catch(e){\r\n            if(e.message !== 'sessao-expirada') alert('N\u00e3o foi poss\u00edvel excluir. Tente novamente.');\r\n          }\r\n          btn.disabled = false;\r\n        }\r\n      });\r\n    });\r\n\r\n    el.querySelectorAll('[data-save-estoque]').forEach(function(btn){\r\n      btn.addEventListener('click', async function(){\r\n        var id = Number(btn.getAttribute('data-save-estoque'));\r\n        var input = el.querySelector('.input-estoque[data-id=\"'+id+'\"]');\r\n        var val = parseInt(input.value, 10);\r\n        if(isNaN(val) || val < 0){ alert('Informe um n\u00famero de estoque v\u00e1lido (0 ou maior).'); return; }\r\n        await definirEstoque(id, val);\r\n        mostrarToast('Estoque atualizado!');\r\n      });\r\n    });\r\n\r\n    el.querySelectorAll('[data-add-compra]').forEach(function(btn){\r\n      btn.addEventListener('click', async function(){\r\n        var id = Number(btn.getAttribute('data-add-compra'));\r\n        var input = el.querySelector('.input-compra[data-id=\"'+id+'\"]');\r\n        var caixas = parseFloat((input.value||'').replace(',', '.'));\r\n        if(isNaN(caixas) || caixas <= 0){ alert('Informe a quantidade de caixas compradas.'); return; }\r\n        var p = produtos.find(function(x){ return x.id===id; });\r\n        if(!p) return;\r\n        var unidades = Math.round(caixas * p.qtd);\r\n        await definirEstoque(id, (p.estoque||0) + unidades);\r\n        input.value = '';\r\n        mostrarToast('+'+unidades+' unidades adicionadas ao estoque de \"'+p.nome+'\"!');\r\n      });\r\n    });\r\n\r\n    function item(k, v, lucro, destaque){\r\n      return '<div class=\"prod-item'+(lucro?' lucro':'')+(destaque?' destaque-item':'')+'\"><div class=\"k\">'+k+'<\/div><div class=\"v mono\">'+v+'<\/div><\/div>';\r\n    }\r\n  }\r\n\r\n  async function definirEstoque(id, novoValor){\r\n    try{\r\n      await apiFetch('\/produtos\/' + id, { method:'PUT', body: JSON.stringify({ estoque: novoValor }) });\r\n      await carregarProdutos();\r\n      renderProdutos(document.getElementById('search-input').value);\r\n      renderStats();\r\n    }catch(e){\r\n      if(e.message !== 'sessao-expirada') alert('N\u00e3o foi poss\u00edvel atualizar o estoque. Tente novamente.');\r\n    }\r\n  }\r\n\r\n  function mostrarToast(texto){\r\n    var t = document.getElementById('toast');\r\n    t.textContent = texto;\r\n    t.classList.add('show');\r\n    clearTimeout(t._timer);\r\n    t._timer = setTimeout(function(){ t.classList.remove('show'); }, 2600);\r\n  }\r\n\r\n  function escapeHtml(s){\r\n    var d = document.createElement('div'); d.textContent = s; return d.innerHTML;\r\n  }\r\n\r\n  \/\/ ---------- resumo ----------\r\n  function renderStats(){\r\n    var el = document.getElementById('stats-grid');\r\n    if(produtos.length===0){\r\n      el.innerHTML = '<div class=\"empty-state\" style=\"grid-column:1\/-1;\"><div class=\"ic\">\ud83d\udcca<\/div><h3>Sem dados ainda<\/h3><p>Cadastre produtos para ver o resumo geral aqui.<\/p><\/div>';\r\n      return;\r\n    }\r\n    var totalInvestido = produtos.reduce(function(s,p){ return s + (p.estoque||0) * (p.precoUnitCompra||0); }, 0);\r\n    var totalVenda = produtos.reduce(function(s,p){ return s + (p.estoque||0) * (p.precoUnitVenda||0); }, 0);\r\n    var lucroTotal = totalVenda - totalInvestido;\r\n    var lucroMedio = produtos.reduce(function(s,p){ return s + (p.lucroPct||0); }, 0) \/ produtos.length;\r\n    var maisCaro = produtos.slice().sort(function(a,b){ return b.precoUnitVenda-a.precoUnitVenda; })[0];\r\n    var maisBarato = produtos.slice().sort(function(a,b){ return a.precoUnitVenda-b.precoUnitVenda; })[0];\r\n    var maiorMargem = produtos.slice().sort(function(a,b){ return b.lucroPct-a.lucroPct; })[0];\r\n    var totalUnidadesEstoque = produtos.reduce(function(s,p){ return s + (p.estoque||0); }, 0);\r\n\r\n    var cards = [\r\n      {k:'Total de produtos', v: produtos.length, destaque:true},\r\n      {k:'Unidades em estoque', v: totalUnidadesEstoque, destaque:true},\r\n      {k:'Investido no estoque atual', v: fmtR$(totalInvestido)},\r\n      {k:'Valor esperado de venda (estoque)', v: fmtR$(totalVenda)},\r\n      {k:'Lucro total esperado (estoque)', v: fmtR$(lucroTotal)},\r\n      {k:'Lucro m\u00e9dio %', v: fmtPct(lucroMedio)},\r\n      {k:'Produto mais caro', v: maisCaro.nome, small:true},\r\n      {k:'Produto mais barato', v: maisBarato.nome, small:true},\r\n      {k:'Maior margem de lucro', v: maiorMargem.nome, small:true}\r\n    ];\r\n    el.innerHTML = cards.map(function(c){\r\n      return '<div class=\"stat-card'+(c.destaque?' destaque':'')+'\"><div class=\"k\">'+c.k+'<\/div>' +\r\n             '<div class=\"v'+(c.small?' small':'')+'\">'+c.v+'<\/div><\/div>';\r\n    }).join('');\r\n  }\r\n\r\n  \/\/ ---------- impress\u00e3o ----------\r\n  function imprimirLista(){\r\n    var area = document.getElementById('print-area');\r\n    if(produtos.length===0){\r\n      alert('N\u00e3o h\u00e1 produtos cadastrados para imprimir.');\r\n      return;\r\n    }\r\n    var totalInvestido = produtos.reduce(function(s,p){ return s + (p.estoque||0) * (p.precoUnitCompra||0); }, 0);\r\n    var totalVenda = produtos.reduce(function(s,p){ return s + (p.estoque||0) * (p.precoUnitVenda||0); }, 0);\r\n    var dataHoje = new Date().toLocaleDateString('pt-BR');\r\n\r\n    var linhas = produtos.map(function(p){\r\n      return '<tr>' +\r\n        '<td class=\"nome-col\">'+escapeHtml(p.nome)+'<\/td>' +\r\n        '<td>'+(p.estoque||0)+'<\/td>' +\r\n        '<td>'+p.qtd+'<\/td>' +\r\n        '<td>'+fmtR$(p.precoUnitCompra)+'<\/td>' +\r\n        '<td>'+fmtR$(p.precoCaixaCompra)+'<\/td>' +\r\n        '<td>'+fmtPct(p.lucroPct)+'<\/td>' +\r\n        '<td>'+fmtR$(p.precoUnitVenda)+'<\/td>' +\r\n        '<td>'+fmtR$(p.precoCaixaVenda)+'<\/td>' +\r\n      '<\/tr>';\r\n    }).join('');\r\n\r\n    area.innerHTML =\r\n      '<div class=\"print-head\">' +\r\n        '<h1><span class=\"brand-ad\">AD<\/span> Mercearia \u2014 Lista de Produtos<\/h1>' +\r\n        '<div class=\"data\">Emitido em '+dataHoje+' \u00b7 '+produtos.length+' produto(s)<\/div>' +\r\n      '<\/div>' +\r\n      '<table>' +\r\n        '<thead><tr>' +\r\n          '<th>Nome<\/th><th>Estoque<\/th><th>Qtd\/Caixa<\/th><th>Pre\u00e7o Unit. Compra<\/th><th>Pre\u00e7o Caixa Compra<\/th>' +\r\n          '<th>% Lucro<\/th><th>Venda Unit\u00e1ria<\/th><th>Venda Caixa<\/th>' +\r\n        '<\/tr><\/thead>' +\r\n        '<tbody>'+linhas+'<\/tbody>' +\r\n        '<tfoot><tr>' +\r\n          '<td colspan=\"4\">Total investido no estoque atual<\/td><td>'+fmtR$(totalInvestido)+'<\/td>' +\r\n          '<td colspan=\"1\">Valor esperado de venda (estoque)<\/td><td colspan=\"2\">'+fmtR$(totalVenda)+'<\/td>' +\r\n        '<\/tr><\/tfoot>' +\r\n      '<\/table>' +\r\n      '<div class=\"print-foot\">AD Mercearia \u00b7 documento gerado automaticamente pelo sistema de cadastro de produtos<\/div>';\r\n\r\n    window.print();\r\n  }\r\n\r\n  \/\/ ---------- abas ----------\r\n  document.querySelectorAll('.tab-btn').forEach(function(btn){\r\n    btn.addEventListener('click', function(){ switchView(btn.dataset.view); });\r\n  });\r\n\r\n  \/\/ ---------- eventos ----------\r\n  ['in-nome','in-caixa','in-qtd','in-unit','in-lucro','in-vunit','in-vcaixa'].forEach(function(id){\r\n    document.getElementById(id).addEventListener('input', function(){\r\n      sincronizarCampos(id);\r\n      renderPreview();\r\n    });\r\n  });\r\n  document.getElementById('btn-registrar').addEventListener('click', registrar);\r\n  document.getElementById('btn-cancel-edit').addEventListener('click', cancelarEdicao);\r\n  document.getElementById('search-input').addEventListener('input', function(){ renderProdutos(this.value); });\r\n  document.getElementById('btn-print').addEventListener('click', imprimirLista);\r\n\r\n  document.getElementById('btn-export').addEventListener('click', function(){\r\n    var blob = new Blob([JSON.stringify(produtos, null, 2)], {type:'application\/json'});\r\n    var url = URL.createObjectURL(blob);\r\n    var a = document.createElement('a');\r\n    a.href = url; a.download = 'mercearia-backup-'+new Date().toISOString().slice(0,10)+'.json';\r\n    document.body.appendChild(a); a.click(); document.body.removeChild(a);\r\n    URL.revokeObjectURL(url);\r\n  });\r\n  document.getElementById('btn-import').addEventListener('click', function(){\r\n    document.getElementById('file-import').click();\r\n  });\r\n  document.getElementById('file-import').addEventListener('change', function(e){\r\n    var file = e.target.files[0];\r\n    if(!file) return;\r\n    var reader = new FileReader();\r\n    reader.onload = async function(ev){\r\n      try{\r\n        var dados = JSON.parse(ev.target.result);\r\n        if(!Array.isArray(dados)) throw new Error('formato inv\u00e1lido');\r\n        if(confirm('Importar '+dados.length+' produto(s)? Isso vai somar \u00e0 lista atual no WordPress.')){\r\n          for(var i=0; i<dados.length; i++){\r\n            var p = dados[i];\r\n            await apiFetch('\/produtos', { method:'POST', body: JSON.stringify({\r\n              nome: p.nome, qtd: p.qtd, estoque: p.estoque||0,\r\n              precoCaixaCompra: p.precoCaixaCompra, precoUnitCompra: p.precoUnitCompra,\r\n              lucroPct: p.lucroPct, precoUnitVenda: p.precoUnitVenda, precoCaixaVenda: p.precoCaixaVenda\r\n            })});\r\n          }\r\n          await carregarProdutos();\r\n          renderProdutos(); renderStats();\r\n          mostrarToast('Backup importado com sucesso!');\r\n        }\r\n      }catch(err){\r\n        if(err.message !== 'sessao-expirada') alert('N\u00e3o foi poss\u00edvel importar esse arquivo.');\r\n      }\r\n      e.target.value = '';\r\n    };\r\n    reader.readAsText(file);\r\n  });\r\n\r\n  document.getElementById('btn-setup').addEventListener('click', criarConta);\r\n  document.getElementById('btn-login').addEventListener('click', fazerLogin);\r\n  document.getElementById('btn-logout').addEventListener('click', sair);\r\n  document.getElementById('link-forgot').href = window.location.origin + '\/wp-login.php?action=lostpassword';\r\n  document.getElementById('link-goto-setup').addEventListener('click', mostrarTelaCadastroConta);\r\n  document.getElementById('link-goto-login').addEventListener('click', mostrarTelaLogin);\r\n  ['setup-user','setup-email','setup-pass','setup-pass2'].forEach(function(id){\r\n    document.getElementById(id).addEventListener('keydown', function(e){ if(e.key==='Enter') criarConta(); });\r\n  });\r\n  ['login-user','login-pass'].forEach(function(id){\r\n    document.getElementById(id).addEventListener('keydown', function(e){ if(e.key==='Enter') fazerLogin(); });\r\n  });\r\n\r\n  \/\/ ---------- inicializa\u00e7\u00e3o ----------\r\n  if(usuarioLogado()){\r\n    abrirApp();\r\n  }else{\r\n    mostrarTelaAuth();\r\n  }\r\n})();\r\n<\/script>\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>AD Mercearia \u00b7 Cadastro de Produtos AD AD Mercearia Digite seu usu\u00e1rio e senha para continuar. Usu\u00e1rio Senha Manter conectado neste dispositivo \u2713 Entrar \uff0b Criar conta Esqueceu a senha? Redefinir no WordPress Criar conta Escolha um usu\u00e1rio e senha para acessar o sistema. Usu\u00e1rio E-mail Senha Confirmar senha \u2713 Criar e Entrar J\u00e1 tem [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"1","meta":{"footnotes":""},"class_list":["post-12","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/d7dsgn.com.br\/wp-json\/wp\/v2\/pages\/12","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/d7dsgn.com.br\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/d7dsgn.com.br\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/d7dsgn.com.br\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/d7dsgn.com.br\/wp-json\/wp\/v2\/comments?post=12"}],"version-history":[{"count":19,"href":"https:\/\/d7dsgn.com.br\/wp-json\/wp\/v2\/pages\/12\/revisions"}],"predecessor-version":[{"id":41,"href":"https:\/\/d7dsgn.com.br\/wp-json\/wp\/v2\/pages\/12\/revisions\/41"}],"wp:attachment":[{"href":"https:\/\/d7dsgn.com.br\/wp-json\/wp\/v2\/media?parent=12"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}