{"id":11954,"date":"2026-06-25T02:50:57","date_gmt":"2026-06-25T00:50:57","guid":{"rendered":"https:\/\/shopini.tn\/?page_id=11954"},"modified":"2026-06-26T02:23:48","modified_gmt":"2026-06-26T00:23:48","slug":"generateur-de-factures-et-devis-gratuit-tunisie","status":"publish","type":"page","link":"https:\/\/shopini.tn\/ar\/generateur-de-factures-et-devis-gratuit-tunisie\/","title":{"rendered":"Generateur de factures et devis gratuit Tunisie"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"11954\" class=\"elementor elementor-11954\">\n\t\t\t\t<div class=\"elementor-element elementor-element-c5960c4 e-flex e-con-boxed e-con e-parent\" data-id=\"c5960c4\" 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-caa71de elementor-widget elementor-widget-html\" data-id=\"caa71de\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div id=\"si-app\"><\/div>\r\n\r\n<style>\r\n@import url('https:\/\/fonts.googleapis.com\/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500&display=swap');\r\n\r\n#si-app,#si-app *,#si-app *::before,#si-app *::after{margin:0;padding:0;box-sizing:border-box}\r\n\r\n#si-app{\r\n    --si-bg:#f5f5f3;--si-white:#ffffff;--si-text:#1a1a1a;--si-text-2:#555;\r\n    --si-text-3:#999;--si-text-4:#ccc;--si-border:#e0ddd8;\r\n    --si-orange:#ff6b2c;--si-orange-hover:#e55a1f;--si-orange-light:rgba(255,107,44,.08);\r\n    --si-orange-glow:rgba(255,107,44,.20);--si-dark:#1e1e1e;\r\n    --si-green:#22c55e;--si-green-light:rgba(34,197,94,.10);\r\n    --si-red:#ef4444;--si-red-light:rgba(239,68,68,.08);\r\n    --si-amber:#f59e0b;--si-amber-light:rgba(245,158,11,.10);\r\n    --si-r:16px;--si-rm:12px;--si-rs:8px;\r\n    --si-shadow:0 2px 8px rgba(0,0,0,.06),0 8px 24px rgba(0,0,0,.04);\r\n    --si-shadow-lg:0 12px 40px rgba(0,0,0,.10);\r\n    --si-font:'Plus Jakarta Sans',-apple-system,sans-serif;\r\n    --si-mono:'JetBrains Mono',monospace;\r\n\r\n    font-family:var(--si-font);font-size:14px;color:var(--si-text);line-height:1.6;\r\n    background:var(--si-bg);border-radius:var(--si-r);overflow:hidden;\r\n    max-width:940px;margin:0 auto;position:relative;\r\n}\r\n#si-app input,#si-app select,#si-app textarea,#si-app button{font-family:var(--si-font)}\r\n\r\n\/* \u2550\u2550\u2550 HERO \u2550\u2550\u2550 *\/\r\n#si-hero{background:linear-gradient(135deg,#1a1a1a,#2d2d2d 50%,#1a1a1a);padding:36px 32px 28px;position:relative;overflow:hidden}\r\n#si-hero::before{content:'';position:absolute;top:-80px;right:-60px;width:300px;height:300px;background:radial-gradient(circle,rgba(255,107,44,.15),transparent 60%);pointer-events:none}\r\n#si-hero::after{content:'';position:absolute;bottom:-40px;left:-30px;width:200px;height:200px;background:radial-gradient(circle,rgba(255,107,44,.08),transparent 60%);pointer-events:none}\r\n.si-hero-top{display:flex;align-items:center;justify-content:space-between;position:relative;z-index:1;margin-bottom:20px}\r\n.si-hero-brand{display:flex;align-items:center;gap:14px}\r\n.si-hero-logo{font-size:28px;font-weight:900;color:#fff;letter-spacing:-.04em}\r\n.si-hero-logo em{font-style:normal;color:var(--si-orange)}\r\n.si-hero-badge{display:inline-flex;align-items:center;gap:5px;padding:5px 14px;background:rgba(255,107,44,.15);border:1px solid rgba(255,107,44,.3);border-radius:20px;font-size:10px;font-weight:700;color:var(--si-orange);text-transform:uppercase;letter-spacing:.08em}\r\n.si-hero-tools{display:flex;align-items:center;gap:8px}\r\n.si-hero-btn{display:inline-flex;align-items:center;gap:6px;padding:8px 16px;border:1px solid rgba(255,255,255,.15);border-radius:var(--si-rs);background:rgba(255,255,255,.06);color:rgba(255,255,255,.8);font-size:12px;font-weight:600;cursor:pointer;transition:all .2s;white-space:nowrap}\r\n.si-hero-btn:hover{border-color:rgba(255,255,255,.3);background:rgba(255,255,255,.12);color:#fff}\r\n.si-hero-btn svg{width:14px;height:14px}\r\n.si-hero-btn--accent{background:var(--si-orange);border-color:var(--si-orange);color:#fff}\r\n.si-hero-btn--accent:hover{background:var(--si-orange-hover);border-color:var(--si-orange-hover);box-shadow:0 4px 20px var(--si-orange-glow)}\r\n.si-hero-sub{font-size:12px;color:rgba(255,255,255,.4);margin-top:12px;position:relative;z-index:1}\r\n\r\n\/* \u2550\u2550\u2550 TOOLBAR \u2550\u2550\u2550 *\/\r\n#si-toolbar{display:flex;align-items:center;justify-content:space-between;padding:14px 32px;background:var(--si-white);border-bottom:1px solid var(--si-border);gap:12px;flex-wrap:wrap}\r\n.si-tb-left{display:flex;align-items:center;gap:12px}\r\n.si-tb-right{display:flex;align-items:center;gap:8px}\r\n\r\n\/* \u2550\u2550\u2550 LOGO UPLOAD \u2550\u2550\u2550 *\/\r\n.si-logo-zone{position:relative;width:170px;height:50px;border:2px dashed var(--si-border);border-radius:var(--si-rs);background:var(--si-bg);cursor:pointer;display:flex;align-items:center;justify-content:center;overflow:hidden;transition:all .25s;flex-shrink:0}\r\n.si-logo-zone:hover{border-color:var(--si-orange);background:var(--si-orange-light)}\r\n.si-logo-zone.has-logo{border-style:solid;border-color:var(--si-border);background:var(--si-white)}\r\n.si-logo-zone.has-logo:hover{border-color:var(--si-orange)}\r\n.si-logo-zone input[type=\"file\"]{position:absolute;inset:0;opacity:0;cursor:pointer;z-index:3}\r\n.si-logo-ph{display:flex;flex-direction:column;align-items:center;gap:2px;color:var(--si-text-3);pointer-events:none;z-index:1}\r\n.si-logo-ph svg{width:16px;height:16px;opacity:.5}\r\n.si-logo-ph span{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.06em}\r\n.si-logo-zone.has-logo .si-logo-ph{display:none}\r\n.si-logo-img{display:none;width:100%;height:100%;object-fit:contain;padding:6px 10px;pointer-events:none;z-index:2}\r\n.si-logo-zone.has-logo .si-logo-img{display:block}\r\n.si-logo-hover{position:absolute;inset:0;background:rgba(0,0,0,.55);display:none;align-items:center;justify-content:center;gap:8px;z-index:4;border-radius:6px}\r\n.si-logo-zone.has-logo:hover .si-logo-hover{display:flex}\r\n.si-logo-hover button{width:30px;height:30px;border:none;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .15s}\r\n.si-logo-hover button svg{width:14px;height:14px}\r\n.si-lb-chg{background:rgba(255,255,255,.2);color:#fff}.si-lb-chg:hover{background:rgba(255,255,255,.4)}\r\n.si-lb-rm{background:rgba(239,68,68,.5);color:#fff}.si-lb-rm:hover{background:rgba(239,68,68,.8)}\r\n\r\n\/* \u2550\u2550\u2550 BUTTONS \u2550\u2550\u2550 *\/\r\n.si-btn{display:inline-flex;align-items:center;gap:6px;padding:9px 18px;border:1px solid var(--si-border);border-radius:var(--si-rs);background:var(--si-white);color:var(--si-text);font-size:13px;font-weight:600;cursor:pointer;transition:all .2s;white-space:nowrap}\r\n.si-btn:hover{border-color:var(--si-orange);color:var(--si-orange);transform:translateY(-1px)}\r\n.si-btn:active{transform:translateY(0)}\r\n.si-btn svg{width:15px;height:15px;flex-shrink:0}\r\n.si-btn--orange{background:var(--si-orange);border-color:var(--si-orange);color:#fff}\r\n.si-btn--orange:hover{background:var(--si-orange-hover);color:#fff;box-shadow:0 4px 16px var(--si-orange-glow)}\r\n.si-btn--danger{background:var(--si-red-light);border-color:transparent;color:var(--si-red)}\r\n.si-btn--danger:hover{background:rgba(239,68,68,.15);border-color:var(--si-red)}\r\n.si-btn--ghost{background:transparent;border-style:dashed;color:var(--si-text-3)}\r\n.si-btn--ghost:hover{color:var(--si-orange);border-color:var(--si-orange);background:var(--si-orange-light)}\r\n\r\n\/* \u2550\u2550\u2550 TABS \u2550\u2550\u2550 *\/\r\n.si-card-hd{display:flex;width:100%;border-bottom:1px solid var(--si-border)}\r\n.si-tab{flex:1;padding:18px 28px;border:none;background:var(--si-bg);color:var(--si-text-3);font-size:15px;font-weight:800;text-transform:uppercase;letter-spacing:.12em;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);position:relative;text-align:center;border-bottom:3px solid transparent}\r\n.si-tab:hover:not(.on){color:var(--si-text-2);background:rgba(255,107,44,.03)}\r\n.si-tab.on{background:var(--si-white);color:var(--si-orange);border-bottom-color:var(--si-orange)}\r\n.si-tab.on::after{content:'';position:absolute;bottom:-3px;left:50%;transform:translateX(-50%);width:40px;height:3px;background:var(--si-orange);border-radius:3px 3px 0 0;box-shadow:0 0 12px var(--si-orange-glow)}\r\n.si-tab-icon{display:block;margin:0 auto 6px;font-size:20px;opacity:.4;transition:all .3s}\r\n.si-tab.on .si-tab-icon{opacity:1;transform:scale(1.1)}\r\n\r\n\/* \u2550\u2550\u2550 REF \u2550\u2550\u2550 *\/\r\n.si-ref-inp{background:var(--si-bg);border:1.5px solid var(--si-border);border-radius:var(--si-rs);padding:8px 14px;font-size:13px;color:var(--si-text);width:160px;font-weight:700;font-family:var(--si-mono);transition:all .2s}\r\n.si-ref-inp:focus{outline:none;border-color:var(--si-orange);box-shadow:0 0 0 3px var(--si-orange-light)}\r\n\r\n\/* \u2550\u2550\u2550 CARD \u2550\u2550\u2550 *\/\r\n#si-body{padding:0}\r\n.si-card{background:var(--si-white);margin:24px;border-radius:var(--si-r);box-shadow:var(--si-shadow);overflow:hidden}\r\n\r\n\/* \u2550\u2550\u2550 SECTIONS \u2550\u2550\u2550 *\/\r\n.si-sec{padding:28px;border-bottom:1px solid var(--si-border)}.si-sec:last-child{border-bottom:none}\r\n.si-sec-title{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.1em;color:var(--si-text-2);margin-bottom:18px;display:flex;align-items:center;gap:10px}\r\n.si-sec-title::before{content:'';width:4px;height:16px;background:var(--si-orange);border-radius:3px;flex-shrink:0}\r\n\r\n\/* \u2550\u2550\u2550 FORM \u2550\u2550\u2550 *\/\r\n.si-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px 24px}.si-grid .si-full{grid-column:1\/-1}\r\n.si-field{display:flex;flex-direction:column;gap:5px}\r\n.si-field label{font-size:10px;font-weight:700;color:var(--si-text-3);text-transform:uppercase;letter-spacing:.08em}\r\n.si-field input,.si-field textarea{background:var(--si-bg);border:1.5px solid transparent;border-radius:var(--si-rs);padding:11px 14px;font-size:13px;color:var(--si-text);transition:all .2s;width:100%}\r\n.si-field input:hover,.si-field textarea:hover{border-color:var(--si-border);background:var(--si-white)}\r\n.si-field input:focus,.si-field textarea:focus{outline:none;border-color:var(--si-orange);background:var(--si-white);box-shadow:0 0 0 3px var(--si-orange-light)}\r\n.si-field input::placeholder{color:var(--si-text-4)}\r\n.si-field textarea{resize:vertical;min-height:60px}\r\n\r\n.si-add-field{display:inline-flex;align-items:center;gap:5px;padding:7px 16px;background:transparent;border:1.5px dashed var(--si-border);border-radius:var(--si-rs);color:var(--si-text-3);font-size:12px;font-weight:600;cursor:pointer;transition:all .2s;margin-top:10px}\r\n.si-add-field:hover{border-color:var(--si-orange);color:var(--si-orange);background:var(--si-orange-light)}\r\n\r\n.si-field-wrap{position:relative;display:flex;flex-direction:column;gap:5px;animation:siFadeIn .25s ease}\r\n.si-field-wrap .si-field-rm{position:absolute;top:0;right:0;width:24px;height:24px;border:none;border-radius:6px;background:transparent;color:var(--si-text-4);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .15s;opacity:0}\r\n.si-field-wrap:hover .si-field-rm{opacity:1}\r\n.si-field-wrap .si-field-rm:hover{background:var(--si-red-light);color:var(--si-red)}\r\n@keyframes siFadeIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}\r\n\r\n\/* \u2550\u2550\u2550 TABLE \u2550\u2550\u2550 *\/\r\n.si-tbl-wrap{overflow-x:auto}\r\n.si-tbl{width:100%;border-collapse:collapse;font-size:13px}\r\n.si-tbl thead th{background:#faf9f7;padding:12px 14px;text-align:left;font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:var(--si-text-3);border-bottom:2px solid var(--si-border);white-space:nowrap}\r\n.si-tbl thead th.si-n{text-align:right}\r\n.si-tbl thead th.si-act{text-align:center;width:44px}\r\n.si-tbl tbody td{padding:12px 14px;border-bottom:1px solid var(--si-border);vertical-align:middle}\r\n.si-tbl tbody td.si-n{text-align:right;font-variant-numeric:tabular-nums}\r\n.si-tbl tbody td.si-act{text-align:center;width:44px}\r\n.si-tbl tbody tr{transition:background .15s}\r\n.si-tbl tbody tr:hover{background:rgba(255,107,44,.02)}\r\n.si-tbl .si-row-tot{font-weight:700;text-align:right;color:var(--si-text);font-variant-numeric:tabular-nums;font-family:var(--si-mono);font-size:12px}\r\n.si-tbl [contenteditable]{padding:6px 8px;border-radius:6px;border:1.5px solid transparent;transition:all .15s;min-width:40px}\r\n.si-tbl [contenteditable]:hover{border-color:var(--si-border);background:var(--si-bg)}\r\n.si-tbl [contenteditable]:focus{border-color:var(--si-orange);outline:none;background:var(--si-white);box-shadow:0 0 0 3px var(--si-orange-light)}\r\n.si-ph:empty::before{content:attr(data-ph);color:var(--si-text-4);font-style:italic}\r\n\r\n\/* TVA SELECT tunisien *\/\r\n.si-tva-sel{background:var(--si-bg);border:1.5px solid transparent;border-radius:6px;padding:7px 10px;font-size:12px;color:var(--si-text);font-family:var(--si-mono);font-weight:600;cursor:pointer;transition:all .15s;min-width:72px}\r\n.si-tva-sel:hover{border-color:var(--si-border);background:var(--si-white)}\r\n.si-tva-sel:focus{outline:none;border-color:var(--si-orange);box-shadow:0 0 0 3px var(--si-orange-light)}\r\n.si-tva-sel option{background:var(--si-white);color:var(--si-text);padding:6px}\r\n\r\n.si-del{width:30px;height:30px;border:none;border-radius:8px;background:transparent;color:var(--si-text-4);font-size:18px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:all .15s}\r\n.si-del:hover{background:var(--si-red-light);color:var(--si-red)}\r\n.si-add-row{padding:16px 28px;border-bottom:1px solid var(--si-border)}\r\n\r\n\/* \u2550\u2550\u2550 TOTALS \u2550\u2550\u2550 *\/\r\n.si-totals{display:flex;gap:28px;padding:28px;border-bottom:1px solid var(--si-border);align-items:flex-start}\r\n.si-tva-bk{flex:1;min-width:200px}\r\n.si-tva-tbl{width:100%;border-collapse:collapse;font-size:12px}\r\n.si-tva-tbl th{background:#faf9f7;padding:10px 14px;text-align:left;font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:var(--si-text-3);border-bottom:2px solid var(--si-border)}\r\n.si-tva-tbl th.si-n{text-align:right}\r\n.si-tva-tbl td{padding:10px 14px;border-bottom:1px solid var(--si-border);font-variant-numeric:tabular-nums;font-family:var(--si-mono);font-size:12px}\r\n.si-tva-tbl td.si-n{text-align:right;font-weight:500}\r\n.si-sum{width:300px;flex-shrink:0}\r\n.si-sum-row{display:flex;justify-content:space-between;align-items:center;padding:10px 0;font-size:13px}\r\n.si-sum-lbl{color:var(--si-text-2);font-weight:600}\r\n.si-sum-val{font-weight:700;font-variant-numeric:tabular-nums;color:var(--si-text);font-family:var(--si-mono);font-size:13px}\r\n.si-sum-hr{border:none;height:1px;background:var(--si-border);margin:4px 0}\r\n\r\n.si-timbre-btn{display:inline-flex;align-items:center;gap:6px;padding:7px 16px;background:transparent;border:1.5px dashed var(--si-border);border-radius:var(--si-rs);color:var(--si-text-3);font-size:12px;font-weight:600;cursor:pointer;transition:all .2s;margin-top:8px}\r\n.si-timbre-btn:hover{border-color:var(--si-amber);color:var(--si-amber);background:var(--si-amber-light)}\r\n.si-timbre-btn.on{border-style:solid;border-color:var(--si-green);color:var(--si-green);background:var(--si-green-light);cursor:default}\r\n.si-timbre-row{display:none}.si-timbre-row.show{display:flex}\r\n.si-timbre-row .si-sum-lbl{color:var(--si-amber);font-weight:700}\r\n.si-timbre-row .si-sum-val{color:var(--si-amber);font-weight:800}\r\n.si-timbre-x{width:20px;height:20px;border:none;border-radius:4px;background:transparent;color:var(--si-text-3);font-size:14px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:all .15s;margin-left:4px}\r\n.si-timbre-x:hover{background:var(--si-red-light);color:var(--si-red)}\r\n\r\n.si-grand{padding:16px 20px 10px;background:linear-gradient(135deg,var(--si-orange-light),rgba(255,107,44,.04));margin:10px -20px 0;border-radius:var(--si-rm);border:1.5px solid rgba(255,107,44,.15)}\r\n.si-grand .si-sum-lbl{font-size:16px;font-weight:800;color:var(--si-text)}\r\n.si-grand .si-sum-val{font-size:22px;font-weight:800;color:var(--si-orange);font-family:var(--si-mono)}\r\n\r\n\/* \u2550\u2550\u2550 NOTES \u2550\u2550\u2550 *\/\r\n.si-notes textarea{width:100%;background:var(--si-bg);border:1.5px solid transparent;border-radius:var(--si-rs);padding:14px 16px;font-size:13px;color:var(--si-text);resize:vertical;min-height:80px;font-family:var(--si-font);transition:all .2s}\r\n.si-notes textarea:hover{border-color:var(--si-border);background:var(--si-white)}\r\n.si-notes textarea:focus{outline:none;border-color:var(--si-orange);background:var(--si-white);box-shadow:0 0 0 3px var(--si-orange-light)}\r\n.si-notes textarea::placeholder{color:var(--si-text-4)}\r\n\r\n\/* \u2550\u2550\u2550 FOOTER \u2550\u2550\u2550 *\/\r\n.si-foot-grid{display:grid;grid-template-columns:1fr 1fr;gap:24px}\r\n.si-foot-block h4{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.1em;color:var(--si-text-3);margin-bottom:12px;display:flex;align-items:center;gap:8px}\r\n.si-foot-block h4::before{content:'';width:4px;height:14px;background:var(--si-orange);border-radius:3px}\r\n.si-foot-block [contenteditable]{padding:4px 8px;border:1.5px dashed transparent;border-radius:6px;transition:all .15s;font-size:13px;color:var(--si-text-2);line-height:1.9}\r\n.si-foot-block [contenteditable]:hover{border-color:var(--si-border);background:var(--si-bg)}\r\n.si-foot-block [contenteditable]:focus{border-color:var(--si-orange);outline:none;background:var(--si-white);box-shadow:0 0 0 3px var(--si-orange-light)}\r\n\r\n.si-watermark{text-align:center;padding:18px;font-size:11px;color:var(--si-text-3);border-top:1px solid var(--si-border);background:#faf9f7;font-weight:500}\r\n.si-watermark a{color:var(--si-orange);text-decoration:none;font-weight:700}\r\n\r\n\/* \u2550\u2550\u2550 OVERLAY \u2550\u2550\u2550 *\/\r\n#si-pdf-ov{position:absolute;inset:0;background:rgba(255,255,255,.94);backdrop-filter:blur(10px);display:none;flex-direction:column;align-items:center;justify-content:center;gap:16px;z-index:100;border-radius:var(--si-r)}\r\n#si-pdf-ov.on{display:flex}\r\n.si-spinner{width:36px;height:36px;border:3px solid var(--si-border);border-top-color:var(--si-orange);border-radius:50%;animation:si-spin .7s linear infinite}\r\n@keyframes si-spin{to{transform:rotate(360deg)}}\r\n#si-pdf-ov p{font-size:13px;color:var(--si-text-3);font-weight:600}\r\n\r\n\/* \u2550\u2550\u2550 TOAST \u2550\u2550\u2550 *\/\r\n#si-toast{position:fixed;bottom:32px;right:32px;padding:14px 24px;background:var(--si-dark);border:none;border-radius:var(--si-rm);color:#fff;font-size:13px;font-weight:600;box-shadow:var(--si-shadow-lg);transform:translateY(80px);opacity:0;transition:all .35s cubic-bezier(.34,1.56,.64,1);z-index:9999;pointer-events:none}\r\n#si-toast.on{transform:translateY(0);opacity:1}\r\n\r\n.si-np{}\r\n@media print{.si-np{display:none!important}}\r\n\r\n@media(max-width:720px){\r\n    .si-card{margin:14px}.si-sec{padding:20px 18px}\r\n    .si-grid{grid-template-columns:1fr}\r\n    .si-totals{flex-direction:column}.si-sum{width:100%}\r\n    .si-foot-grid{grid-template-columns:1fr}\r\n    #si-hero{padding:24px 18px 20px}\r\n    .si-hero-top{flex-direction:column;gap:12px;align-items:flex-start}\r\n    .si-hero-tools{flex-wrap:wrap}\r\n    #si-toolbar{padding:12px 18px}\r\n    .si-logo-zone{width:130px;height:42px}\r\n    .si-tab{padding:14px 16px;font-size:13px;letter-spacing:.06em}\r\n    .si-tab-icon{font-size:16px}\r\n}\r\n<\/style>\r\n\r\n<script>\r\n(function(){\r\n'use strict';\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   CONFIG \u2014 TUNISIE 100%\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nconst STORAGE='si_tn_invoice';\r\nconst DEVISE='DT';\r\nconst DECIMALES=3;\r\nconst SYMBOLE=' DT';\r\nconst TIMBRE_FISCAL=1.000;\r\n\r\n\/* Bar\u00e8me TVA tunisien officiel *\/\r\nconst TVA_TUNISIE=[\r\n    {val:'19',label:'19% \u2014 Taux normal'},\r\n    {val:'13',label:'13% \u2014 Taux interm\u00e9diaire'},\r\n    {val:'7', label:'7% \u2014 Taux r\u00e9duit'},\r\n    {val:'0', label:'0% \u2014 Exon\u00e9r\u00e9'}\r\n];\r\n\r\nlet logoData=null,timbreOn=false;\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   HELPERS\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nfunction fmt(n){return n.toFixed(DECIMALES)+SYMBOLE}\r\nfunction pN(t){if(!t)return 0;let s=t.replace(\/[^\\d,.\\-]\/g,'').replace(',','.');let v=parseFloat(s);return isNaN(v)?0:v}\r\nfunction qs(s,c){return(c||document).querySelector(s)}\r\nfunction qa(s,c){return(c||document).querySelectorAll(s)}\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   SVG ICONS\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nconst I={\r\npdf:'<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"\/><polyline points=\"14 2 14 8 20 8\"\/><line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"\/><line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"\/><\/svg>',\r\nsave:'<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z\"\/><polyline points=\"17 21 17 13 7 13 7 21\"\/><polyline points=\"7 3 7 8 15 8\"\/><\/svg>',\r\nload:'<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polyline points=\"1 4 1 10 7 10\"\/><path d=\"M3.51 15a9 9 0 1 0 2.13-9.36L1 10\"\/><\/svg>',\r\ntrash:'<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polyline points=\"3 6 5 6 21 6\"\/><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\"\/><\/svg>',\r\nplus:'<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"\/><line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"\/><\/svg>',\r\nup:'<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"\/><polyline points=\"17 8 12 3 7 8\"\/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"\/><\/svg>',\r\nedit:'<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"\/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"\/><\/svg>',\r\nx:'<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"\/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"\/><\/svg>',\r\nstamp:'<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"2\" y=\"7\" width=\"20\" height=\"14\" rx=\"2\"\/><path d=\"M16 7V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v3\"\/><\/svg>',\r\ntn:'<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\"\/><path d=\"M2 12h20\"\/><\/svg>',\r\n};\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   STATE\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nlet cfc=0,dfc=0;\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   BUILD TVA OPTIONS\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nfunction tvaOptions(selected){\r\n    return TVA_TUNISIE.map(t=>`<option value=\"${t.val}\" ${t.val===(selected!==undefined?selected:'19')?'selected':''}>${t.label}<\/option>`).join('');\r\n}\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   BUILD UI\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nconst root=document.getElementById('si-app');\r\n\r\nfunction build(){\r\n    const t=new Date(),d=new Date();d.setDate(d.getDate()+30);\r\n    const td=t.toLocaleDateString('fr-FR'),dd=d.toLocaleDateString('fr-FR');\r\n\r\n    root.innerHTML=`\r\n    <div id=\"si-pdf-ov\"><div class=\"si-spinner\"><\/div><p>Generation du PDF en cours\u2026<\/p><\/div>\r\n\r\n    <!-- HERO BANNER -->\r\n    <div id=\"si-hero\" class=\"si-np\">\r\n        <div class=\"si-hero-top\">\r\n            <div class=\"si-hero-brand\">\r\n                <div class=\"si-hero-logo\">Shop<em>ini<\/em><\/div>\r\n                <div class=\"si-hero-badge\">\ud83c\uddf9\ud83c\uddf3 Marche Tunisien<\/div>\r\n            <\/div>\r\n            <div class=\"si-hero-tools\">\r\n                <button class=\"si-hero-btn si-hero-btn--accent\" id=\"b-pdf\">${I.pdf} Telecharger PDF<\/button>\r\n                <button class=\"si-hero-btn\" id=\"b-save\">${I.save}<\/button>\r\n                <button class=\"si-hero-btn\" id=\"b-load\">${I.load}<\/button>\r\n                <button class=\"si-hero-btn\" id=\"b-reset\" style=\"color:rgba(239,68,68,.7)\">${I.trash}<\/button>\r\n            <\/div>\r\n        <\/div>\r\n        <div class=\"si-hero-sub\">Generateur de factures et devis gratuit Tunisie \u2014 conforme a la reglementation tunisienne \u2014 toutes les montants en Dinars Tunisiens (DT)<\/div>\r\n    <\/div>\r\n\r\n    <!-- TOOLBAR -->\r\n    <div id=\"si-toolbar\" class=\"si-np\">\r\n        <div class=\"si-tb-left\">\r\n            <div class=\"si-logo-zone\" id=\"si-lzone\">\r\n                <input type=\"file\" accept=\"image\/*\" id=\"si-linput\">\r\n                <img class=\"si-logo-img\" id=\"si-limg\" alt=\"\">\r\n                <div class=\"si-logo-ph\">${I.up}<span>Logo entreprise<\/span><\/div>\r\n                <div class=\"si-logo-hover\">\r\n                    <button class=\"si-lb-chg\" id=\"si-lchg\" title=\"Changer\">${I.edit}<\/button>\r\n                    <button class=\"si-lb-rm\" id=\"si-lrm\" title=\"Supprimer\">${I.x}<\/button>\r\n                <\/div>\r\n            <\/div>\r\n            <span style=\"font-size:11px;color:var(--si-text-3);font-weight:500\">Logo de votre societe (apparaitra sur le PDF)<\/span>\r\n        <\/div>\r\n        <div class=\"si-tb-right\">\r\n            <span style=\"font-size:11px;color:var(--si-text-3);font-weight:600\">N\u00b0 Document<\/span>\r\n            <input type=\"text\" class=\"si-ref-inp\" id=\"i-ref\" value=\"FAC 0001\">\r\n        <\/div>\r\n    <\/div>\r\n\r\n    <!-- CARD -->\r\n    <div id=\"si-body\">\r\n        <div class=\"si-card\">\r\n\r\n            <!-- TABS -->\r\n            <div class=\"si-card-hd si-np\">\r\n                <button class=\"si-tab\" data-t=\"Devis\"><span class=\"si-tab-icon\">\ud83d\udccb<\/span>DEVIS<\/button>\r\n                <button class=\"si-tab on\" data-t=\"Facture\"><span class=\"si-tab-icon\">\ud83d\udcc4<\/span>FACTURE<\/button>\r\n            <\/div>\r\n\r\n            <!-- CLIENT -->\r\n            <div class=\"si-sec\">\r\n                <div class=\"si-sec-title\">Details du client<\/div>\r\n                <div class=\"si-grid\">\r\n                    <div class=\"si-field\"><label>Raison sociale<\/label><input type=\"text\" id=\"i-cn\" placeholder=\"Nom de la societe cliente\"><\/div>\r\n                    <div class=\"si-field\"><label>Matricule fiscal (MF)<\/label><input type=\"text\" id=\"i-mf\" placeholder=\"1234567\/A\/M\/000\"><\/div>\r\n                    <div class=\"si-field si-full\"><label>Adresse<\/label><input type=\"text\" id=\"i-ca\" placeholder=\"Adresse complete du client\"><\/div>\r\n                    <div id=\"i-cextra\"><\/div>\r\n                <\/div>\r\n                <button class=\"si-add-field si-np\" id=\"b-acf\">${I.plus} Ajouter un champ<\/button>\r\n            <\/div>\r\n\r\n            <!-- DOCUMENT -->\r\n            <div class=\"si-sec\">\r\n                <div class=\"si-sec-title\">Details du document<\/div>\r\n                <div class=\"si-grid\">\r\n                    <div class=\"si-field\"><label>Date d'emission<\/label><input type=\"text\" id=\"i-dc\" value=\"${td}\"><\/div>\r\n                    <div class=\"si-field\"><label>Date d'echeance<\/label><input type=\"text\" id=\"i-dd\" value=\"${dd}\"><\/div>\r\n                    <div id=\"i-dextra\"><\/div>\r\n                <\/div>\r\n                <button class=\"si-add-field si-np\" id=\"b-adf\">${I.plus} Ajouter un champ<\/button>\r\n            <\/div>\r\n\r\n            <!-- LIGNES -->\r\n            <div class=\"si-sec\" style=\"padding-bottom:0\"><div class=\"si-sec-title\">Lignes<\/div><\/div>\r\n            <div class=\"si-tbl-wrap\">\r\n                <table class=\"si-tbl\" id=\"si-tbl\">\r\n                    <thead><tr>\r\n                        <th>Reference<\/th><th>Designation<\/th>\r\n                        <th class=\"si-n\">Qte<\/th><th class=\"si-n\">Prix unit. HT (DT)<\/th>\r\n                        <th>TVA<\/th><th class=\"si-n\">Total HT (DT)<\/th>\r\n                        <th class=\"si-act si-np\"><\/th>\r\n                    <\/tr><\/thead>\r\n                    <tbody id=\"si-tb\">\r\n                        <tr>\r\n                            <td contenteditable=\"true\" class=\"si-ph\" data-ph=\"REF-001\">REF-001<\/td>\r\n                            <td contenteditable=\"true\" class=\"si-ph\" data-ph=\"Produit \/ Service\">Produit \/ Service<\/td>\r\n                            <td class=\"si-n\" contenteditable=\"true\">1<\/td>\r\n                            <td class=\"si-n\" contenteditable=\"true\">0,000<\/td>\r\n                            <td><select class=\"si-tva-sel\">${tvaOptions('19')}<\/select><\/td>\r\n                            <td class=\"si-row-tot\">0,000 DT<\/td>\r\n                            <td class=\"si-act si-np\"><button class=\"si-del\" title=\"Supprimer\">&times;<\/button><\/td>\r\n                        <\/tr>\r\n                    <\/tbody>\r\n                <\/table>\r\n            <\/div>\r\n            <div class=\"si-add-row si-np\"><button class=\"si-btn si-btn--ghost\" id=\"b-arow\">${I.plus} Ajouter une ligne<\/button><\/div>\r\n\r\n            <!-- TOTAUX -->\r\n            <div class=\"si-totals\">\r\n                <div class=\"si-tva-bk\">\r\n                    <table class=\"si-tva-tbl\"><thead><tr><th>TVA<\/th><th class=\"si-n\">Base HT<\/th><th class=\"si-n\">Montant TVA<\/th><\/tr><\/thead><tbody id=\"si-tva-tb\"><\/tbody><\/table>\r\n                <\/div>\r\n                <div class=\"si-sum\">\r\n                    <div class=\"si-sum-row\"><span class=\"si-sum-lbl\">Total HT<\/span><span class=\"si-sum-val\" id=\"v-ht\">0,000 DT<\/span><\/div>\r\n                    <hr class=\"si-sum-hr\">\r\n                    <div class=\"si-sum-row\"><span class=\"si-sum-lbl\">Total TVA<\/span><span class=\"si-sum-val\" id=\"v-tva\">0,000 DT<\/span><\/div>\r\n                    <div class=\"si-sum-row si-timbre-row\" id=\"r-timbre\"><span class=\"si-sum-lbl\">Timbre fiscal<\/span><span class=\"si-sum-val\" id=\"v-timbre\">${fmt(TIMBRE_FISCAL)}<\/span><\/div>\r\n                    <div class=\"si-np\" style=\"margin-top:8px\"><button class=\"si-timbre-btn\" id=\"b-timbre\">${I.stamp} Ajouter le timbre fiscal (${fmt(TIMBRE_FISCAL)})<\/button><\/div>\r\n                    <hr class=\"si-sum-hr\">\r\n                    <div class=\"si-sum-row si-grand\"><span class=\"si-sum-lbl\">Net a payer<\/span><span class=\"si-sum-val\" id=\"v-ttc\">0,000 DT<\/span><\/div>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <!-- NOTES -->\r\n            <div class=\"si-sec\">\r\n                <div class=\"si-sec-title\">Notes<\/div>\r\n                <div class=\"si-notes\"><textarea id=\"i-notes\" placeholder=\"Conditions de paiement, remarques\u2026\">Reglement a 30 jours. En cas de retard, penalites de retard selon la legislation tunisienne en vigueur.<\/textarea><\/div>\r\n            <\/div>\r\n\r\n            <!-- ENTREPRISE & BANQUE -->\r\n            <div class=\"si-sec\">\r\n                <div class=\"si-foot-grid\">\r\n                    <div class=\"si-foot-block\">\r\n                        <h4>Informations de l'entreprise<\/h4>\r\n                        <div contenteditable=\"true\" class=\"si-ph\" id=\"i-cinfo\" data-ph=\"Nom, adresse, MF, email, tel\">Societe XYZ SARL<br>9 Avenue Habib Bourguiba, 1000 Tunis<br>MF: 1234567\/A\/M\/000<br>RIB: 00000000000000000000<br>contact@exemple.tn<br>+216 71 000 000<\/div>\r\n                    <\/div>\r\n                    <div class=\"si-foot-block\">\r\n                        <h4>Coordonnees bancaires<\/h4>\r\n                        <div class=\"si-field\" style=\"margin-bottom:10px\"><label>Banque<\/label><input type=\"text\" id=\"i-bank\" placeholder=\"Ex: BIAT, Amen Bank, STB...\"><\/div>\r\n                        <div class=\"si-field\" style=\"margin-bottom:10px\"><label>RIB<\/label><input type=\"text\" id=\"i-rib\" placeholder=\"20 chiffres\"><\/div>\r\n                        <div class=\"si-field\"><label>IBAN<\/label><input type=\"text\" id=\"i-iban\" placeholder=\"TN59 0000 0000 0000 0000 0000\"><\/div>\r\n                    <\/div>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <div class=\"si-watermark si-np\">Outil gratuit pour le marche tunisien \u2014 <a href=\"#\">Shopini.tn<\/a><\/div>\r\n        <\/div>\r\n    <\/div>`;\r\n\r\n    const tEl=document.createElement('div');tEl.id='si-toast';document.body.appendChild(tEl);\r\n    bind();recalc();\r\n}\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   CALCULATIONS\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nfunction recalc(){\r\n    const tb=document.getElementById('si-tb');if(!tb)return;\r\n    const rows=tb.querySelectorAll('tr');let ht=0;const bk={};\r\n\r\n    rows.forEach(r=>{\r\n        const c=r.children;if(c.length<6)return;\r\n        const q=pN(c[2].textContent);\r\n        const p=pN(c[3].textContent);\r\n        const sel=c[4].querySelector('select');\r\n        const rate=sel?parseFloat(sel.value):0;\r\n        const ln=q*p;ht+=ln;\r\n        c[5].textContent=fmt(ln);\r\n        if(!bk[rate])bk[rate]={b:0,m:0};\r\n        bk[rate].b+=ln;\r\n        bk[rate].m+=ln*rate\/100;\r\n    });\r\n\r\n    const vtb=document.getElementById('si-tva-tb');\r\n    if(vtb){\r\n        vtb.innerHTML='';\r\n        let tva=0;\r\n        Object.keys(bk).sort((a,b)=>a-b).forEach(rate=>{\r\n            const b=bk[rate];tva+=b.m;\r\n            const tr=document.createElement('tr');\r\n            const label=TVA_TUNISIE.find(t=>t.val==rate);\r\n            tr.innerHTML=`<td>${label?label.label:rate+'%'}<\/td><td class=\"si-n\">${fmt(b.b)}<\/td><td class=\"si-n\">${fmt(b.m)}<\/td>`;\r\n            vtb.appendChild(tr);\r\n        });\r\n        const tv=timbreOn?TIMBRE_FISCAL:0;\r\n        document.getElementById('v-ht').textContent=fmt(ht);\r\n        document.getElementById('v-tva').textContent=fmt(tva);\r\n        document.getElementById('v-ttc').textContent=fmt(ht+tva+tv);\r\n    }\r\n}\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   ROWS\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nfunction addRow(d){\r\n    d=d||{};\r\n    const tr=document.createElement('tr');\r\n    tr.innerHTML=`\r\n        <td contenteditable=\"true\" class=\"si-ph\" data-ph=\"REF-001\">${d.r||''}<\/td>\r\n        <td contenteditable=\"true\" class=\"si-ph\" data-ph=\"Produit \/ Service\">${d.d||''}<\/td>\r\n        <td class=\"si-n\" contenteditable=\"true\">${d.q||'1'}<\/td>\r\n        <td class=\"si-n\" contenteditable=\"true\">${d.p||'0,000'}<\/td>\r\n        <td><select class=\"si-tva-sel\">${tvaOptions(d.v!==undefined?d.v:'19')}<\/select><\/td>\r\n        <td class=\"si-row-tot\">0,000 DT<\/td>\r\n        <td class=\"si-act si-np\"><button class=\"si-del\" title=\"Supprimer\">&times;<\/button><\/td>`;\r\n    document.getElementById('si-tb').appendChild(tr);\r\n    wireRow(tr);\r\n    tr.style.opacity='0';tr.style.transform='translateY(-8px)';\r\n    requestAnimationFrame(()=>{tr.style.transition='all .25s';tr.style.opacity='1';tr.style.transform='none'});\r\n    if(!d.d)tr.querySelectorAll('[contenteditable]')[1]?.focus();\r\n    recalc();\r\n}\r\n\r\nfunction delRow(b){\r\n    const tr=b.closest('tr');\r\n    tr.style.transition='all .2s';tr.style.opacity='0';tr.style.transform='translateX(16px)';\r\n    setTimeout(()=>{tr.remove();recalc()},200);\r\n}\r\n\r\nfunction wireRow(tr){\r\n    tr.querySelectorAll('[contenteditable]').forEach(el=>{\r\n        el.addEventListener('input',recalc);\r\n        el.addEventListener('keyup',recalc);\r\n        el.addEventListener('paste',()=>setTimeout(recalc,10));\r\n    });\r\n    const sel=tr.querySelector('.si-tva-sel');\r\n    if(sel)sel.addEventListener('change',recalc);\r\n    const del=tr.querySelector('.si-del');\r\n    if(del)del.addEventListener('click',()=>delRow(del));\r\n}\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   TIMBRE FISCAL\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nfunction toggleTimbre(){if(timbreOn)removeTimbre();else addTimbre()}\r\nfunction addTimbre(){\r\n    timbreOn=true;\r\n    const btn=document.getElementById('b-timbre');\r\n    btn.classList.add('on');\r\n    btn.innerHTML=I.stamp+' Timbre fiscal : '+fmt(TIMBRE_FISCAL)+' <button class=\"si-timbre-x\" id=\"b-tx\" title=\"Retirer\">&times;<\/button>';\r\n    document.getElementById('b-tx').addEventListener('click',e=>{e.stopPropagation();removeTimbre()});\r\n    document.getElementById('r-timbre').classList.add('show');\r\n    recalc();toast('Timbre fiscal ajoute : '+fmt(TIMBRE_FISCAL));\r\n}\r\nfunction removeTimbre(){\r\n    timbreOn=false;\r\n    const btn=document.getElementById('b-timbre');\r\n    btn.classList.remove('on');\r\n    btn.innerHTML=I.stamp+' Ajouter le timbre fiscal ('+fmt(TIMBRE_FISCAL)+')';\r\n    document.getElementById('r-timbre').classList.remove('show');\r\n    recalc();toast('Timbre fiscal retire');\r\n}\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   LOGO\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nfunction handleLogo(f){\r\n    if(!f||!f.type.startsWith('image\/')){toast('Selectionnez une image');return}\r\n    if(f.size>512000){toast('Image trop volumineuse (max 500 Ko)');return}\r\n    const rd=new FileReader();\r\n    rd.onload=e=>{logoData=e.target.result;applyLogo();toast('Logo charge')};\r\n    rd.readAsDataURL(f);\r\n}\r\nfunction applyLogo(){\r\n    const z=document.getElementById('si-lzone'),i=document.getElementById('si-limg');\r\n    if(logoData){i.src=logoData;z.classList.add('has-logo')}\r\n    else{i.src='';z.classList.remove('has-logo')}\r\n}\r\nfunction removeLogo(){logoData=null;applyLogo();document.getElementById('si-linput').value='';toast('Logo supprime')}\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   CUSTOM FIELDS\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nfunction addCustomField(cid,lbl){\r\n    const c=document.getElementById(cid),num=cid==='i-cextra'?++cfc:++dfc;\r\n    const w=document.createElement('div');w.className='si-field-wrap';\r\n    w.innerHTML=`<div class=\"si-field\"><label>${lbl} ${num}<\/label><input type=\"text\" placeholder=\"Champ personnalise\"><\/div><button class=\"si-field-rm\" title=\"Supprimer\">&times;<\/button>`;\r\n    w.querySelector('.si-field-rm').addEventListener('click',function(){\r\n        w.style.transition='all .2s';w.style.opacity='0';w.style.transform='translateX(10px)';\r\n        setTimeout(()=>w.remove(),200);toast('Champ supprime');\r\n    });\r\n    c.appendChild(w);w.querySelector('input').focus();\r\n}\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   EVENTS\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nfunction bind(){\r\n    qa('#si-tb tr').forEach(wireRow);\r\n    document.getElementById('b-arow').addEventListener('click',()=>addRow());\r\n\r\n    qa('.si-tab').forEach(t=>{\r\n        t.addEventListener('click',function(){\r\n            qa('.si-tab').forEach(x=>x.classList.remove('on'));\r\n            this.classList.add('on');\r\n            const ref=document.getElementById('i-ref');\r\n            ref.value=this.dataset.t==='Devis'?ref.value.replace('FAC','DEV'):ref.value.replace('DEV','FAC');\r\n        });\r\n    });\r\n\r\n    document.getElementById('b-acf').addEventListener('click',()=>addCustomField('i-cextra','Champ'));\r\n    document.getElementById('b-adf').addEventListener('click',()=>addCustomField('i-dextra','Champ'));\r\n    document.getElementById('b-timbre').addEventListener('click',toggleTimbre);\r\n    document.getElementById('b-pdf').addEventListener('click',genPDF);\r\n    document.getElementById('b-save').addEventListener('click',saveData);\r\n    document.getElementById('b-load').addEventListener('click',loadData);\r\n    document.getElementById('b-reset').addEventListener('click',resetData);\r\n\r\n    document.getElementById('si-linput').addEventListener('change',e=>{if(e.target.files[0])handleLogo(e.target.files[0])});\r\n    document.getElementById('si-lchg').addEventListener('click',e=>{e.stopPropagation();document.getElementById('si-linput').click()});\r\n    document.getElementById('si-lrm').addEventListener('click',e=>{e.stopPropagation();removeLogo()});\r\n    document.getElementById('si-lzone').addEventListener('click',function(e){if(this.classList.contains('has-logo')&&e.target===this)e.preventDefault()});\r\n}\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   PDF \u2014 TEMPLATE PRO TUNISIEN\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nfunction loadSc(src){return new Promise((ok,fail)=>{if(window.html2pdf)return ok();const s=document.createElement('script');s.src=src;s.onload=ok;s.onerror=fail;document.head.appendChild(s)})}\r\n\r\nfunction buildPDFTemplate(){\r\n    const docType=document.querySelector('.si-tab.on')?.dataset.t||'Facture';\r\n    const ref=document.getElementById('i-ref').value||'';\r\n    const cn=document.getElementById('i-cn').value||'';\r\n    const mf=document.getElementById('i-mf').value||'';\r\n    const ca=document.getElementById('i-ca').value||'';\r\n    const dc=document.getElementById('i-dc').value||'';\r\n    const dd=document.getElementById('i-dd').value||'';\r\n    const notes=document.getElementById('i-notes').value||'';\r\n    const ciHTML=document.getElementById('i-cinfo').innerHTML||'';\r\n    const bank=document.getElementById('i-bank').value||'';\r\n    const rib=document.getElementById('i-rib').value||'';\r\n    const iban=document.getElementById('i-iban').value||'';\r\n\r\n    let cfields='';\r\n    document.querySelectorAll('#i-cextra .si-field-wrap').forEach(w=>{\r\n        const lbl=w.querySelector('label')?.textContent||'';\r\n        const val=w.querySelector('input')?.value||'';\r\n        if(val)cfields+=`<div style=\"font-size:10px;color:#666;margin-top:2px\"><span style=\"color:#999;font-size:9px;text-transform:uppercase;letter-spacing:.06em\">${lbl}:<\/span> ${val}<\/div>`;\r\n    });\r\n    let dfields='';\r\n    document.querySelectorAll('#i-dextra .si-field-wrap').forEach(w=>{\r\n        const lbl=w.querySelector('label')?.textContent||'';\r\n        const val=w.querySelector('input')?.value||'';\r\n        if(val)dfields+=`<span style=\"margin-right:20px\"><span style=\"color:#999;font-size:9px;text-transform:uppercase;letter-spacing:.06em\">${lbl}:<\/span> <strong>${val}<\/strong><\/span>`;\r\n    });\r\n\r\n    let rowsHTML='';let rIdx=0;\r\n    document.querySelectorAll('#si-tb tr').forEach(r=>{\r\n        const c=r.children;if(c.length<6)return;\r\n        const bg=rIdx%2===1?'background:#fafaf8;':'';\r\n        const sel=c[4].querySelector('select');\r\n        const tvaLabel=sel?sel.options[sel.selectedIndex].text:'19%';\r\n        rowsHTML+=`<tr style=\"${bg}border-bottom:1px solid #eee\">\r\n            <td style=\"padding:10px 14px;font-size:11px;color:#555\">${c[0].textContent.trim()}<\/td>\r\n            <td style=\"padding:10px 14px;font-size:11px;font-weight:600\">${c[1].textContent.trim()}<\/td>\r\n            <td style=\"padding:10px 14px;text-align:right;font-size:11px;font-family:'Courier New',monospace\">${c[2].textContent.trim()}<\/td>\r\n            <td style=\"padding:10px 14px;text-align:right;font-size:11px;font-family:'Courier New',monospace\">${c[3].textContent.trim()}<\/td>\r\n            <td style=\"padding:10px 14px;text-align:center;font-size:10px;color:#888\">${tvaLabel.split('\u2014')[0].trim()}<\/td>\r\n            <td style=\"padding:10px 14px;text-align:right;font-size:11px;font-weight:700;font-family:'Courier New',monospace\">${c[5].textContent.trim()}<\/td>\r\n        <\/tr>`;\r\n        rIdx++;\r\n    });\r\n\r\n    const totHT=document.getElementById('v-ht').textContent;\r\n    const totTVA=document.getElementById('v-tva').textContent;\r\n    const totTTC=document.getElementById('v-ttc').textContent;\r\n\r\n    let tvaRows='';\r\n    document.querySelectorAll('#si-tva-tb tr').forEach(r=>{\r\n        const c=r.children;\r\n        tvaRows+=`<div style=\"display:flex;justify-content:space-between;padding:6px 0;font-size:10px;border-bottom:1px solid #f0f0f0\"><span style=\"color:#888\">${c[0].textContent}<\/span><span style=\"font-family:'Courier New',monospace;font-weight:600\">${c[1].textContent.trim()} \u2192 ${c[2].textContent.trim()}<\/span><\/div>`;\r\n    });\r\n\r\n    let timbreHTML='';\r\n    if(timbreOn)timbreHTML=`<div style=\"display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px solid #eee;font-size:11px\"><span style=\"color:#f59e0b;font-weight:600\">Timbre fiscal<\/span><span style=\"font-weight:700;color:#f59e0b;font-family:'Courier New',monospace\">${fmt(TIMBRE_FISCAL)}<\/span><\/div>`;\r\n\r\n    let logoHTML='';\r\n    if(logoData)logoHTML=`<img decoding=\"async\" src=\"${logoData}\" style=\"max-height:55px;max-width:180px;object-fit:contain;display:block;margin-bottom:12px\"\/>`;\r\n\r\n    const ciLines=ciHTML.split(\/<br\\s*\\\/?>\/i);\r\n    const coName=ciLines[0]||'';\r\n    const coDetails=ciLines.slice(1).join('<br>');\r\n\r\n    \/\/ Bank footer content\r\n    let bankHTML='';\r\n    if(bank)bankHTML+=`<div><strong style=\"color:#555\">Banque :<\/strong> ${bank}<\/div>`;\r\n    if(rib)bankHTML+=`<div><strong style=\"color:#555\">RIB :<\/strong> ${rib}<\/div>`;\r\n    if(iban)bankHTML+=`<div><strong style=\"color:#555\">IBAN :<\/strong> ${iban}<\/div>`;\r\n    if(!bank&&!rib&&!iban)bankHTML='<span style=\"color:#ccc\">\u2014<\/span>';\r\n\r\n    const div=document.createElement('div');\r\n    div.innerHTML=`\r\n    <div style=\"width:794px;min-height:1123px;padding:48px 56px;background:#fff;font-family:Arial,'Helvetica Neue',sans-serif;color:#1a1a1a;font-size:11px;line-height:1.5;box-sizing:border-box;position:relative\">\r\n\r\n        <!-- HEADER -->\r\n        <div style=\"display:flex;justify-content:space-between;align-items:flex-start;padding-bottom:22px;border-bottom:3px solid #ff6b2c;margin-bottom:30px\">\r\n            <div style=\"flex:1\">\r\n                ${logoHTML}\r\n                <div style=\"font-size:17px;font-weight:800;color:#1a1a1a;margin-bottom:6px;line-height:1.3\">${coName}<\/div>\r\n                <div style=\"font-size:10px;color:#777;line-height:1.8\">${coDetails}<\/div>\r\n            <\/div>\r\n            <div style=\"text-align:right;min-width:200px\">\r\n                <div style=\"font-size:30px;font-weight:900;color:#ff6b2c;text-transform:uppercase;letter-spacing:.06em;line-height:1\">${docType}<\/div>\r\n                <div style=\"margin-top:16px;font-size:11px;color:#555;line-height:2.2\">\r\n                    <div><span style=\"color:#aaa;font-size:9px;text-transform:uppercase;letter-spacing:.08em;display:inline-block;width:80px\">N\u00b0<\/span><strong style=\"font-family:'Courier New',monospace\">${ref}<\/strong><\/div>\r\n                    <div><span style=\"color:#aaa;font-size:9px;text-transform:uppercase;letter-spacing:.08em;display:inline-block;width:80px\">Emission<\/span><strong>${dc}<\/strong><\/div>\r\n                    <div><span style=\"color:#aaa;font-size:9px;text-transform:uppercase;letter-spacing:.08em;display:inline-block;width:80px\">Echeance<\/span><strong>${dd}<\/strong><\/div>\r\n                    ${dfields?`<div style=\"margin-top:4px\">${dfields}<\/div>`:''}\r\n                <\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <!-- CLIENT -->\r\n        <div style=\"background:#f9f9f7;border-left:4px solid #ff6b2c;padding:16px 20px;border-radius:0 8px 8px 0;margin-bottom:30px\">\r\n            <div style=\"font-size:9px;font-weight:700;color:#aaa;text-transform:uppercase;letter-spacing:.12em;margin-bottom:8px\">Destinataire<\/div>\r\n            <div style=\"font-size:15px;font-weight:700;color:#1a1a1a;margin-bottom:3px\">${cn||'\u2014'}<\/div>\r\n            ${mf?`<div style=\"font-size:10px;color:#888;margin-bottom:2px\"><span style=\"text-transform:uppercase;font-size:8px;letter-spacing:.06em;color:#aaa\">MF:<\/span> ${mf}<\/div>`:''}\r\n            <div style=\"font-size:11px;color:#666\">${ca||'\u2014'}<\/div>\r\n            ${cfields}\r\n        <\/div>\r\n\r\n        <!-- TABLE -->\r\n        <table style=\"width:100%;border-collapse:collapse;margin-bottom:30px\">\r\n            <thead><tr>\r\n                <th style=\"background:#1a1a1a;color:#fff;padding:12px 14px;text-align:left;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;border-radius:6px 0 0 0\">Ref.<\/th>\r\n                <th style=\"background:#1a1a1a;color:#fff;padding:12px 14px;text-align:left;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.08em\">Designation<\/th>\r\n                <th style=\"background:#1a1a1a;color:#fff;padding:12px 14px;text-align:right;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.08em\">Qte<\/th>\r\n                <th style=\"background:#1a1a1a;color:#fff;padding:12px 14px;text-align:right;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.08em\">P.U. HT<\/th>\r\n                <th style=\"background:#1a1a1a;color:#fff;padding:12px 14px;text-align:center;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.08em\">TVA<\/th>\r\n                <th style=\"background:#1a1a1a;color:#fff;padding:12px 14px;text-align:right;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;border-radius:0 6px 0 0\">Total HT<\/th>\r\n            <\/tr><\/thead>\r\n            <tbody>${rowsHTML}<\/tbody>\r\n        <\/table>\r\n\r\n        <!-- TOTALS -->\r\n        <div style=\"display:flex;gap:30px;margin-bottom:30px;align-items:flex-start\">\r\n            <div style=\"flex:1\">\r\n                ${tvaRows?`<div style=\"font-size:9px;font-weight:700;color:#aaa;text-transform:uppercase;letter-spacing:.1em;margin-bottom:8px\">Ventilation TVA (bar\u00e8me tunisien)<\/div>${tvaRows}`:''}\r\n            <\/div>\r\n            <div style=\"width:300px\">\r\n                <div style=\"display:flex;justify-content:space-between;padding:9px 0;border-bottom:1px solid #eee;font-size:12px\"><span style=\"color:#888\">Total HT<\/span><span style=\"font-weight:700;font-family:'Courier New',monospace\">${totHT}<\/span><\/div>\r\n                <div style=\"display:flex;justify-content:space-between;padding:9px 0;border-bottom:1px solid #eee;font-size:12px\"><span style=\"color:#888\">Total TVA<\/span><span style=\"font-weight:700;font-family:'Courier New',monospace\">${totTVA}<\/span><\/div>\r\n                ${timbreHTML}\r\n                <div style=\"display:flex;justify-content:space-between;padding:16px 20px;background:rgba(255,107,44,.06);border:2px solid rgba(255,107,44,.2);border-radius:10px;margin-top:12px\">\r\n                    <span style=\"font-size:15px;font-weight:900;color:#1a1a1a;text-transform:uppercase;letter-spacing:.04em\">Net a payer<\/span>\r\n                    <span style=\"font-size:20px;font-weight:900;color:#ff6b2c;font-family:'Courier New',monospace\">${totTTC}<\/span>\r\n                <\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <!-- FOOTER -->\r\n        <div style=\"border-top:3px solid #ff6b2c;padding-top:20px;display:flex;gap:30px\">\r\n            <div style=\"flex:1\">\r\n                <div style=\"font-size:9px;font-weight:700;color:#1a1a1a;text-transform:uppercase;letter-spacing:.1em;margin-bottom:8px\">Notes & Conditions<\/div>\r\n                <div style=\"font-size:10px;color:#888;line-height:1.9\">${notes||'\u2014'}<\/div>\r\n            <\/div>\r\n            <div style=\"flex:1\">\r\n                <div style=\"font-size:9px;font-weight:700;color:#1a1a1a;text-transform:uppercase;letter-spacing:.1em;margin-bottom:8px\">Coordonnees bancaires<\/div>\r\n                <div style=\"font-size:10px;color:#888;line-height:1.9\">${bankHTML}<\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <!-- BOTTOM BAR -->\r\n        <div style=\"position:absolute;bottom:30px;left:56px;right:56px;text-align:center;font-size:8px;color:#ccc;letter-spacing:.06em;border-top:1px solid #f0f0f0;padding-top:10px\">\r\n            ${docType} ${ref} \u2014 Emise le ${dc} \u2014 Montants exprimes en Dinars Tunisiens (DT)\r\n        <\/div>\r\n    <\/div>`;\r\n\r\n    div.style.cssText='position:fixed;left:-9999px;top:0;z-index:-1';\r\n    document.body.appendChild(div);\r\n    return div;\r\n}\r\n\r\nfunction genPDF(){\r\n    const ov=document.getElementById('si-pdf-ov');ov.classList.add('on');\r\n    loadSc('https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/html2pdf.js\/0.10.2\/html2pdf.bundle.min.js').then(()=>{\r\n        const container=buildPDFTemplate();\r\n        const page=container.firstElementChild;\r\n        const docType=(document.querySelector('.si-tab.on')?.dataset.t||'document').toLowerCase();\r\n        const ref=document.getElementById('i-ref').value||'document';\r\n        html2pdf().set({\r\n            margin:0,\r\n            filename:docType+'_'+ref.replace(\/\\s+\/g,'_')+'.pdf',\r\n            image:{type:'jpeg',quality:0.98},\r\n            html2canvas:{scale:2,useCORS:true,backgroundColor:'#ffffff',logging:false},\r\n            jsPDF:{unit:'px',format:[794,1123],orientation:'portrait',hotfixes:['px_scaling']}\r\n        }).from(page).save().then(()=>{\r\n            container.remove();ov.classList.remove('on');toast('PDF genere avec succes');\r\n        }).catch(e=>{container.remove();ov.classList.remove('on');toast('Erreur PDF');console.error('[si]',e)});\r\n    }).catch(()=>{ov.classList.remove('on');toast('Impossible de charger html2pdf.js')});\r\n}\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   SAVE \/ LOAD \/ RESET\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nfunction gather(){\r\n    const rows=[];\r\n    document.querySelectorAll('#si-tb tr').forEach(tr=>{\r\n        const c=tr.children;if(c.length<6)return;\r\n        rows.push({r:c[0].textContent.trim(),d:c[1].textContent.trim(),q:c[2].textContent.trim(),p:c[3].textContent.trim(),v:c[4].querySelector('select')?.value||'19'});\r\n    });\r\n    return{\r\n        dt:document.querySelector('.si-tab.on')?.dataset.t||'Facture',\r\n        ref:document.getElementById('i-ref').value,\r\n        cn:document.getElementById('i-cn').value,\r\n        mf:document.getElementById('i-mf').value,\r\n        ca:document.getElementById('i-ca').value,\r\n        dc:document.getElementById('i-dc').value,\r\n        dd:document.getElementById('i-dd').value,\r\n        rows,notes:document.getElementById('i-notes').value,\r\n        ci:document.getElementById('i-cinfo').innerHTML,\r\n        bank:document.getElementById('i-bank').value,\r\n        rib:document.getElementById('i-rib').value,\r\n        iban:document.getElementById('i-iban').value,\r\n        logo:logoData,timbre:timbreOn,ts:Date.now()\r\n    };\r\n}\r\n\r\nfunction saveData(){\r\n    try{localStorage.setItem(STORAGE,JSON.stringify(gather()));toast('Sauvegarde effectuee')}\r\n    catch(e){toast(e.name==='QuotaExceededError'?'Logo trop volumineux':'Erreur de sauvegarde')}\r\n}\r\n\r\nfunction loadData(){\r\n    try{\r\n        const raw=localStorage.getItem(STORAGE);\r\n        if(!raw){toast('Aucune sauvegarde trouvee');return}\r\n        const d=JSON.parse(raw);\r\n        qa('.si-tab').forEach(t=>t.classList.toggle('on',t.dataset.t===d.dt));\r\n        document.getElementById('i-ref').value=d.ref||'';\r\n        document.getElementById('i-cn').value=d.cn||'';\r\n        document.getElementById('i-mf').value=d.mf||'';\r\n        document.getElementById('i-ca').value=d.ca||'';\r\n        document.getElementById('i-dc').value=d.dc||'';\r\n        document.getElementById('i-dd').value=d.dd||'';\r\n        document.getElementById('i-notes').value=d.notes||'';\r\n        document.getElementById('i-cinfo').innerHTML=d.ci||'';\r\n        document.getElementById('i-bank').value=d.bank||'';\r\n        document.getElementById('i-rib').value=d.rib||'';\r\n        document.getElementById('i-iban').value=d.iban||'';\r\n        logoData=d.logo||null;applyLogo();\r\n        if(d.timbre)addTimbre();else removeTimbre();\r\n        const tb=document.getElementById('si-tb');tb.innerHTML='';\r\n        (d.rows||[]).forEach(r=>addRow(r));\r\n        if(!d.rows||!d.rows.length)addRow();\r\n        recalc();\r\n        toast('Restaure \u2014 '+new Date(d.ts).toLocaleDateString('fr-FR'));\r\n    }catch(e){toast('Erreur de restauration');console.error('[si]',e)}\r\n}\r\n\r\nfunction resetData(){\r\n    if(!confirm('Reinitialiser le document ?'))return;\r\n    document.getElementById('i-ref').value='FAC 0001';\r\n    qa('.si-tab').forEach(t=>t.classList.toggle('on',t.dataset.t==='Facture'));\r\n    ['i-cn','i-mf','i-ca','i-bank','i-rib','i-iban'].forEach(id=>document.getElementById(id).value='');\r\n    document.getElementById('i-dc').value=new Date().toLocaleDateString('fr-FR');\r\n    const d=new Date();d.setDate(d.getDate()+30);\r\n    document.getElementById('i-dd').value=d.toLocaleDateString('fr-FR');\r\n    document.getElementById('i-notes').value='Reglement a 30 jours. En cas de retard, penalites de retard selon la legislation tunisienne en vigueur.';\r\n    document.getElementById('i-cinfo').innerHTML='';\r\n    document.getElementById('i-cextra').innerHTML='';\r\n    document.getElementById('i-dextra').innerHTML='';\r\n    removeLogo();removeTimbre();cfc=0;dfc=0;\r\n    const tb=document.getElementById('si-tb');tb.innerHTML='';addRow();\r\n    toast('Reinitialise');\r\n}\r\n\r\nfunction toast(m){const e=document.getElementById('si-toast');if(!e)return;e.textContent=m;e.classList.add('on');clearTimeout(e._t);e._t=setTimeout(()=>e.classList.remove('on'),2800)}\r\n\r\nif(document.readyState==='loading')document.addEventListener('DOMContentLoaded',build);else build();\r\n})();\r\n<\/script>\t\t\t\t<\/div>\n\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":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-11954","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/shopini.tn\/ar\/wp-json\/wp\/v2\/pages\/11954","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/shopini.tn\/ar\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/shopini.tn\/ar\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/shopini.tn\/ar\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/shopini.tn\/ar\/wp-json\/wp\/v2\/comments?post=11954"}],"version-history":[{"count":20,"href":"https:\/\/shopini.tn\/ar\/wp-json\/wp\/v2\/pages\/11954\/revisions"}],"predecessor-version":[{"id":12025,"href":"https:\/\/shopini.tn\/ar\/wp-json\/wp\/v2\/pages\/11954\/revisions\/12025"}],"wp:attachment":[{"href":"https:\/\/shopini.tn\/ar\/wp-json\/wp\/v2\/media?parent=11954"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}