mirror of
https://github.com/wasrusgen/wasrusgen1-crm.git
synced 2026-06-03 19:04:47 +00:00
4232 lines
310 KiB
HTML
4232 lines
310 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||
<title>ЗАЩИТА — прототип (весь путь)</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Montserrat:wght@700&display=swap" rel="stylesheet" media="print" onload="this.media='all'">
|
||
<script src="https://telegram.org/js/telegram-web-app.js"></script>
|
||
<script>
|
||
(function(){
|
||
var tg = window.Telegram && window.Telegram.WebApp;
|
||
if(tg){
|
||
tg.ready();
|
||
tg.expand();
|
||
document.documentElement.classList.add('tma');
|
||
// Нативная кнопка «назад» TG
|
||
tg.BackButton.onClick(function(){
|
||
var screens = document.querySelectorAll('.screen.on');
|
||
if(screens.length && screens[0].id !== 'start'){ window.go('start'); }
|
||
});
|
||
}
|
||
})();
|
||
</script>
|
||
<link rel="stylesheet" href="tokens.css">
|
||
<style>
|
||
*{box-sizing:border-box;margin:0;padding:0}
|
||
body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-height:1.5}
|
||
.screen{display:none;min-height:100vh}
|
||
.screen.on{display:block}
|
||
.brand{font-family:var(--font-logo);font-weight:700;letter-spacing:2px}
|
||
.btn{border:none;border-radius:11px;padding:13px 20px;font-size:15px;font-weight:700;cursor:pointer;font-family:inherit}
|
||
.btn-p{background:var(--bg);color:#fff} .btn-p:hover{background:var(--bghv)}
|
||
.btn-o{background:#fff;color:var(--bg);border:1.5px solid var(--bg)}
|
||
.chip{font-size:11px;font-weight:700;padding:3px 9px;border-radius:20px}
|
||
.chip.d{background:var(--dngbg);color:var(--dng)} .chip.w{background:var(--warnbg);color:var(--warn)} .chip.n{background:var(--surf);color:var(--mut)} .chip.ok{background:var(--okbg);color:var(--ok)}
|
||
|
||
/* ── 1. СТАРТ ── */
|
||
#start{background:linear-gradient(150deg,#2A020D,var(--bg));color:#fff;display:none;align-items:center}
|
||
#start.on{display:flex}
|
||
.hero{max-width:1000px;margin:0 auto;padding:50px 32px;display:grid;grid-template-columns:1.2fr .8fr;grid-template-rows:auto 1fr;gap:0 40px;align-items:start}
|
||
.hero-logo{grid-column:1;grid-row:1;display:flex;align-items:center;gap:0;margin-bottom:28px}
|
||
.hero-logomark{height:34px;filter:brightness(0) invert(1);flex-shrink:0}
|
||
.hero-logo-sep{width:1.5px;height:26px;background:rgba(255,255,255,.35);margin:0 16px;flex-shrink:0}
|
||
.hero-wordmark{height:17px;filter:brightness(0) invert(1);flex-shrink:0}
|
||
.hero-body{grid-column:1;grid-row:2}
|
||
.hero .face{grid-column:2;grid-row:1/3;align-self:stretch}
|
||
.hero h1{font-size:40px;font-weight:800;letter-spacing:-1px;line-height:1.1;margin-bottom:16px}
|
||
.hero p{font-size:17px;color:rgba(255,255,255,.75);margin-bottom:28px;max-width:460px}
|
||
.hero .cta{display:flex;gap:12px;flex-wrap:wrap}
|
||
.hero .priv{margin-top:20px;font-size:12px;color:rgba(255,255,255,.5)}
|
||
.hero .face img{width:100%;height:100%;min-height:380px;object-fit:cover;object-position:center 18%;border-radius:20px;display:block;box-shadow:0 20px 50px rgba(0,0,0,.4)}
|
||
.hero .face .cap{text-align:center;font-size:13px;color:rgba(255,255,255,.7);margin-top:10px}
|
||
|
||
/* ── общий чат (Елена) ── */
|
||
.topbar{background:linear-gradient(90deg,var(--shell),var(--shell2));color:#fff;display:flex;align-items:center;gap:12px;padding:12px 22px}
|
||
.topbar .w{font-size:14px;color:#fff} .topbar .sep{width:1.5px;height:16px;background:rgba(255,255,255,.3)}
|
||
.topbar-wm{height:13px;filter:brightness(0) invert(1);vertical-align:middle;flex-shrink:0}
|
||
.topbar .ttl{font-size:13px;color:rgba(255,255,255,.8);margin-left:6px}
|
||
.back{margin-left:auto;font-size:12px;color:rgba(255,255,255,.6);cursor:pointer}
|
||
.chatwrap{max-width:660px;margin:0 auto;padding:24px 18px 120px}
|
||
.msg{display:flex;gap:11px;margin-bottom:16px;align-items:flex-start}
|
||
.av{width:40px;height:40px;border-radius:50%;overflow:hidden;flex-shrink:0;border:1.5px solid var(--line)}
|
||
.av img{width:100%;height:100%;object-fit:cover;object-position:center 16%}
|
||
.bubble{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:13px 16px;font-size:14px;max-width:80%;box-shadow:0 1px 2px rgba(0,0,0,.04)}
|
||
.bubble .nm{font-size:11px;font-weight:700;color:var(--bg);margin-bottom:4px}
|
||
.bubble b{color:var(--bg)}
|
||
.risk-mini{border-top:1px dashed var(--line);padding:8px 0 0;margin-top:8px;font-size:12.5px}
|
||
.risk-mini .rn{color:var(--bg);font-weight:600;font-size:11px}
|
||
.lock{background:var(--tint);border:1px dashed var(--bg);border-radius:10px;padding:10px 12px;margin-top:10px;font-size:12.5px;color:var(--dark)}
|
||
.forks{display:flex;gap:10px;margin:4px 0 4px 51px;flex-wrap:wrap}
|
||
.fork{background:var(--card);border:1.5px solid var(--line);border-radius:13px;padding:12px 14px;cursor:pointer;font-size:13px;font-weight:700;flex:1;min-width:180px}
|
||
.fork:hover{border-color:var(--bg);transform:translateY(-1px)} .fork .ds{font-weight:400;color:var(--mut);font-size:12px;margin-top:3px}
|
||
.actbar{position:fixed;bottom:0;left:0;right:0;background:linear-gradient(180deg,transparent,var(--surf) 30%);padding:18px;display:flex;justify-content:center}
|
||
.actbar .inner{max-width:660px;width:100%;display:flex;gap:10px}
|
||
|
||
/* ── 3. ОПЛАТА ── */
|
||
.pay{max-width:560px;margin:0 auto;padding:40px 22px}
|
||
.pay h2{font-size:24px;font-weight:800;margin-bottom:6px} .pay .s{color:var(--mut);font-size:14px;margin-bottom:24px}
|
||
.plan{background:var(--card);border:1.5px solid var(--line);border-radius:16px;padding:18px;margin-bottom:14px}
|
||
.plan.sel{border-color:var(--bg);box-shadow:0 4px 16px rgba(159,18,57,.12)}
|
||
.plan .pn{font-weight:800;font-size:16px} .plan .pp{font-weight:800;font-size:20px;color:var(--bg);float:right}
|
||
.plan .pd{font-size:13px;color:var(--mut);margin-top:4px}
|
||
.field{margin:14px 0}.field label{font-size:12px;font-weight:600;display:block;margin-bottom:5px}
|
||
.field input{width:100%;border:1.5px solid var(--line);border-radius:10px;padding:11px 13px;font-size:14px;font-family:inherit}
|
||
.pdn{font-size:11px;color:var(--mut);margin:10px 0 16px}
|
||
/* ── PAY HYBRID ── */
|
||
.pay-bal{background:linear-gradient(135deg,#4f46e5 0%,#7c3aed 100%);color:#fff;border-radius:14px;padding:14px 18px;display:flex;align-items:center;gap:12px;margin-bottom:20px}
|
||
.pay-bal-ico{font-size:22px;flex-shrink:0}
|
||
.pay-bal-body{flex:1}
|
||
.pay-bal-lbl{font-size:11px;opacity:.75;font-weight:600;text-transform:uppercase;letter-spacing:.05em}
|
||
.pay-bal-val{font-size:20px;font-weight:800;line-height:1.1}
|
||
.pay-bal-sub{font-size:11px;opacity:.75;margin-top:2px}
|
||
.pay-bal-use{background:rgba(255,255,255,.2);border:1.5px solid rgba(255,255,255,.35);color:#fff;border-radius:8px;padding:7px 14px;font-size:12px;font-weight:700;cursor:pointer;white-space:nowrap;flex-shrink:0}
|
||
.pay-bal-use:hover{background:rgba(255,255,255,.3)}
|
||
.pay-tabs{display:flex;gap:8px;margin-bottom:20px}
|
||
.pay-tab{flex:1;padding:10px;border:2px solid #e5e7eb;border-radius:12px;text-align:center;cursor:pointer;font-size:13px;font-weight:700;color:#6b7280;background:#fff;transition:all .15s}
|
||
.pay-tab.on{border-color:var(--bg);color:var(--bg);background:#fef2f2}
|
||
.pay-pane{display:none}
|
||
.pay-pane.on{display:block}
|
||
.pkg-grid{display:flex;flex-direction:column;gap:10px;margin-bottom:16px}
|
||
.pkg-card{border:2px solid #e5e7eb;border-radius:14px;padding:14px 16px;cursor:pointer;transition:all .15s;position:relative}
|
||
.pkg-card:hover{border-color:#d1d5db}
|
||
.pkg-card.sel{border-color:var(--bg);background:#fff5f5}
|
||
.pkg-card.rec::before{content:"Выгоднее всего";position:absolute;top:-1px;right:14px;background:var(--bg);color:#fff;font-size:10px;font-weight:700;padding:2px 8px;border-radius:0 0 6px 6px}
|
||
.pkg-top{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:3px}
|
||
.pkg-name{font-size:14px;font-weight:700;color:var(--ink)}
|
||
.pkg-price{font-size:18px;font-weight:800;color:var(--bg)}
|
||
.pkg-desc{font-size:12px;color:var(--mut)}
|
||
.pkg-per{font-size:11px;color:#9ca3af;margin-top:2px}
|
||
.sub-grid{display:flex;flex-direction:column;gap:10px;margin-bottom:16px}
|
||
.sub-card{border:2px solid #e5e7eb;border-radius:14px;padding:14px 16px;cursor:pointer;transition:all .15s;position:relative}
|
||
.sub-card:hover{border-color:#d1d5db}
|
||
.sub-card.sel{border-color:var(--bg);background:#fff5f5}
|
||
.sub-card.rec::before{content:"Популярно";position:absolute;top:-1px;right:14px;background:var(--bg);color:#fff;font-size:10px;font-weight:700;padding:2px 8px;border-radius:0 0 6px 6px}
|
||
.sub-top{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:3px}
|
||
.sub-name{font-size:14px;font-weight:700;color:var(--ink)}
|
||
.sub-price{font-size:18px;font-weight:800;color:var(--bg)}
|
||
.sub-period{font-size:11px;color:#9ca3af;margin-left:3px}
|
||
.sub-desc{font-size:12px;color:var(--mut)}
|
||
.sub-feat{font-size:11px;color:#6b7280;margin-top:6px;display:flex;flex-wrap:wrap;gap:4px}
|
||
.sub-feat span{background:#f3f4f6;padding:2px 7px;border-radius:6px}
|
||
.pay-refund-note{font-size:11px;color:var(--mut);text-align:center;margin-bottom:12px}
|
||
.pay-refund-note a{color:var(--bg);text-decoration:none}
|
||
/* ЮKassa modal */
|
||
.yk-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:1000;align-items:flex-end;justify-content:center}
|
||
.yk-overlay.on{display:flex}
|
||
.yk-modal{background:#fff;border-radius:20px 20px 0 0;padding:24px;width:100%;max-width:480px;animation:slideUp .25s ease}
|
||
@keyframes slideUp{from{transform:translateY(100%)}to{transform:translateY(0)}}
|
||
.yk-hdr{display:flex;justify-content:space-between;align-items:center;margin-bottom:18px}
|
||
.yk-ttl{font-size:16px;font-weight:800;color:var(--ink)}
|
||
.yk-close{font-size:20px;cursor:pointer;color:#9ca3af;background:none;border:none;padding:4px}
|
||
.yk-amount{font-size:28px;font-weight:800;color:var(--bg);text-align:center;margin-bottom:20px}
|
||
.yk-methods{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:18px}
|
||
.yk-method{border:2px solid #e5e7eb;border-radius:12px;padding:12px;cursor:pointer;text-align:center;transition:all .15s}
|
||
.yk-method:hover,.yk-method.sel{border-color:var(--bg);background:#fff5f5}
|
||
.yk-method-ico{font-size:22px;margin-bottom:4px}
|
||
.yk-method-lbl{font-size:11px;font-weight:700;color:var(--ink)}
|
||
.yk-sbp{background:linear-gradient(135deg,#00b27a,#00913c);color:#fff;border:none!important}
|
||
.yk-sbp .yk-method-lbl{color:#fff}
|
||
.yk-card-form{margin-bottom:16px}
|
||
.yk-card-form input{width:100%;border:1.5px solid #e5e7eb;border-radius:10px;padding:10px 12px;font-size:14px;box-sizing:border-box;margin-bottom:8px}
|
||
.yk-card-row{display:grid;grid-template-columns:1fr 1fr;gap:8px}
|
||
.yk-pay-btn{width:100%;background:var(--bg);color:#fff;border:none;border-radius:12px;padding:14px;font-size:15px;font-weight:700;cursor:pointer}
|
||
.yk-pay-btn:hover{background:var(--bghv)}
|
||
.yk-secure{font-size:10px;color:#9ca3af;text-align:center;margin-top:8px}.pdn a{color:var(--bg)}
|
||
|
||
/* ── кабинет (общий каркас) ── */
|
||
.app{display:flex;min-height:100vh;background:#f4f5f7}
|
||
/* ── Сайдбар ── */
|
||
.side{width:224px;background:#0C0608;color:#cbb;display:flex;flex-direction:column;flex-shrink:0;min-height:100vh}
|
||
.side-logo{padding:20px 20px 16px;border-bottom:1px solid rgba(255,255,255,.07)}
|
||
.side-logo img{height:16px;filter:brightness(0) invert(1)}
|
||
.side-nav{padding:10px 0;flex:1}
|
||
.side-section{font-size:10px;font-weight:700;letter-spacing:.8px;color:rgba(255,255,255,.25);padding:14px 20px 5px;text-transform:uppercase}
|
||
.side a{display:flex;align-items:center;gap:10px;padding:9px 20px;color:rgba(255,255,255,.55);font-size:13px;font-weight:500;cursor:pointer;border-left:3px solid transparent;transition:all .15s;text-decoration:none}
|
||
.side a:hover{color:#fff;background:rgba(255,255,255,.05)}
|
||
.side a.on{color:#fff;background:rgba(159,18,57,.25);border-left-color:var(--bg)}
|
||
.side a .sico{font-size:15px;width:20px;text-align:center;flex-shrink:0}
|
||
.side a .sbadge{margin-left:auto;background:var(--bg);color:#fff;font-size:10px;font-weight:700;border-radius:10px;padding:1px 6px;min-width:18px;text-align:center}
|
||
.side-new{margin:8px 12px 4px;background:var(--bg);color:#fff;border:none;border-radius:10px;padding:10px 14px;font-size:13px;font-weight:700;cursor:pointer;font-family:inherit;width:calc(100% - 24px);display:flex;align-items:center;gap:8px;transition:background .15s}
|
||
.side-new:hover{background:var(--bghv)}
|
||
.side .prof{padding:14px 16px;border-top:1px solid rgba(255,255,255,.07);display:flex;gap:10px;align-items:center}
|
||
.side .prof .pa{width:34px;height:34px;border-radius:10px;background:var(--bg);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:12px;flex-shrink:0}
|
||
.side .prof .pn{font-size:12px;color:#fff;font-weight:600}
|
||
.side .prof .pt{font-size:10px;color:rgba(255,255,255,.4);margin-top:1px}
|
||
/* ── Основная область ── */
|
||
.main{flex:1;display:flex;flex-direction:column;min-width:0;min-height:100vh}
|
||
.main-hdr{background:#fff;border-bottom:1px solid #e5e7eb;padding:0 28px;height:56px;display:flex;align-items:center;gap:16px;flex-shrink:0;position:sticky;top:0;z-index:50}
|
||
.main-hdr h2{font-size:17px;font-weight:800;margin:0;flex-shrink:0}
|
||
.main-hdr-search{flex:1;max-width:340px;position:relative}
|
||
.main-hdr-search input{width:100%;border:1.5px solid #e5e7eb;border-radius:9px;padding:7px 12px 7px 34px;font-size:13px;font-family:inherit;outline:none;background:#f9fafb;color:var(--ink);box-sizing:border-box}
|
||
.main-hdr-search input:focus{border-color:var(--bg);background:#fff}
|
||
.main-hdr-search::before{content:'🔍';position:absolute;left:10px;top:50%;transform:translateY(-50%);font-size:13px;pointer-events:none}
|
||
.main-hdr-actions{margin-left:auto;display:flex;gap:8px;align-items:center}
|
||
.main-body{padding:24px 28px;flex:1}
|
||
.main-body .crumb{font-size:12px;color:var(--mut);margin-bottom:6px}
|
||
.main-body h1{font-size:20px;font-weight:800;margin:0 0 18px}
|
||
/* ── KPI карточки ── */
|
||
.kpi-row{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:22px}
|
||
.kpi-card{background:#fff;border:1px solid #e5e7eb;border-radius:13px;padding:16px 18px;display:flex;align-items:center;gap:14px}
|
||
.kpi-card .kc-ico{width:42px;height:42px;border-radius:11px;display:flex;align-items:center;justify-content:center;font-size:20px;flex-shrink:0}
|
||
.kpi-card .kc-num{font-size:24px;font-weight:800;line-height:1}
|
||
.kpi-card .kc-lbl{font-size:12px;color:var(--mut);margin-top:2px}
|
||
.kpi-card.kpi-total .kc-ico{background:#ede9fe}
|
||
.kpi-card.kpi-work .kc-ico{background:#dbeafe}
|
||
.kpi-card.kpi-urg .kc-ico{background:#fee2e2}
|
||
.kpi-card.kpi-done .kc-ico{background:#dcfce7}
|
||
.enote{display:flex;gap:11px;align-items:center;background:var(--card);border:1px solid var(--line);border-left:3px solid var(--bg);border-radius:12px;padding:12px 14px;max-width:760px;margin:14px 0 16px}
|
||
.enote img{width:40px;height:40px;border-radius:50%;object-fit:cover;object-position:center 16%}
|
||
.enote .et{font-size:13px}
|
||
.cases{display:flex;flex-direction:column;gap:11px;max-width:760px}
|
||
.case{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:14px 16px;display:flex;align-items:center;gap:13px;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.04)}
|
||
.case:hover{border-color:var(--bg);transform:translateY(-1px);box-shadow:0 6px 18px rgba(0,0,0,.08)}
|
||
.case .ci{width:44px;height:44px;border-radius:11px;background:var(--tint);display:flex;align-items:center;justify-content:center;font-size:21px}
|
||
.case .cb{flex:1}.case .ct{font-weight:700;font-size:14px}.case .cs{font-size:12px;color:var(--mut);margin-top:2px}
|
||
.case .cm{display:flex;gap:6px;margin-top:6px;flex-wrap:wrap}.case .cg{color:var(--bg);font-weight:700;font-size:13px}
|
||
.tabpane{display:none}.tabpane.on{display:block}
|
||
.docrow{display:flex;align-items:center;gap:9px;font-size:13px;padding:9px 0;border-top:1px dashed var(--line);max-width:760px}
|
||
.docrow:first-of-type{border-top:none}.docrow .ver{font-size:10px;font-weight:700;color:var(--bg);background:var(--tint);border-radius:6px;padding:2px 6px;margin-left:auto}
|
||
.dlx{background:var(--card);border:1px solid var(--line);border-radius:13px;padding:12px 15px;display:flex;align-items:center;gap:13px;max-width:760px;margin-bottom:9px}
|
||
.dlx .dd{min-width:50px;height:50px;border-radius:11px;display:flex;flex-direction:column;align-items:center;justify-content:center;font-weight:800}
|
||
.dd.dd{background:var(--dngbg);color:var(--dng)}.dd.dw{background:var(--warnbg);color:var(--warn)}.dd.dn{background:var(--surf);color:var(--mut)}
|
||
.dlx .n{font-size:18px;line-height:1}.dlx .u{font-size:9px}
|
||
.tpls{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px;max-width:760px}
|
||
.tpl{background:var(--card);border:1px solid var(--line);border-radius:13px;padding:15px;cursor:pointer}.tpl:hover{border-color:var(--bg)}
|
||
.tpl .ti{font-size:22px}.tpl .tn{font-weight:700;font-size:13.5px;margin:7px 0 3px}.tpl .td{font-size:12px;color:var(--mut)}
|
||
.steps{font-size:12px;color:var(--mut);margin:24px 0;display:flex;gap:8px;flex-wrap:wrap}
|
||
.steps b{color:var(--bg)}
|
||
/* ── выбор deliverable ── */
|
||
.deliverables{display:flex;flex-direction:column;gap:9px;margin:4px 0 4px 51px;max-width:520px}
|
||
.deliv{background:var(--card);border:1.5px solid var(--line);border-radius:13px;padding:13px 16px;cursor:pointer;display:flex;align-items:flex-start;gap:12px;transition:border-color .15s,box-shadow .15s}
|
||
.deliv:hover{border-color:var(--bg);box-shadow:0 4px 14px rgba(159,18,57,.1)}
|
||
.deliv .di{font-size:20px;flex-shrink:0;margin-top:1px}
|
||
.deliv .dn{font-size:13.5px;font-weight:700}
|
||
.deliv .dd2{font-size:12.5px;color:var(--mut);margin-top:4px;line-height:1.55}
|
||
.deliv-top{border-color:rgba(159,18,57,.3);background:var(--tint)}
|
||
.deliv-top .dn{color:var(--bg)}
|
||
.deliv-badge{font-size:10px;font-weight:700;background:var(--bg);color:#fff;border-radius:6px;padding:2px 7px;margin-left:auto;flex-shrink:0}
|
||
.deliv-highlighted{border-color:var(--bg)!important;background:linear-gradient(135deg,#fff 0%,rgba(159,18,57,.06) 100%)!important;box-shadow:0 0 0 2px rgba(159,18,57,.15)!important}
|
||
.deliv-highlighted .dn{color:var(--bg)!important}
|
||
.ctype-note{display:block;font-size:13px;color:var(--mut);line-height:1.5;margin-bottom:6px;padding:8px 10px;background:var(--surf);border-radius:8px;border-left:3px solid var(--bg)}
|
||
.sample-link{display:inline-block;margin-top:7px;font-size:11px;font-weight:600;color:var(--bg);text-decoration:none;border:1px solid rgba(159,18,57,.3);border-radius:5px;padding:2px 9px;transition:background .15s}
|
||
.sample-link:hover{background:var(--tint)}
|
||
|
||
.deliv-sep{font-size:11px;color:var(--mut);text-align:center;padding:6px 0 2px;letter-spacing:.3px;display:flex;align-items:center;gap:8px}
|
||
.deliv-sep::before,.deliv-sep::after{content:'';flex:1;height:1px;background:var(--line)}
|
||
|
||
/* ── свой запрос ── */
|
||
.custom-req-row{margin:14px 0 0 51px}
|
||
.custom-req-toggle{background:none;border:1.5px dashed var(--line);border-radius:11px;padding:9px 14px;font-size:13px;color:var(--mut);cursor:pointer;font-family:inherit;transition:all .15s;width:100%;max-width:520px;text-align:left}
|
||
.custom-req-toggle:hover{border-color:var(--bg);color:var(--bg);background:var(--tint)}
|
||
.custom-req-area{margin-top:4px}
|
||
.custom-input-block{margin:0 0 12px 51px;max-width:520px}
|
||
.custom-input-block textarea{width:100%;border:1.5px solid var(--line);border-radius:11px;padding:11px 13px;font-size:14px;font-family:inherit;color:var(--ink);resize:none;background:var(--card);transition:border .15s;line-height:1.5}
|
||
.custom-input-block textarea:focus{outline:none;border-color:var(--bg)}
|
||
.custom-input-btns{display:flex;gap:8px;margin-top:8px;align-items:stretch}
|
||
.custom-voice-btn{background:var(--surf);border:1.5px solid var(--line);border-radius:11px;width:46px;height:46px;font-size:20px;cursor:pointer;flex-shrink:0;transition:all .15s;display:flex;align-items:center;justify-content:center}
|
||
.custom-voice-btn:hover{border-color:var(--bg);background:var(--tint)}
|
||
.custom-voice-btn.recording{background:#fee2e2;border-color:#ef4444;animation:crpulse 1s infinite}
|
||
@keyframes crpulse{0%,100%{box-shadow:0 0 0 0 rgba(239,68,68,.3)}50%{box-shadow:0 0 0 6px rgba(239,68,68,0)}}
|
||
/* ── план после выбора ── */
|
||
.plan-what{background:var(--surf);border-radius:12px;padding:14px 16px;margin:16px 0;max-width:600px}
|
||
.plan-what-title{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1.2px;color:var(--mut);margin-bottom:10px}
|
||
.plan-what li{font-size:13px;color:var(--dark);padding:4px 0;list-style:none;display:flex;gap:8px;align-items:flex-start}
|
||
.plan-what li::before{content:'✓';color:var(--ok);font-weight:700;flex-shrink:0}
|
||
.plan-pitch{background:var(--tint);border:1.5px solid rgba(159,18,57,.2);border-radius:13px;padding:14px 16px;margin:20px 0;display:flex;gap:11px;align-items:flex-start;max-width:600px}
|
||
.plan-pitch img{width:38px;height:38px;border-radius:50%;object-fit:cover;object-position:center 16%;flex-shrink:0}
|
||
.plan-pitch-body{font-size:13px;line-height:1.6}
|
||
.plan-pitch-body b{color:var(--bg)}
|
||
.plan-pitch-body .pi-step{display:flex;gap:10px;margin:5px 0;align-items:flex-start;font-size:13px;line-height:1.6}
|
||
.plan-pitch-body .pi-n{background:var(--bg);color:#fff;border-radius:50%;width:20px;height:20px;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:1px}
|
||
.plan-pitch-body .pi-meta{font-size:11.5px;color:var(--mut);background:var(--surf);border-radius:7px;padding:5px 10px;margin-top:8px;line-height:1.5}
|
||
.plan-pitch-body .pi-tag{display:inline-block;font-size:10px;font-weight:700;padding:2px 7px;border-radius:8px;margin-right:5px;margin-top:2px}
|
||
.plan-pitch-body .pi-incl{background:var(--okbg);color:var(--ok)}.plan-pitch-body .pi-warn{background:var(--warnbg);color:var(--warn)}
|
||
|
||
/* ── intake-вопрос ── */
|
||
.intake{display:flex;flex-direction:column;gap:9px;margin:4px 0 4px 51px}
|
||
.intake-opt{background:var(--card);border:1.5px solid var(--line);border-radius:13px;padding:12px 16px;cursor:pointer;font-size:13.5px;font-weight:600;display:flex;align-items:center;gap:10px;transition:border-color .15s,box-shadow .15s}
|
||
.intake-opt:hover{border-color:var(--bg);box-shadow:0 4px 14px rgba(159,18,57,.1)}
|
||
.intake-opt .io{font-size:18px;pointer-events:none}
|
||
.intake-opt .id{font-weight:400;color:var(--mut);font-size:12px;margin-top:2px;pointer-events:none}
|
||
.intake-opt>div{pointer-events:none}
|
||
.intake-other{display:flex;gap:8px;margin-top:2px}
|
||
.intake-other input{flex:1;border:1.5px solid var(--line);border-radius:11px;padding:10px 13px;font-size:13.5px;font-family:inherit;outline:none}
|
||
.intake-other input:focus{border-color:var(--bg)}
|
||
/* цитата из договора */
|
||
.risk-quote{background:var(--surf);border-left:3px solid var(--bg);border-radius:0 8px 8px 0;padding:7px 10px;font-size:12px;color:var(--mut);font-style:italic;margin:6px 0 5px;line-height:1.5}
|
||
.intake-other button{background:var(--bg);color:#fff;border:none;border-radius:11px;padding:10px 16px;font-size:13px;font-weight:700;cursor:pointer;font-family:inherit}
|
||
/* режим — полоска под topbar */
|
||
.mode-badge{font-size:11px;font-weight:700;padding:4px 12px;border-radius:0 0 10px 10px;display:inline-block;margin-left:22px;letter-spacing:.5px}
|
||
.mode-novice{background:rgba(159,18,57,.1);color:var(--bg)}
|
||
.mode-mid{background:rgba(245,158,11,.12);color:#92400E}
|
||
.mode-pro{background:rgba(16,185,129,.1);color:#065F46}
|
||
/* stats dev-panel */
|
||
.stats-pill{position:fixed;bottom:70px;right:18px;background:#0C0608;color:#fff;border-radius:12px;padding:10px 14px;font-size:11px;z-index:9999;cursor:pointer;line-height:1.6;min-width:160px;box-shadow:0 6px 20px rgba(0,0,0,.25)}
|
||
.stats-pill b{color:#FECDD3}
|
||
|
||
|
||
|
||
/* ── GANTT ── */
|
||
.gantt-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;margin-top:4px;padding-bottom:16px}
|
||
/* ── DEADLINE CARDS ── */
|
||
.dl-filter{display:flex;gap:8px;margin-bottom:20px;flex-wrap:wrap}
|
||
.dl-ftab{padding:6px 16px;border-radius:20px;border:1.5px solid #e5e7eb;font-size:12px;font-weight:600;cursor:pointer;color:#6b7280;background:#fff;transition:all .15s}
|
||
.dl-ftab.on{background:var(--bg);color:#fff;border-color:var(--bg)}
|
||
.dl-list{display:flex;flex-direction:column;gap:10px}
|
||
.dl-card{background:#fff;border:1.5px solid #e5e7eb;border-radius:14px;padding:16px 18px;display:flex;gap:14px;align-items:flex-start;transition:box-shadow .15s}
|
||
.dl-card:hover{box-shadow:0 2px 12px rgba(0,0,0,.07)}
|
||
.dl-card.overdue{border-left:4px solid #ef4444}
|
||
.dl-card.soon{border-left:4px solid #f59e0b}
|
||
.dl-card.ok{border-left:4px solid #22c55e}
|
||
.dl-card.done{opacity:.55}
|
||
.dl-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0;margin-top:4px}
|
||
.dl-card.overdue .dl-dot{background:#ef4444}
|
||
.dl-card.soon .dl-dot{background:#f59e0b}
|
||
.dl-card.ok .dl-dot{background:#22c55e}
|
||
.dl-card.done .dl-dot{background:#9ca3af}
|
||
.dl-body{flex:1;min-width:0}
|
||
.dl-title{font-size:14px;font-weight:700;color:var(--ink);margin-bottom:3px}
|
||
.dl-meta{font-size:12px;color:var(--mut);margin-bottom:6px}
|
||
.dl-quote{font-size:11px;color:#6b7280;background:#f9fafb;border-left:2px solid #e5e7eb;padding:5px 10px;border-radius:0 6px 6px 0;margin-bottom:8px;line-height:1.5}
|
||
.dl-right{flex-shrink:0;text-align:right}
|
||
.dl-date{font-size:12px;font-weight:700;color:var(--ink);margin-bottom:4px}
|
||
.dl-badge{font-size:11px;font-weight:700;padding:2px 8px;border-radius:6px}
|
||
.dl-badge.overdue{background:#fee2e2;color:#991b1b}
|
||
.dl-badge.soon{background:#fef3c7;color:#92400e}
|
||
.dl-badge.ok{background:#dcfce7;color:#166534}
|
||
.dl-badge.done{background:#f3f4f6;color:#6b7280}
|
||
.dl-btn{margin-top:8px;font-size:11px;font-weight:700;padding:5px 12px;border-radius:8px;border:1.5px solid #e5e7eb;background:#fff;cursor:pointer;color:#374151;transition:all .15s;white-space:nowrap}
|
||
.dl-btn:hover{border-color:var(--bg);color:var(--bg)}
|
||
.dl-btn.done-btn{border-color:#22c55e;color:#16a34a}
|
||
.dl-empty{text-align:center;padding:48px 24px;color:var(--mut)}
|
||
.dl-empty-ico{font-size:40px;margin-bottom:12px}
|
||
.dl-empty-txt{font-size:14px;font-weight:600;margin-bottom:6px;color:var(--ink)}
|
||
.dl-empty-sub{font-size:12px}
|
||
/* ── ADMIN SCREEN ── */
|
||
.admin-wrap{padding:24px 20px;max-width:900px;margin:0 auto}
|
||
.admin-kpi{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:24px}
|
||
@media(max-width:600px){.admin-kpi{grid-template-columns:1fr 1fr}}
|
||
.akpi{background:#fff;border:1.5px solid #e5e7eb;border-radius:14px;padding:14px 16px}
|
||
.akpi-num{font-size:24px;font-weight:800;line-height:1;margin-bottom:4px}
|
||
.akpi-lbl{font-size:11px;color:var(--mut);font-weight:600}
|
||
.akpi-trend{font-size:11px;margin-top:3px}
|
||
.akpi-trend.up{color:#16a34a}
|
||
.akpi-trend.dn{color:#dc2626}
|
||
.admin-section{margin-bottom:24px}
|
||
.admin-section-hdr{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}
|
||
.admin-section-ttl{font-size:15px;font-weight:800;color:var(--ink)}
|
||
.admin-section-link{font-size:12px;color:var(--bg);cursor:pointer;font-weight:600}
|
||
.pay-table{width:100%;border-collapse:collapse;background:#fff;border-radius:12px;overflow:hidden;border:1.5px solid #e5e7eb}
|
||
.pay-table th{background:#f9fafb;font-size:11px;font-weight:700;color:var(--mut);text-transform:uppercase;padding:8px 12px;text-align:left}
|
||
.pay-table td{padding:10px 12px;font-size:13px;border-top:1px solid #f3f4f6;color:var(--ink)}
|
||
.pay-table tr:hover td{background:#fafafa}
|
||
.pay-badge{font-size:10px;font-weight:700;padding:2px 7px;border-radius:6px}
|
||
.pay-badge.paid{background:#dcfce7;color:#166534}
|
||
.pay-badge.ref{background:#fee2e2;color:#991b1b}
|
||
.pay-badge.pend{background:#fef3c7;color:#92400e}
|
||
.refund-card{background:#fff;border:1.5px solid #e5e7eb;border-radius:12px;padding:14px 16px;margin-bottom:8px;display:flex;gap:12px;align-items:flex-start}
|
||
.refund-card.urgent{border-left:3px solid #ef4444}
|
||
.refund-body{flex:1}
|
||
.refund-ttl{font-size:13px;font-weight:700;color:var(--ink);margin-bottom:3px}
|
||
.refund-meta{font-size:11px;color:var(--mut)}
|
||
.refund-amt{font-size:14px;font-weight:800;color:#ef4444;flex-shrink:0;text-align:right}
|
||
.refund-actions{display:flex;gap:6px;margin-top:8px}
|
||
.refund-btn{font-size:11px;font-weight:700;padding:5px 10px;border-radius:7px;border:1.5px solid;cursor:pointer}
|
||
.refund-btn.approve{border-color:#16a34a;color:#16a34a;background:#f0fdf4}
|
||
.refund-btn.decline{border-color:#dc2626;color:#dc2626;background:#fef2f2}
|
||
.admin-chart{background:#fff;border:1.5px solid #e5e7eb;border-radius:14px;padding:16px;margin-bottom:24px}
|
||
.chart-bars{display:flex;align-items:flex-end;gap:3px;height:80px;margin-top:8px}
|
||
.chart-bar{flex:1;border-radius:4px 4px 0 0;min-height:4px;transition:height .3s}
|
||
.chart-bar.cur{background:var(--bg)}
|
||
.chart-bar:not(.cur){background:#fecaca}
|
||
.chart-lbl{display:flex;gap:3px;margin-top:4px}
|
||
.chart-lbl span{flex:1;font-size:9px;color:var(--mut);text-align:center;overflow:hidden}
|
||
/* Balance tab */
|
||
.bal-hero{background:linear-gradient(135deg,#4f46e5,#7c3aed);border-radius:16px;padding:20px;color:#fff;margin-bottom:20px;text-align:center}
|
||
.bal-hero-num{font-size:48px;font-weight:800;line-height:1}
|
||
.bal-hero-lbl{font-size:13px;opacity:.8;margin-top:4px}
|
||
.bal-hero-sub{font-size:12px;opacity:.65;margin-top:6px}
|
||
.bal-actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:20px}
|
||
.bal-action-btn{padding:12px;border:2px solid #e5e7eb;border-radius:12px;text-align:center;cursor:pointer;font-size:13px;font-weight:700;color:var(--ink);background:#fff;transition:all .15s}
|
||
.bal-action-btn:hover{border-color:var(--bg);color:var(--bg)}
|
||
.pay-hist-item{display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px solid #f3f4f6}
|
||
.phi-left{}
|
||
.phi-desc{font-size:13px;font-weight:600;color:var(--ink)}
|
||
.phi-date{font-size:11px;color:var(--mut);margin-top:2px}
|
||
.phi-right{text-align:right;flex-shrink:0}
|
||
.phi-amt{font-size:14px;font-weight:700}
|
||
.phi-amt.cr{color:#16a34a}
|
||
.phi-amt.db{color:#ef4444}
|
||
.phi-status{font-size:10px;color:var(--mut);margin-top:2px}
|
||
.ref-form{background:#fff5f5;border:1.5px solid #fecaca;border-radius:12px;padding:14px;margin-top:16px}
|
||
.ref-form h4{font-size:13px;font-weight:700;color:var(--ink);margin-bottom:10px}
|
||
.ref-form textarea{width:100%;border:1.5px solid #e5e7eb;border-radius:8px;padding:8px;font-size:13px;box-sizing:border-box;height:70px;resize:none;margin-bottom:8px}
|
||
.ref-form-hint{font-size:11px;color:var(--mut);margin-bottom:10px}
|
||
.dl-summary{display:flex;gap:12px;margin-bottom:20px;flex-wrap:wrap}
|
||
.dl-sum-card{background:#fff;border:1.5px solid #e5e7eb;border-radius:12px;padding:12px 16px;flex:1;min-width:100px;text-align:center}
|
||
.dl-sum-num{font-size:22px;font-weight:800;line-height:1}
|
||
.dl-sum-lbl{font-size:11px;color:var(--mut);margin-top:3px}
|
||
.dl-sum-card.red .dl-sum-num{color:#ef4444}
|
||
.dl-sum-card.yellow .dl-sum-num{color:#f59e0b}
|
||
.dl-sum-card.green .dl-sum-num{color:#22c55e}
|
||
.gantt{min-width:580px;font-family:var(--font-ui)}
|
||
.gantt-hdr{display:grid;grid-template-columns:170px 1fr;align-items:end;margin-bottom:6px;padding-bottom:8px;border-bottom:1.5px solid var(--line)}
|
||
.gantt-hdr-lbl{font-size:11px;font-weight:700;color:var(--mut);text-transform:uppercase;letter-spacing:.5px}
|
||
.gantt-dates{position:relative;height:22px}
|
||
.gantt-tick{position:absolute;transform:translateX(-50%);font-size:10px;color:var(--mut);font-weight:500;white-space:nowrap}
|
||
.gantt-today-hdr{position:absolute;transform:translateX(-50%);font-size:10px;font-weight:800;color:var(--bg);white-space:nowrap;top:-2px}
|
||
.gantt-row{display:grid;grid-template-columns:170px 1fr;align-items:center;margin-bottom:8px;cursor:pointer}
|
||
.gantt-row:hover .gantt-lbl{color:var(--bg)}
|
||
.gantt-lbl{padding-right:12px;overflow:hidden}
|
||
.gantt-lbl-name{font-size:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.gantt-lbl-sub{font-size:11px;color:var(--mut);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.gantt-track{position:relative;height:32px;background:var(--surf);border-radius:6px;overflow:visible}
|
||
.gantt-bar{position:absolute;height:100%;border-radius:6px;display:flex;align-items:center;padding:0 10px;font-size:11px;font-weight:700;color:#fff;white-space:nowrap;overflow:hidden;box-shadow:0 2px 8px rgba(0,0,0,.18);transition:filter .15s}
|
||
.gantt-bar:hover{filter:brightness(1.1)}
|
||
.gantt-bar.g-overdue{background:linear-gradient(90deg,#7f1d1d,#dc2626)}
|
||
.gantt-bar.g-urgent{background:linear-gradient(90deg,#9f1239,#e11d48)}
|
||
.gantt-bar.g-warn{background:linear-gradient(90deg,#92400e,#d97706)}
|
||
.gantt-bar.g-ok{background:linear-gradient(90deg,#1e3a8a,#3b82f6)}
|
||
.gantt-bar.g-done{background:linear-gradient(90deg,#14532d,#16a34a);opacity:.7}
|
||
.gantt-today-line{position:absolute;top:-4px;bottom:-4px;width:2px;background:var(--bg);border-radius:1px;z-index:10;pointer-events:none}
|
||
.gantt-today-line::after{content:'';position:absolute;top:0;left:50%;transform:translateX(-50%);width:8px;height:8px;background:var(--bg);border-radius:50%;margin-top:-3px}
|
||
.gantt-legend{display:flex;gap:14px;flex-wrap:wrap;margin-top:16px;padding-top:12px;border-top:1px solid var(--line)}
|
||
.gantt-leg-item{display:flex;align-items:center;gap:5px;font-size:11px;color:var(--mut)}
|
||
.gantt-leg-dot{width:10px;height:10px;border-radius:3px;flex-shrink:0}
|
||
|
||
/* ── GANTT ── */
|
||
(function() {
|
||
// Дата-хелперы
|
||
function d(str) { return new Date(str + 'T00:00:00'); }
|
||
function addDays(dt, n) { var r = new Date(dt); r.setDate(r.getDate()+n); return r; }
|
||
function daysBetween(a, b) { return Math.round((b-a)/86400000); }
|
||
function fmt(dt) {
|
||
var m = ['янв','фев','мар','апр','май','июн','июл','авг','сен','окт','ноя','дек'];
|
||
return dt.getDate() + ' ' + m[dt.getMonth()];
|
||
}
|
||
|
||
var CASES = [
|
||
{ ico:'🍽️', name:'Кухня — агентский', sub:'Протокол разногласий · ст.22 ЗоЗПП', start:'2025-05-19', end:'2025-05-26', cls:'g-urgent', go:"tab('case')" },
|
||
{ ico:'💼', name:'Трудовой договор', sub:'Допсоглашение (испыт. срок)', start:'2025-05-21', end:'2025-05-30', cls:'g-warn', go:"tab('case')" },
|
||
{ ico:'🏠', name:'ДДУ (новая редакция)',sub:'Сверка версий с застройщиком', start:'2025-05-19', end:'2025-06-05', cls:'g-ok', go:"tab('case')" },
|
||
{ ico:'📄', name:'Квартира · ДДУ', sub:'Передача квартиры · 214-ФЗ', start:'2025-05-27', end:'2025-06-22', cls:'g-ok', go:"toast('📅 Открываю дело')" },
|
||
];
|
||
|
||
function render() {
|
||
var root = document.getElementById('gantt-root');
|
||
if (!root) return;
|
||
|
||
var today = new Date(); today.setHours(0,0,0,0);
|
||
var rangeStart = d('2025-05-17');
|
||
var rangeEnd = d('2025-06-25');
|
||
var totalDays = daysBetween(rangeStart, rangeEnd);
|
||
|
||
function pct(dt) { return Math.max(0, Math.min(100, daysBetween(rangeStart, dt) / totalDays * 100)); }
|
||
|
||
// Шапка с датами
|
||
var tickDates = [];
|
||
var cur = new Date(rangeStart);
|
||
while (cur <= rangeEnd) {
|
||
tickDates.push(new Date(cur));
|
||
cur.setDate(cur.getDate() + 7);
|
||
}
|
||
|
||
var ticksHTML = tickDates.map(function(dt) {
|
||
var p = pct(dt);
|
||
return '<span class="gantt-tick" style="left:' + p.toFixed(1) + '%">' + fmt(dt) + '</span>';
|
||
}).join('');
|
||
|
||
var todayPct = pct(today);
|
||
var todayHdrHTML = '<span class="gantt-today-hdr" style="left:' + todayPct.toFixed(1) + '%">сегодня ▼</span>';
|
||
|
||
var hdrHTML = '<div class="gantt-hdr"><div class="gantt-hdr-lbl">Договор / дело</div><div class="gantt-dates">' + ticksHTML + todayHdrHTML + '</div></div>';
|
||
|
||
// Строки
|
||
var rowsHTML = CASES.map(function(c) {
|
||
var startPct = pct(d(c.start));
|
||
var endPct = pct(d(c.end));
|
||
var width = Math.max(4, endPct - startPct);
|
||
var daysLeft = daysBetween(today, d(c.end));
|
||
var lbl = daysLeft < 0 ? '⚠ просрочен' : daysLeft === 0 ? 'сегодня' : daysLeft + ' дн.';
|
||
var cls = c.cls;
|
||
if (daysLeft < 0) cls = 'g-overdue';
|
||
|
||
var todayLine = '<div class="gantt-today-line" style="left:' + todayPct.toFixed(1) + '%"></div>';
|
||
|
||
return '<div class="gantt-row" onclick="' + c.go + '">' +
|
||
'<div class="gantt-lbl"><div class="gantt-lbl-name">' + c.ico + ' ' + c.name + '</div><div class="gantt-lbl-sub">' + c.sub + '</div></div>' +
|
||
'<div class="gantt-track">' +
|
||
todayLine +
|
||
'<div class="gantt-bar ' + cls + '" style="left:' + startPct.toFixed(1) + '%;width:' + width.toFixed(1) + '%">' + fmt(d(c.end)) + ' · ' + lbl + '</div>' +
|
||
'</div>' +
|
||
'</div>';
|
||
}).join('');
|
||
|
||
// Легенда
|
||
var legend = '<div class="gantt-legend">' +
|
||
'<div class="gantt-leg-item"><div class="gantt-leg-dot" style="background:#dc2626"></div>Просрочен</div>' +
|
||
'<div class="gantt-leg-item"><div class="gantt-leg-dot" style="background:#e11d48"></div>Срочно (≤3 дня)</div>' +
|
||
'<div class="gantt-leg-item"><div class="gantt-leg-dot" style="background:#d97706"></div>Скоро (≤7 дней)</div>' +
|
||
'<div class="gantt-leg-item"><div class="gantt-leg-dot" style="background:#3b82f6"></div>В работе</div>' +
|
||
'<div class="gantt-leg-item"><div class="gantt-leg-dot" style="background:#16a34a;opacity:.7"></div>Завершён</div>' +
|
||
'</div>';
|
||
|
||
root.innerHTML = hdrHTML + rowsHTML + legend;
|
||
}
|
||
|
||
// Запускаем при открытии вкладки
|
||
var _origTab = window.tab;
|
||
window.tab = function(id) {
|
||
if (_origTab) _origTab(id);
|
||
if (id === 'sroki') setTimeout(render, 50);
|
||
};
|
||
window.addEventListener('DOMContentLoaded', function() {
|
||
// Если уже на вкладке sroki
|
||
var el = document.getElementById('p-sroki');
|
||
if (el && el.classList.contains('on')) render();
|
||
});
|
||
})();
|
||
|
||
|
||
/* ── ТАБЛИЦА ДОГОВОРОВ ── */
|
||
.ct-filters{display:flex;align-items:center;gap:0;margin-bottom:18px;background:#fff;border:1.5px solid #e5e7eb;border-radius:10px;padding:4px;width:fit-content}
|
||
.ct-filter-sep{width:1px;height:20px;background:#e5e7eb;margin:0 4px;flex-shrink:0}
|
||
.ct-fbtn{background:transparent;border:none;border-radius:7px;padding:6px 14px;font-size:12px;font-weight:600;cursor:pointer;color:#6b7280;font-family:inherit;transition:all .15s;white-space:nowrap}
|
||
.ct-fbtn:hover{color:var(--ink);background:#f3f4f6}
|
||
.ct-fbtn.act{background:var(--bg);color:#fff;box-shadow:0 1px 4px rgba(159,18,57,.25)}
|
||
.ct-add{margin-left:auto;background:var(--bg);color:#fff;border:none;border-radius:8px;padding:6px 14px;font-size:12px;font-weight:700;cursor:pointer;font-family:inherit}
|
||
.ct-add:hover{background:var(--bghv)}
|
||
.ct-table{width:100%;border-collapse:collapse;font-size:13px}
|
||
.ct-table thead tr{background:#f3f4f6;border-bottom:2px solid var(--line)}
|
||
.ct-table thead th{padding:8px 10px;text-align:left;font-size:11px;font-weight:700;color:var(--mut);text-transform:uppercase;letter-spacing:.4px;cursor:pointer;white-space:nowrap;user-select:none}
|
||
.ct-table thead th:hover{color:var(--bg)}
|
||
.ct-table thead th.sort-asc::after{content:' ↑'}
|
||
.ct-table thead th.sort-desc::after{content:' ↓'}
|
||
.ct-table tbody tr{border-bottom:1px solid var(--line);cursor:pointer;transition:background .12s}
|
||
.ct-table tbody tr:hover{background:#f8f8ff}
|
||
.ct-table tbody tr.ct-closed{opacity:.55}
|
||
.ct-table tbody td{padding:9px 10px;white-space:nowrap;vertical-align:middle}
|
||
.ct-table tbody td.ct-name{font-weight:600;max-width:220px;overflow:hidden;text-overflow:ellipsis}
|
||
.ct-table tbody td.ct-open{color:var(--bg);font-weight:700;font-size:13px;text-align:right}
|
||
.ct-type-badge{background:var(--surf);border:1px solid var(--line);border-radius:6px;padding:2px 7px;font-size:11px;color:var(--mut);font-weight:500}
|
||
|
||
/* ── MS-PROJECT GANTT ── */
|
||
.msp-section{margin-top:28px;border-top:2px solid var(--line);padding-top:16px}
|
||
.msp-title{font-size:13px;font-weight:800;color:var(--mut);text-transform:uppercase;letter-spacing:.6px;margin-bottom:12px}
|
||
.msp-outer{border:1.5px solid #d1d5db;border-radius:10px;overflow:hidden;font-size:12px;font-family:var(--font-ui)}
|
||
.msp-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
|
||
.msp-table{display:grid;min-width:820px}
|
||
/* Шапка */
|
||
.msp-head{display:flex;background:#e8e8f0;border-bottom:2px solid #b0b0c8;font-weight:700;font-size:11px;color:#444}
|
||
.msp-head .msp-left{display:flex;border-right:2px solid #b0b0c8;flex-shrink:0}
|
||
.msp-head .msp-right{flex:1;position:relative;overflow:hidden}
|
||
.msp-hcol{padding:6px 8px;border-right:1px solid #c8c8d8;white-space:nowrap;color:#333}
|
||
.msp-hcol.msp-c-num{width:32px;text-align:center}
|
||
.msp-hcol.msp-c-name{width:200px}
|
||
.msp-hcol.msp-c-dur{width:56px;text-align:center}
|
||
.msp-hcol.msp-c-start{width:72px;text-align:center}
|
||
.msp-hcol.msp-c-end{width:72px;text-align:center}
|
||
/* Строки */
|
||
.msp-row{display:flex;border-bottom:1px solid #e5e7eb;cursor:pointer}
|
||
.msp-row:hover{background:#f0f0ff}
|
||
.msp-row.msp-group{background:#f3f4f8;font-weight:700}
|
||
.msp-row.msp-done .msp-cell{color:#9ca3af}
|
||
.msp-row.msp-done .msp-c-name{text-decoration:line-through;color:#9ca3af}
|
||
.msp-row.msp-group.msp-done .msp-c-name{text-decoration:none;color:#6b7280}
|
||
.msp-bar.b-done{background:linear-gradient(180deg,#16a34a,#14532d)}
|
||
.msp-bar.b-done::after{content:' ✅';font-size:10px}
|
||
.msp-row.msp-active-row{background:#fffbf0}
|
||
.msp-row.msp-active-row:hover{background:#fff7e0}
|
||
.msp-bar.b-active::after{content:' ⏳'}
|
||
.msp-bar.b-urgent::after{content:' ⚠️'}
|
||
.msp-soa{display:flex;align-items:center;gap:8px;margin-bottom:10px;font-size:12px;color:var(--mut)}
|
||
.msp-soa-item{display:flex;align-items:center;gap:4px}
|
||
.msp-soa-dot{width:12px;height:12px;border-radius:2px;flex-shrink:0}
|
||
.msp-elena-note{display:flex;align-items:flex-start;gap:8px;background:#fffbf0;border:1px solid #fde68a;border-radius:10px;padding:10px 14px;margin-bottom:12px;font-size:12px;color:#92400e}
|
||
.msp-elena-note img{width:28px;height:28px;border-radius:50%;object-fit:cover;object-position:center 16%;flex-shrink:0}
|
||
|
||
.msp-row.msp-group:hover{background:#ebebf8}
|
||
.msp-row:last-child{border-bottom:none}
|
||
.msp-left{display:flex;border-right:2px solid #b0b0c8;flex-shrink:0}
|
||
.msp-right{flex:1;position:relative;height:28px;overflow:hidden}
|
||
.msp-cell{padding:6px 8px;border-right:1px solid #e5e7eb;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center}
|
||
.msp-cell.msp-c-num{width:32px;justify-content:center;color:#888;font-size:10px}
|
||
.msp-cell.msp-c-name{width:200px}
|
||
.msp-cell.msp-c-name.ind{padding-left:20px;font-weight:400;color:#333}
|
||
.msp-cell.msp-c-dur{width:56px;justify-content:center;color:#555}
|
||
.msp-cell.msp-c-start{width:72px;justify-content:center;color:#555;font-size:11px}
|
||
.msp-cell.msp-c-end{width:72px;justify-content:center;color:#555;font-size:11px}
|
||
/* Сетка и бары */
|
||
.msp-grid-bg{position:absolute;inset:0;display:flex}
|
||
.msp-grid-col{flex:1;border-right:1px solid #e8e8f0;height:100%}
|
||
.msp-grid-col.weekend{background:#f5f5fb}
|
||
.msp-bar-wrap{position:absolute;inset:0;pointer-events:none}
|
||
.msp-bar{position:absolute;top:5px;height:18px;border-radius:3px;display:flex;align-items:center;padding:0 6px;font-size:10px;font-weight:700;color:#fff;white-space:nowrap;overflow:hidden}
|
||
.msp-bar.b-group{background:linear-gradient(180deg,#4a4a8a,#2d2d6a);height:8px;top:10px;border-radius:1px}
|
||
.msp-bar.b-done{background:linear-gradient(180deg,#2d7a2d,#1a5c1a)}
|
||
.msp-bar.b-active{background:linear-gradient(180deg,#1a56db,#1e40af)}
|
||
.msp-bar.b-urgent{background:linear-gradient(180deg,#c81e1e,#991b1b)}
|
||
.msp-bar.b-pending{background:linear-gradient(180deg,#6b7280,#4b5563)}
|
||
.msp-today{position:absolute;top:0;bottom:0;width:2px;background:#c81e1e;z-index:5;pointer-events:none}
|
||
.msp-today::before{content:'▼';position:absolute;top:-1px;left:50%;transform:translateX(-50%);color:#c81e1e;font-size:9px;line-height:1}
|
||
/* Дата-шапка на сетке */
|
||
.msp-date-hdr{height:28px;position:relative;border-bottom:1px solid #c8c8d8;background:#e8e8f0}
|
||
.msp-date-tick{position:absolute;top:0;bottom:0;display:flex;align-items:center;font-size:10px;font-weight:700;color:#555;padding-left:4px;border-left:1px solid #c8c8d8;white-space:nowrap}
|
||
|
||
/* ── ELENA INTAKE v2 ── */
|
||
.intake-v2{margin:0 0 80px}
|
||
.intent-chips{display:flex;gap:10px;margin:4px 0 4px 51px;flex-wrap:wrap}
|
||
.intent-chip{background:var(--card);border:1.5px solid var(--line);border-radius:13px;padding:12px 16px;cursor:pointer;font-size:13px;font-weight:700;flex:1;min-width:160px;transition:border-color .15s,transform .1s}
|
||
.intent-chip:hover{border-color:var(--bg);transform:translateY(-1px)}
|
||
.intent-chip:active{transform:translateY(0)}
|
||
.intent-chip .ic-ico{font-size:20px;margin-bottom:4px}
|
||
.intent-chip .ic-lbl{font-weight:700;color:var(--ink)}
|
||
.intent-chip .ic-sub{font-size:11px;color:var(--mut);font-weight:400;margin-top:2px}
|
||
.voice-input-row{display:flex;gap:8px;margin:12px 0 12px 51px;align-items:center}
|
||
.voice-input-row input{flex:1;border:1.5px solid var(--line);border-radius:11px;padding:11px 14px;font-size:14px;font-family:inherit;outline:none;background:#fff;color:var(--ink)}
|
||
.voice-input-row input:focus{border-color:var(--bg)}
|
||
.voice-btn{width:44px;height:44px;border-radius:50%;border:1.5px solid var(--line);background:#fff;cursor:pointer;font-size:18px;display:flex;align-items:center;justify-content:center;transition:all .15s;flex-shrink:0}
|
||
.voice-btn:hover{border-color:var(--bg);background:var(--tint)}
|
||
.voice-btn.recording{background:#fee2e2;border-color:#ef4444;animation:voicePulse .8s ease infinite}
|
||
@keyframes voicePulse{0%,100%{box-shadow:0 0 0 0 rgba(239,68,68,.4)}50%{box-shadow:0 0 0 8px rgba(239,68,68,0)}}
|
||
.voice-btn.no-support{display:none}
|
||
.send-btn{width:44px;height:44px;border-radius:11px;border:none;background:var(--bg);color:#fff;cursor:pointer;font-size:16px;font-weight:700;flex-shrink:0}
|
||
.send-btn:hover{background:var(--bghv)}
|
||
.voice-hint{font-size:11px;color:var(--mut);margin:0 0 8px 51px}
|
||
/* Шаг составления */
|
||
.create-step{margin:8px 0 80px 0}
|
||
.create-type-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:4px 0 16px 51px}
|
||
.create-type-card{background:var(--card);border:1.5px solid var(--line);border-radius:13px;padding:14px;cursor:pointer;transition:border-color .15s}
|
||
.create-type-card:hover{border-color:var(--bg)}
|
||
.create-type-card .ctc-ico{font-size:24px;margin-bottom:6px}
|
||
.create-type-card .ctc-name{font-weight:700;font-size:13px}
|
||
.create-type-card .ctc-sub{font-size:11px;color:var(--mut);margin-top:2px}
|
||
|
||
/* ── КАРТОЧКА ДЕЛА CRM ── */
|
||
.case-hdr{background:#fff;border:1px solid #e5e7eb;border-radius:14px;padding:20px 22px;margin-bottom:20px;display:flex;align-items:flex-start;gap:18px}
|
||
.case-hdr-ico{width:52px;height:52px;border-radius:13px;background:var(--tint);display:flex;align-items:center;justify-content:center;font-size:26px;flex-shrink:0}
|
||
.case-hdr-info{flex:1;min-width:0}
|
||
.case-hdr-name{font-size:18px;font-weight:800;margin-bottom:6px;line-height:1.2}
|
||
.case-hdr-meta{display:flex;gap:8px;flex-wrap:wrap;align-items:center}
|
||
.case-hdr-actions{display:flex;gap:8px;flex-shrink:0;align-items:flex-start}
|
||
|
||
.next-step-v2{background:linear-gradient(135deg,#fff7f8,#fff);border:2px solid var(--bg);border-radius:16px;padding:20px 22px;margin-bottom:22px;display:flex;align-items:center;gap:16px;cursor:pointer;transition:box-shadow .15s}
|
||
.next-step-v2:hover{box-shadow:0 4px 20px rgba(159,18,57,.12)}
|
||
.ns2-pulse{width:48px;height:48px;border-radius:13px;background:var(--bg);display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;animation:nsPulse 2s ease-in-out infinite}
|
||
@keyframes nsPulse{0%,100%{box-shadow:0 0 0 0 rgba(159,18,57,.3)}50%{box-shadow:0 0 0 8px rgba(159,18,57,0)}}
|
||
.ns2-body{flex:1;min-width:0}
|
||
.ns2-label{font-size:11px;font-weight:700;color:var(--bg);text-transform:uppercase;letter-spacing:.6px;margin-bottom:4px}
|
||
.ns2-action{font-size:16px;font-weight:800;color:var(--ink);margin-bottom:4px}
|
||
.ns2-meta{font-size:12px;color:var(--mut)}
|
||
.ns2-deadline{background:#fee2e2;color:#991b1b;border-radius:7px;padding:2px 9px;font-size:11px;font-weight:700;margin-left:8px}
|
||
.ns2-btn{background:var(--bg);color:#fff;border:none;border-radius:10px;padding:10px 18px;font-size:13px;font-weight:700;cursor:pointer;font-family:inherit;flex-shrink:0;white-space:nowrap}
|
||
.ns2-btn:hover{background:var(--bghv)}
|
||
|
||
.case-tabs{display:flex;gap:0;border-bottom:2px solid #e5e7eb;margin-bottom:20px}
|
||
.case-tab{padding:10px 18px;font-size:13px;font-weight:600;color:#6b7280;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-2px;transition:all .15s}
|
||
.case-tab:hover{color:var(--ink)}
|
||
.case-tab.on{color:var(--bg);border-bottom-color:var(--bg);font-weight:700}
|
||
|
||
.case-pane{display:none}.case-pane.on{display:block}
|
||
|
||
.overview-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:20px}
|
||
.ov-card{background:#fff;border:1px solid #e5e7eb;border-radius:12px;padding:16px 18px}
|
||
.ov-card-ttl{font-size:11px;font-weight:700;color:var(--mut);text-transform:uppercase;letter-spacing:.5px;margin-bottom:10px}
|
||
.ov-row{display:flex;justify-content:space-between;align-items:center;padding:5px 0;border-bottom:1px solid #f3f4f6;font-size:13px}
|
||
.ov-row:last-child{border-bottom:none}
|
||
.ov-row .ov-k{color:var(--mut)}
|
||
.ov-row .ov-v{font-weight:600}
|
||
|
||
/* ── ELENA INTENT v3 ── */
|
||
.elena-q{font-size:15px;font-weight:700;color:var(--ink);margin:4px 0 14px 51px;line-height:1.4}
|
||
.intent-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:0 0 12px 51px;max-width:580px}
|
||
.int-card{background:#fff;border:2px solid #e5e7eb;border-radius:14px;padding:16px 14px;cursor:pointer;transition:all .15s;display:flex;align-items:flex-start;gap:12px}
|
||
.int-card:hover{border-color:var(--bg);background:var(--tint);transform:translateY(-1px);box-shadow:0 4px 14px rgba(159,18,57,.08)}
|
||
.int-card:active{transform:none}
|
||
.int-ico{font-size:24px;flex-shrink:0;line-height:1}
|
||
.int-body{}
|
||
.int-lbl{font-size:13px;font-weight:700;color:var(--ink);margin-bottom:2px}
|
||
.int-sub{font-size:11px;color:var(--mut);line-height:1.4}
|
||
.elena-voice-row{display:flex;align-items:center;gap:10px;margin:0 0 4px 51px}
|
||
.elena-voice-input{flex:1;border:1.5px solid var(--line);border-radius:10px;padding:10px 14px;font-size:13px;font-family:inherit;outline:none;max-width:440px}
|
||
.elena-voice-input:focus{border-color:var(--bg)}
|
||
.voice-btn-sm{background:var(--bg);color:#fff;border:none;border-radius:10px;padding:10px 14px;font-size:16px;cursor:pointer;flex-shrink:0;transition:background .15s}
|
||
.voice-btn-sm:hover{background:var(--bghv)}
|
||
.voice-btn-sm.pulse{animation:vPulse 1s ease-in-out infinite}
|
||
@keyframes vPulse{0%,100%{box-shadow:0 0 0 0 rgba(159,18,57,.4)}50%{box-shadow:0 0 0 8px rgba(159,18,57,0)}}
|
||
/* ── ELENA CHAT ENTRY v4 ── */
|
||
.elena-anim{opacity:0;transform:translateY(8px);animation:elFadeIn .38s ease forwards;animation-delay:var(--d,0s)}
|
||
@keyframes elFadeIn{to{opacity:1;transform:translateY(0)}}
|
||
.elena-dialog-wrap{margin:18px 0 10px 51px;max-width:560px}
|
||
.elena-dialog-row{display:flex;gap:8px;align-items:center;background:#fff;border:2.5px solid var(--bg);border-radius:14px;padding:10px 14px;box-shadow:0 0 0 5px rgba(159,18,57,.07)}
|
||
.elena-main-inp{flex:1;border:none;outline:none;font-size:14px;font-family:inherit;color:var(--ink);background:transparent;padding:6px 0}
|
||
.elena-main-inp::placeholder{color:#b0b7c3}
|
||
.elena-go-btn{background:var(--bg);color:#fff;border:none;border-radius:10px;padding:9px 20px;font-size:16px;font-weight:700;cursor:pointer;flex-shrink:0;transition:background .15s}
|
||
.elena-go-btn:hover{background:var(--bghv)}
|
||
.elena-quick{margin-top:4px}
|
||
.elena-q-lbl{font-size:11px;font-weight:700;color:var(--mut);margin:14px 0 10px 51px;letter-spacing:.04em}
|
||
|
||
/* Стартовый экран — усиление Елены */
|
||
.hero-elena-hint{background:rgba(255,255,255,.08);border-radius:12px;padding:12px 14px;margin:14px 0;font-size:12px;color:rgba(255,255,255,.7);line-height:1.5}
|
||
.hero-elena-hint b{color:#fff}
|
||
.hero-services{display:flex;flex-wrap:wrap;gap:6px;margin:12px 0}
|
||
.hero-svc{background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.2);border-radius:20px;padding:5px 13px;font-size:11px;font-weight:600;color:rgba(255,255,255,.85);white-space:nowrap}
|
||
|
||
/* ── СОСТАВИТЬ ДОКУМЕНТ ── */
|
||
.create-steps{display:flex;align-items:center;gap:0;margin-bottom:28px}
|
||
.cstep{display:flex;align-items:center;gap:8px;padding:9px 16px;border-radius:10px;font-size:13px;font-weight:600;color:var(--mut);border:1.5px solid #e5e7eb;background:#fff;transition:all .2s}
|
||
.cstep.act{background:var(--bg);color:#fff;border-color:var(--bg)}
|
||
.cstep.done{background:var(--tint);color:var(--bg);border-color:var(--bg)}
|
||
.cstep-num{width:20px;height:20px;border-radius:50%;background:rgba(0,0,0,.08);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:800}
|
||
.cstep.act .cstep-num{background:rgba(255,255,255,.25)}
|
||
.cstep.done .cstep-num{background:var(--bg);color:#fff}
|
||
.cstep-arrow{color:#d1d5db;font-size:18px;margin:0 6px;flex-shrink:0}
|
||
|
||
.create-pane{display:none}.create-pane.on{display:block}
|
||
|
||
/* Тип документа */
|
||
.doc-type-intro{font-size:14px;color:var(--mut);margin-bottom:20px;line-height:1.5}
|
||
.doc-type-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;max-width:800px;margin-bottom:24px}
|
||
.doc-type-card{background:#fff;border:2px solid #e5e7eb;border-radius:14px;padding:18px 14px;cursor:pointer;transition:all .15s;text-align:center}
|
||
.doc-type-card:hover{border-color:var(--bg);background:var(--tint);transform:translateY(-2px);box-shadow:0 4px 14px rgba(159,18,57,.1)}
|
||
.doc-type-card.sel{border-color:var(--bg);background:var(--tint);box-shadow:0 2px 10px rgba(159,18,57,.15)}
|
||
.dtc-ico{font-size:30px;margin-bottom:8px}
|
||
.dtc-name{font-size:12px;font-weight:700;color:var(--ink);line-height:1.3}
|
||
.dtc-desc{font-size:10px;color:var(--mut);margin-top:3px}
|
||
.doc-type-next{background:var(--bg);color:#fff;border:none;border-radius:11px;padding:12px 28px;font-size:14px;font-weight:700;cursor:pointer;font-family:inherit;transition:background .15s;display:none}
|
||
.doc-type-next.show{display:inline-flex;align-items:center;gap:8px}
|
||
.doc-type-next:hover{background:var(--bghv)}
|
||
|
||
/* Форма параметров */
|
||
.create-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;max-width:740px;margin-bottom:20px}
|
||
.cf-group{display:flex;flex-direction:column;gap:5px}
|
||
.cf-group.wide{grid-column:1/-1}
|
||
.cf-label{font-size:11px;font-weight:700;color:var(--mut);text-transform:uppercase;letter-spacing:.4px}
|
||
.cf-input{border:1.5px solid #e5e7eb;border-radius:9px;padding:10px 13px;font-size:13px;font-family:inherit;color:var(--ink);outline:none;transition:border-color .15s;background:#fff}
|
||
.cf-input:focus{border-color:var(--bg)}
|
||
.cf-select{border:1.5px solid #e5e7eb;border-radius:9px;padding:10px 13px;font-size:13px;font-family:inherit;color:var(--ink);outline:none;background:#fff;cursor:pointer}
|
||
.cf-hint{font-size:11px;color:var(--mut);margin-top:2px;line-height:1.4}
|
||
.create-form-actions{display:flex;gap:10px;margin-top:8px;max-width:740px}
|
||
.cf-back{background:#fff;color:var(--bg);border:1.5px solid var(--bg);border-radius:11px;padding:11px 22px;font-size:13px;font-weight:700;cursor:pointer;font-family:inherit}
|
||
.cf-generate{background:var(--bg);color:#fff;border:none;border-radius:11px;padding:11px 26px;font-size:14px;font-weight:700;cursor:pointer;font-family:inherit;display:flex;align-items:center;gap:8px}
|
||
.cf-generate:hover{background:var(--bghv)}
|
||
|
||
/* Превью документа */
|
||
.doc-generating{text-align:center;padding:40px 20px;display:none}
|
||
.doc-generating.show{display:block}
|
||
.dg-spinner{width:48px;height:48px;border:4px solid var(--tint);border-top-color:var(--bg);border-radius:50%;animation:spin .8s linear infinite;margin:0 auto 16px}
|
||
@keyframes spin{to{transform:rotate(360deg)}}
|
||
.dg-text{font-size:15px;font-weight:700;color:var(--ink);margin-bottom:6px}
|
||
.dg-sub{font-size:13px;color:var(--mut)}
|
||
|
||
.doc-preview-wrap{display:none;max-width:700px}
|
||
.doc-preview-wrap.show{display:block}
|
||
.doc-preview-actions{display:flex;gap:10px;margin-bottom:16px;flex-wrap:wrap}
|
||
.dpa-btn{display:flex;align-items:center;gap:7px;border-radius:10px;padding:10px 18px;font-size:13px;font-weight:700;cursor:pointer;font-family:inherit;border:none;transition:all .15s}
|
||
.dpa-dl{background:var(--bg);color:#fff}
|
||
.dpa-dl:hover{background:var(--bghv)}
|
||
.dpa-copy{background:#fff;color:var(--bg);border:1.5px solid var(--bg)}
|
||
.dpa-add{background:#f0fdf4;color:#166534;border:1.5px solid #86efac}
|
||
.doc-preview{background:#fff;border:1px solid #e5e7eb;border-radius:14px;padding:32px 36px;font-size:13px;line-height:1.8;color:#374151;font-family:Georgia,serif}
|
||
.doc-preview h3{font-family:var(--font-ui);font-size:15px;font-weight:800;text-align:center;margin-bottom:6px;color:var(--ink)}
|
||
.doc-preview .doc-city{text-align:right;font-size:12px;color:var(--mut);margin-bottom:20px}
|
||
.doc-preview .doc-p{margin-bottom:10px}
|
||
.doc-preview .doc-article{font-weight:700;margin-top:16px;margin-bottom:6px;font-family:var(--font-ui);font-size:12px;text-transform:uppercase;letter-spacing:.5px;color:var(--bg)}
|
||
.doc-preview .doc-clause{margin-bottom:6px;padding-left:12px;border-left:2px solid #e5e7eb}
|
||
.doc-preview .doc-highlight{background:#fef9c3;border-radius:3px;padding:1px 3px}
|
||
.doc-preview .doc-blank{background:#e5e7eb;border-radius:3px;padding:1px 8px;color:var(--mut);font-style:italic}
|
||
.doc-preview .doc-parties{background:#f8f9fa;border-radius:10px;padding:14px 16px;margin-bottom:16px;font-size:12px}
|
||
.doc-preview .doc-parties b{display:block;margin-bottom:4px;font-family:var(--font-ui)}
|
||
|
||
/* ── ЧАСЫ В САЙДБАРЕ ── */
|
||
.side-clock{padding:10px 16px 6px;border-top:1px solid rgba(255,255,255,.07);margin-top:auto}
|
||
.side-clock-day{font-size:10px;font-weight:600;color:rgba(255,255,255,.45);text-transform:uppercase;letter-spacing:.5px;margin-bottom:2px}
|
||
.side-clock-date{font-size:13px;font-weight:700;color:rgba(255,255,255,.85);margin-bottom:2px}
|
||
.side-clock-time{font-size:18px;font-weight:800;color:#fff;letter-spacing:.5px;font-variant-numeric:tabular-nums}
|
||
|
||
/* ── ПАНЕЛЬ ПРОТОКОЛА ── */
|
||
.protocol-bar{display:none;align-items:center;gap:14px;background:linear-gradient(135deg,#fff7f8,#fff);border:2px solid var(--bg);border-radius:14px;padding:14px 18px;margin-bottom:18px;animation:slideIn .25s ease}
|
||
.protocol-bar.show{display:flex}
|
||
@keyframes slideIn{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
|
||
.pb-ico{font-size:22px;flex-shrink:0}
|
||
.pb-body{flex:1;min-width:0}
|
||
.pb-title{font-size:13px;font-weight:800;color:var(--ink)}
|
||
.pb-sub{font-size:11px;color:var(--mut);margin-top:1px}
|
||
.pb-btn{background:var(--bg);color:#fff;border:none;border-radius:10px;padding:10px 20px;font-size:13px;font-weight:700;cursor:pointer;font-family:inherit;white-space:nowrap;flex-shrink:0}
|
||
.pb-btn:hover{background:var(--bghv)}
|
||
|
||
/* ── ПЕРЕПИСКА ── */
|
||
.chat-compose{background:#fff;border:1.5px solid var(--line);border-radius:14px;padding:18px 20px;margin-bottom:18px;max-width:700px}
|
||
.chat-compose-ttl{font-size:13px;font-weight:700;margin-bottom:12px;color:var(--ink)}
|
||
.chat-field{margin-bottom:10px}
|
||
.chat-field label{font-size:11px;font-weight:600;color:var(--mut);text-transform:uppercase;letter-spacing:.4px;display:block;margin-bottom:4px}
|
||
.chat-field input,.chat-field textarea{width:100%;border:1px solid var(--line);border-radius:8px;padding:9px 12px;font-size:13px;font-family:inherit;color:var(--ink);resize:vertical;outline:none;transition:border-color .15s}
|
||
.chat-field input:focus,.chat-field textarea:focus{border-color:var(--bg)}
|
||
.chat-actions{display:flex;gap:8px;margin-top:4px}
|
||
.chat-send-btn{background:var(--bg);color:#fff;border:none;border-radius:9px;padding:9px 20px;font-size:13px;font-weight:700;cursor:pointer;font-family:inherit}
|
||
.chat-send-btn:hover{background:var(--bghv)}
|
||
.chat-copy-btn{background:#fff;color:var(--bg);border:1.5px solid var(--bg);border-radius:9px;padding:9px 16px;font-size:13px;font-weight:600;cursor:pointer;font-family:inherit}
|
||
.chat-list{max-width:700px}
|
||
.chat-list-ttl{font-size:11px;font-weight:700;color:var(--mut);text-transform:uppercase;letter-spacing:.4px;margin-bottom:10px}
|
||
.chat-item{display:flex;gap:12px;align-items:flex-start;padding:12px 14px;background:#fff;border:1px solid var(--line);border-radius:12px;margin-bottom:8px;cursor:pointer;transition:box-shadow .12s}
|
||
.chat-item:hover{box-shadow:0 2px 10px rgba(0,0,0,.07)}
|
||
.chat-item.out .chat-arrow{color:var(--bg);font-size:16px;flex-shrink:0;margin-top:2px}
|
||
.chat-item.inc .chat-arrow{color:#16a34a;font-size:16px;flex-shrink:0;margin-top:2px}
|
||
.chat-item-body{flex:1;min-width:0}
|
||
.chat-item-hdr{display:flex;justify-content:space-between;align-items:center;margin-bottom:3px}
|
||
.chat-item-subj{font-size:13px;font-weight:700;color:var(--ink)}
|
||
.chat-item-date{font-size:11px;color:var(--mut);flex-shrink:0;margin-left:8px}
|
||
.chat-item-prev{font-size:12px;color:var(--mut);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.chat-status{font-size:10px;font-weight:700;padding:2px 7px;border-radius:6px;flex-shrink:0}
|
||
.chat-status.sent{background:#dbeafe;color:#1d4ed8}
|
||
.chat-status.read{background:#dcfce7;color:#166534}
|
||
.chat-status.new{background:#fee2e2;color:#991b1b}
|
||
|
||
/* ── РИСКИ АККОРДЕОН ── */
|
||
.risk-item{cursor:pointer}
|
||
.risk-toggle{margin-left:auto;color:var(--mut);font-size:11px;transition:transform .2s;flex-shrink:0;padding-left:8px}
|
||
.risk-item.expanded .risk-toggle{transform:rotate(180deg)}
|
||
.risk-expand{display:none;margin-top:12px;border-top:1px solid #f3f4f6;padding-top:12px}
|
||
.risk-item.expanded .risk-expand{display:block}
|
||
.risk-quote{background:#fff5f5;border:1px solid #fecaca;border-radius:8px;padding:10px 13px;margin-bottom:8px}
|
||
.risk-quote-lbl{font-size:10px;font-weight:700;color:#991b1b;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px}
|
||
.risk-quote-txt{font-size:12px;color:#374151;font-style:italic;line-height:1.6}
|
||
.risk-fix{background:#f0fdf4;border:1px solid #86efac;border-radius:8px;padding:10px 13px;margin-bottom:10px}
|
||
.risk-fix-lbl{font-size:10px;font-weight:700;color:#166534;text-transform:uppercase;letter-spacing:.4px;margin-bottom:5px}
|
||
.risk-fix-txt{font-size:12px;color:#374151;line-height:1.6}
|
||
.risk-apply-btn{background:var(--bg);color:#fff;border:none;border-radius:8px;padding:8px 18px;font-size:12px;font-weight:700;cursor:pointer;font-family:inherit;transition:background .15s}
|
||
.risk-apply-btn:hover{background:var(--bghv)}
|
||
|
||
/* ── КАРТОЧКА ДЕЛА v2 ── */
|
||
|
||
/* Прогресс-шаги */
|
||
.case-progress{display:flex;align-items:flex-start;gap:0;margin-bottom:20px;overflow-x:auto;padding-bottom:4px}
|
||
.cp-step{display:flex;flex-direction:column;align-items:center;flex:1;min-width:90px;position:relative}
|
||
.cp-step:not(:last-child)::after{content:'';position:absolute;top:14px;left:calc(50% + 16px);right:calc(-50% + 16px);height:2px;background:#e5e7eb;z-index:0}
|
||
.cp-step.done .cp-step:not(:last-child)::after,.cp-step.act::after,.cp-step.done::after{background:var(--bg)}
|
||
.cps-dot{width:28px;height:28px;border-radius:50%;border:2px solid #e5e7eb;background:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;z-index:1;position:relative;flex-shrink:0}
|
||
.cp-step.done .cps-dot{background:var(--bg);border-color:var(--bg);color:#fff}
|
||
.cp-step.act .cps-dot{background:#fff;border-color:var(--bg);box-shadow:0 0 0 3px rgba(159,18,57,.15)}
|
||
.cp-step.pend .cps-dot{background:#f9fafb;border-color:#d1d5db;color:#9ca3af}
|
||
.cps-lbl{font-size:10px;font-weight:600;margin-top:6px;text-align:center;color:var(--mut);max-width:80px;line-height:1.3}
|
||
.cp-step.done .cps-lbl{color:var(--bg)}
|
||
.cp-step.act .cps-lbl{color:var(--ink);font-weight:700}
|
||
.cps-date{font-size:9px;color:var(--mut);margin-top:2px;text-align:center}
|
||
.cp-step.act .cps-date{color:var(--bg)}
|
||
|
||
/* Риски */
|
||
.risk-summary{display:flex;gap:10px;margin-bottom:16px;flex-wrap:wrap}
|
||
.risk-sum-item{display:flex;align-items:center;gap:6px;background:#fff;border:1px solid #e5e7eb;border-radius:10px;padding:7px 14px;font-size:13px;font-weight:700}
|
||
.risk-sum-item.crit{border-color:#fecaca;background:#fff5f5;color:#991b1b}
|
||
.risk-sum-item.mid{border-color:#fde68a;background:#fffbeb;color:#92400e}
|
||
.risk-sum-item.low{border-color:#bbf7d0;background:#f0fdf4;color:#166534}
|
||
|
||
.risk-list{display:flex;flex-direction:column;gap:8px;max-width:760px}
|
||
.risk-item{background:#fff;border:1px solid #e5e7eb;border-radius:12px;padding:14px 16px;cursor:pointer;transition:box-shadow .12s}
|
||
.risk-item:hover{box-shadow:0 2px 12px rgba(0,0,0,.07)}
|
||
.risk-item.crit{border-left:4px solid #ef4444}
|
||
.risk-item.mid{border-left:4px solid #f59e0b}
|
||
.risk-item.low{border-left:4px solid #22c55e}
|
||
.risk-item-hdr{display:flex;align-items:center;gap:10px;margin-bottom:6px}
|
||
.risk-badge{font-size:10px;font-weight:700;padding:2px 8px;border-radius:6px;flex-shrink:0;white-space:nowrap}
|
||
.risk-badge.crit{background:#fee2e2;color:#991b1b}
|
||
.risk-badge.mid{background:#fef3c7;color:#92400e}
|
||
.risk-badge.low{background:#dcfce7;color:#166534}
|
||
.risk-num{font-size:11px;color:var(--mut);flex-shrink:0}
|
||
.risk-title{font-size:13px;font-weight:700;color:var(--ink);flex:1}
|
||
.risk-norm{font-size:11px;color:var(--mut);margin-bottom:6px}
|
||
.risk-rec{font-size:12px;color:var(--ink);line-height:1.5;background:#f8f9fa;border-radius:7px;padding:7px 10px}
|
||
|
||
/* Документы: upload zone */
|
||
.doc-upload-btn{display:flex;align-items:center;gap:10px;border:2px dashed #d1d5db;border-radius:12px;padding:14px 18px;margin-bottom:14px;cursor:pointer;transition:border-color .15s;max-width:700px;background:#fafafa}
|
||
.doc-upload-btn:hover{border-color:var(--bg);background:#fff7f8}
|
||
.doc-upload-ico{font-size:22px}
|
||
.doc-upload-txt{font-size:13px;font-weight:600;color:var(--mut)}
|
||
.doc-upload-txt span{display:block;font-size:11px;font-weight:400;margin-top:1px}
|
||
|
||
/* ── RETURNING CLIENT ── */
|
||
.ret-greet{font-size:30px;font-weight:800;line-height:1.2;margin-bottom:24px;letter-spacing:-.5px}
|
||
.ret-sub{font-size:16px;color:rgba(255,255,255,.7);margin-bottom:22px}
|
||
.ret-card{background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.2);border-radius:14px;padding:16px 18px;margin-bottom:22px}
|
||
.ret-card:empty{display:none}
|
||
/* ── HERO TYPEWRITER ── */
|
||
.hero-tw-wrap{margin:14px 0 4px;display:flex;align-items:center;gap:7px;min-height:28px}
|
||
.hero-tw-cur{color:rgba(255,255,255,.5);font-size:18px;flex-shrink:0;line-height:1;animation:twBlink .65s step-start infinite}
|
||
@keyframes twBlink{0%,100%{opacity:1}50%{opacity:0}}
|
||
.hero-tw-text{font-size:14px;font-weight:600;color:rgba(255,255,255,.82);line-height:1.4}
|
||
.ret-tw-wrap{margin:0 0 22px;display:flex;align-items:baseline;gap:7px;min-height:32px}
|
||
.ret-tw-wrap .hero-tw-cur{font-size:20px;color:rgba(255,255,255,.45)}
|
||
.ret-tw-wrap .hero-tw-text{font-size:18px;font-weight:700;color:rgba(255,255,255,.95)}
|
||
.ret-ord-lbl{font-size:11px;font-weight:700;color:rgba(255,255,255,.45);text-transform:uppercase;letter-spacing:.6px;margin-bottom:7px}
|
||
.ret-ord-name{font-size:15px;font-weight:700;margin-bottom:3px}
|
||
.ret-ord-price{font-size:22px;font-weight:800;color:#ffaaaa}
|
||
|
||
/* ── ЮKASSA ВИДЖЕТ ── */
|
||
.yk-overlay{position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:99990;display:none;align-items:flex-end;justify-content:center}
|
||
.yk-overlay.open{display:flex}
|
||
@media(min-width:520px){.yk-overlay{align-items:center}}
|
||
.yk-sheet{background:#fff;border-radius:20px 20px 0 0;width:100%;max-width:420px;padding:24px 20px 32px;position:relative;box-shadow:0 -8px 40px rgba(0,0,0,.18);animation:ykUp .25s ease}
|
||
@media(min-width:520px){.yk-sheet{border-radius:20px}}
|
||
@keyframes ykUp{from{transform:translateY(60px);opacity:0}to{transform:none;opacity:1}}
|
||
.yk-close{position:absolute;top:14px;right:16px;background:none;border:none;font-size:20px;cursor:pointer;color:#9ca3af;line-height:1}
|
||
.yk-header{display:flex;align-items:center;gap:10px;margin-bottom:20px}
|
||
.yk-logo{font-size:13px;font-weight:800;color:#0057FF;letter-spacing:-.5px}
|
||
.yk-logo span{color:#FF3D00}
|
||
.yk-amount{margin-left:auto;font-size:18px;font-weight:800;color:#111}
|
||
.yk-field{margin-bottom:14px}
|
||
.yk-field label{display:block;font-size:12px;color:#6b7280;font-weight:600;margin-bottom:5px;font-family:inherit}
|
||
.yk-field input{width:100%;border:1.5px solid #e5e7eb;border-radius:10px;padding:11px 14px;font-size:15px;font-family:inherit;outline:none;color:#111;background:#fff;box-sizing:border-box;transition:border-color .15s}
|
||
.yk-field input:focus{border-color:#0057FF}
|
||
.yk-field input.yk-error{border-color:#ef4444}
|
||
.yk-row{display:grid;grid-template-columns:1fr 1fr;gap:12px}
|
||
.yk-sbp{display:flex;align-items:center;justify-content:center;gap:8px;border:1.5px solid #e5e7eb;border-radius:10px;padding:11px 14px;cursor:pointer;font-size:14px;font-weight:600;color:#111;margin-bottom:14px;transition:border-color .15s;font-family:inherit;background:#fff;width:100%;box-sizing:border-box}
|
||
.yk-sbp:hover{border-color:#0057FF;color:#0057FF}
|
||
.yk-sbp-icon{width:24px;height:14px;background:linear-gradient(90deg,#1D63D8 33%,#fff 33% 66%,#ED1C24 66%);border-radius:3px;font-size:9px;display:flex;align-items:center;justify-content:center;color:#fff;font-weight:900;letter-spacing:-.5px}
|
||
.yk-sep{display:flex;align-items:center;gap:8px;color:#9ca3af;font-size:12px;margin:12px 0}
|
||
.yk-sep::before,.yk-sep::after{content:'';flex:1;height:1px;background:#e5e7eb}
|
||
.yk-pay-btn{width:100%;background:#0057FF;color:#fff;border:none;border-radius:12px;padding:15px;font-size:16px;font-weight:800;cursor:pointer;font-family:inherit;margin-top:4px;transition:background .15s}
|
||
.yk-pay-btn:hover{background:#0046CC}
|
||
.yk-pay-btn:disabled{background:#9ca3af;cursor:default}
|
||
.yk-footer{text-align:center;font-size:11px;color:#9ca3af;margin-top:12px}
|
||
.yk-footer a{color:#9ca3af}
|
||
.yk-spinner{display:none;width:20px;height:20px;border:3px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:ykSpin .7s linear infinite;margin:0 auto}
|
||
@keyframes ykSpin{to{transform:rotate(360deg)}}
|
||
.yk-success{display:none;text-align:center;padding:20px 0 8px}
|
||
.yk-success .yk-check{font-size:48px;margin-bottom:12px}
|
||
.yk-success .yk-sttl{font-size:18px;font-weight:800;color:#111;margin-bottom:6px}
|
||
.yk-success .yk-ssub{font-size:13px;color:#6b7280}
|
||
|
||
/* ── ЭКРАН СТАТУСА ЗАКАЗА ── */
|
||
.os-wrap{max-width:560px;margin:0 auto;padding:24px 20px 60px}
|
||
.os-ok{text-align:center;margin:8px 0 20px}
|
||
.os-ok-icon{font-size:44px;margin-bottom:8px}
|
||
.os-ok-ttl{font-size:20px;font-weight:800;color:var(--bg)}
|
||
.os-ok-sub{font-size:13px;color:var(--mut);margin-top:4px}
|
||
.os-card{background:var(--card);border:1.5px solid var(--line);border-radius:14px;padding:16px 18px;margin-bottom:20px}
|
||
.os-card .oc-ttl{font-size:16px;font-weight:800;margin-bottom:4px}
|
||
.os-card .oc-plan{font-size:13px;color:var(--mut);margin-bottom:10px}
|
||
.os-card .oc-price{font-size:22px;font-weight:800;color:var(--bg)}
|
||
.os-card .oc-id{font-size:11px;color:var(--mut);margin-top:4px;letter-spacing:.3px}
|
||
.os-steps{display:flex;align-items:flex-start;gap:0;margin:0 0 20px;position:relative}
|
||
.os-steps::before{content:'';position:absolute;top:13px;left:13px;right:13px;height:2px;background:var(--line);z-index:0}
|
||
.os-step{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;position:relative;z-index:1}
|
||
.os-dot{width:26px;height:26px;border-radius:50%;border:2.5px solid var(--line);background:var(--surf);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;color:var(--mut);flex-shrink:0}
|
||
.os-step.done .os-dot{background:var(--ok);border-color:var(--ok);color:#fff;font-size:13px}
|
||
.os-step.active .os-dot{background:var(--bg);border-color:var(--bg);color:#fff;font-size:13px}
|
||
.os-step-lbl{font-size:11px;color:var(--mut);text-align:center;line-height:1.35;max-width:80px}
|
||
.os-step.done .os-step-lbl{color:var(--ok);font-weight:600}
|
||
.os-step.active .os-step-lbl{color:var(--bg);font-weight:700}
|
||
.os-deadline{background:var(--tint);border:1.5px solid rgba(159,18,57,.2);border-radius:10px;padding:10px 14px;font-size:13px;margin:0 0 16px;display:flex;align-items:center;gap:8px}
|
||
.os-deadline .od-icon{font-size:16px}
|
||
.os-deadline .od-text strong{display:block;font-weight:700;color:var(--bg);font-size:13px}
|
||
.os-deadline .od-text span{font-size:12px;color:var(--mut)}
|
||
.os-actions{display:flex;gap:10px;flex-wrap:wrap}
|
||
.os-tg{display:flex;align-items:center;gap:8px;background:var(--card);border:1.5px solid var(--line);border-radius:10px;padding:10px 16px;font-size:13px;font-weight:700;cursor:pointer;color:var(--ink);text-decoration:none;font-family:inherit}
|
||
.os-tg:hover{border-color:var(--bg);color:var(--bg)}
|
||
|
||
/* ── АНАЛИТИКА CUSTOM-ЗАПРОСОВ ── */
|
||
#custom-admin{background:var(--surf)}
|
||
.ca-wrap{max-width:780px;margin:0 auto;padding:28px 20px 60px}
|
||
.ca-title{font-size:20px;font-weight:800;margin-bottom:4px}
|
||
.ca-sub{font-size:13px;color:var(--mut);margin-bottom:24px}
|
||
.ca-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:24px}
|
||
.ca-stat{background:var(--card);border:1px solid var(--line);border-radius:13px;padding:14px 16px}
|
||
.ca-stat .sv{font-size:26px;font-weight:800;color:var(--bg)}
|
||
.ca-stat .sl{font-size:11px;color:var(--mut);margin-top:2px;text-transform:uppercase;letter-spacing:.5px}
|
||
.ca-section{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;color:var(--mut);margin:20px 0 10px}
|
||
.ca-words{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:24px}
|
||
.ca-word{background:var(--card);border:1.5px solid var(--line);border-radius:20px;padding:5px 12px;font-size:13px;font-weight:600;display:flex;align-items:center;gap:6px;cursor:default}
|
||
.ca-word .wc{background:var(--bg);color:#fff;border-radius:10px;font-size:10px;padding:1px 6px;font-weight:700}
|
||
.ca-word.w-top{border-color:rgba(159,18,57,.4);background:var(--tint)}
|
||
.ca-card{background:var(--card);border:1px solid var(--line);border-radius:13px;padding:14px 16px;margin-bottom:10px}
|
||
.ca-card.ca-done{opacity:.5;border-style:dashed}
|
||
.ca-card .cc-head{display:flex;align-items:center;gap:10px;margin-bottom:8px}
|
||
.ca-card .cc-ctype{font-size:11px;font-weight:700;background:var(--tint);color:var(--bg);padding:2px 8px;border-radius:8px}
|
||
.ca-card .cc-ts{font-size:11px;color:var(--mut);margin-left:auto}
|
||
.ca-card .cc-text{font-size:13.5px;line-height:1.6;color:var(--ink);margin-bottom:10px}
|
||
.ca-card .cc-actions{display:flex;gap:8px}
|
||
.ca-card .cc-add{background:var(--bg);color:#fff;border:none;border-radius:8px;padding:6px 14px;font-size:12px;font-weight:700;cursor:pointer;font-family:inherit}
|
||
.ca-card .cc-add:disabled{background:var(--ok);cursor:default}
|
||
.ca-card .cc-copy{background:none;border:1.5px solid var(--line);border-radius:8px;padding:6px 12px;font-size:12px;cursor:pointer;font-family:inherit;color:var(--mut)}
|
||
.ca-card .cc-copy:hover{border-color:var(--bg);color:var(--bg)}
|
||
.ca-export{display:flex;gap:10px;margin-top:20px;flex-wrap:wrap}
|
||
.ca-export button{background:var(--card);border:1.5px solid var(--line);border-radius:10px;padding:10px 18px;font-size:13px;font-weight:700;cursor:pointer;font-family:inherit;color:var(--ink)}
|
||
.ca-export button:hover{border-color:var(--bg);color:var(--bg)}
|
||
.ca-empty{text-align:center;padding:60px 20px;color:var(--mut);font-size:14px}
|
||
.ca-empty .ce-icon{font-size:40px;margin-bottom:12px}
|
||
@media(max-width:600px){.ca-stats{grid-template-columns:1fr 1fr}.ca-stat:last-child{grid-column:1/-1}}
|
||
|
||
/* тост-подтверждение действий без отдельного экрана */
|
||
.toast{position:fixed;left:50%;bottom:28px;transform:translateX(-50%) translateY(20px);background:#0C0608;color:#fff;padding:13px 20px;border-radius:13px;font-size:13.5px;font-weight:600;box-shadow:0 10px 30px rgba(0,0,0,.3);opacity:0;pointer-events:none;transition:all .25s;z-index:999;max-width:min(90vw,520px);display:flex;align-items:center;gap:9px}
|
||
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
|
||
.toast .tk{color:#FECDD3}
|
||
.docrow{cursor:pointer}.docrow:hover{color:var(--bg)}
|
||
|
||
/* ── дедлайн-виджет / следующий шаг ── */
|
||
.next-step{background:var(--tint);border:1.5px solid rgba(159,18,57,.25);border-radius:13px;padding:13px 16px;display:flex;align-items:center;gap:13px;max-width:760px;margin:14px 0 16px;cursor:pointer}
|
||
.next-step:hover{border-color:var(--bg);box-shadow:0 4px 14px rgba(159,18,57,.12)}
|
||
.ns-icon{font-size:22px;flex-shrink:0}
|
||
.ns-body{flex:1}
|
||
.ns-title{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1.2px;color:var(--bg);margin-bottom:2px}
|
||
.ns-text{font-size:13.5px;font-weight:600;color:var(--dark)}
|
||
.ns-sub{font-size:12px;color:var(--mut);margin-top:1px}
|
||
.ns-btn{background:var(--bg);color:#fff;border:none;border-radius:9px;padding:9px 16px;font-size:13px;font-weight:700;cursor:pointer;flex-shrink:0;font-family:inherit}
|
||
.ns-btn:hover{background:var(--bghv)}
|
||
|
||
/* ── таймлайн дела ── */
|
||
.tl-section{max-width:760px;margin:22px 0 0}
|
||
.tl-label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1.2px;color:var(--mut);margin-bottom:14px}
|
||
.tl{display:flex;flex-direction:column;gap:0;position:relative;padding-left:22px}
|
||
.tl::before{content:'';position:absolute;left:7px;top:6px;bottom:6px;width:2px;background:var(--line)}
|
||
.tl-item{position:relative;padding:0 0 18px 18px}
|
||
.tl-item:last-child{padding-bottom:0}
|
||
.tl-dot{position:absolute;left:-8px;top:5px;width:14px;height:14px;border-radius:50%;background:var(--line);border:2px solid #fff;z-index:1;box-sizing:border-box}
|
||
.tl-item.done .tl-dot{background:var(--ok);border-color:#fff}
|
||
.tl-item.active .tl-dot{background:var(--bg);border-color:#fff;box-shadow:0 0 0 3px rgba(159,18,57,.18)}
|
||
.tl-item.pending .tl-dot{background:#fff;border:2px solid var(--line)}
|
||
.tl-date{font-size:11px;color:var(--mut);font-weight:600;margin-bottom:1px}
|
||
.tl-title{font-size:13px;font-weight:700;color:var(--dark)}
|
||
.tl-item.active .tl-title{color:var(--bg)}
|
||
.tl-item.pending .tl-title{color:var(--mut)}
|
||
.tl-ev{font-size:12px;color:var(--mut);margin-top:2px}
|
||
|
||
/* ── RESPONSIVE · MOBILE / TELEGRAM MINIAPP ── */
|
||
@media (max-width:600px){
|
||
/* HERO — мобиль: лого → фото → текст */
|
||
.hero{grid-template-columns:1fr;grid-template-rows:auto auto auto;padding:0 0 32px;gap:0;align-items:start}
|
||
.hero-logo{grid-column:1;grid-row:1;padding:20px 18px 0;margin-bottom:0}
|
||
.hero .face{grid-column:1;grid-row:2;margin:14px 0 0}
|
||
.hero-body{grid-column:1;grid-row:3;padding:20px 18px 0}
|
||
.hero .face img{height:240px;min-height:unset;border-radius:0;object-position:center 12%}
|
||
.hero .face .cap{padding:0 18px;color:rgba(255,255,255,.6)}
|
||
.hero h1{font-size:26px;letter-spacing:-.5px}
|
||
.hero p{font-size:14px;margin-bottom:20px}
|
||
.hero .cta{flex-direction:column}
|
||
.hero .cta .btn{width:100%;text-align:center}
|
||
|
||
/* TOPBAR */
|
||
.topbar{padding:10px 14px}
|
||
.topbar .ttl{font-size:12px;max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||
.topbar a{font-size:12px}
|
||
|
||
/* CHAT — убираем левый отступ под аватар на мобиле */
|
||
.chatwrap{padding:14px 12px 100px}
|
||
.intake{margin:4px 0 4px 0}
|
||
.deliverables{margin:4px 0 4px 0;max-width:100%}
|
||
.mode-badge{margin-left:0}
|
||
|
||
/* TOUCH TARGETS ≥ 48px */
|
||
.intake-opt{padding:14px 14px;min-height:52px}
|
||
.deliv{padding:14px 14px;min-height:56px}
|
||
.btn{min-height:48px}
|
||
|
||
/* ACTBAR — кнопки в колонку */
|
||
.actbar .inner{flex-direction:column;gap:8px}
|
||
.actbar .inner .btn{width:100%;text-align:center}
|
||
|
||
/* NEXT-STEP WIDGET — стек на мобиле */
|
||
.next-step{flex-wrap:wrap;gap:10px}
|
||
.ns-btn{width:100%;text-align:center}
|
||
.ns-body{min-width:0;width:100%}
|
||
|
||
/* PAY */
|
||
.pay{padding:20px 14px}
|
||
.pay h2{font-size:20px}
|
||
.plan-what{padding:12px 13px}
|
||
.plan-pitch{padding:12px 13px;flex-direction:row;align-items:flex-start}
|
||
|
||
/* STAT PILL — не перекрывает actbar */
|
||
.stats-pill{bottom:100px;right:10px;font-size:10px;min-width:140px}
|
||
|
||
/* ДОКУМЕНТЫ / КЕЙСЫ */
|
||
.tab-content{padding:14px 0}
|
||
|
||
/* КАБИНЕТ — мобиль: сайдбар скрыть, контент на всю ширину */
|
||
.app{flex-direction:column}
|
||
.side{width:100%;flex-direction:row;flex-wrap:wrap;padding:8px 0 0;gap:0;min-height:unset}
|
||
.side .lg{display:none}
|
||
.side .prof{display:none}
|
||
.side a{padding:8px 12px;font-size:12px;flex-direction:column;gap:2px;border-left:none;border-bottom:2px solid transparent;text-align:center;flex:1}
|
||
.side a.on{background:rgba(159,18,57,.2);border-left:none;border-bottom-color:var(--bg)}
|
||
.main{padding:16px 14px}
|
||
}
|
||
|
||
/* ── TELEGRAM MINIAPP ── */
|
||
/* Класс .tma навешивается JS-слоем ниже если запущен внутри TG */
|
||
.tma .actbar{padding-bottom:calc(16px + env(safe-area-inset-bottom,0px))}
|
||
.tma .topbar a.back-link{display:none} /* кнопка «назад» — нативная TG BackButton */
|
||
|
||
/* ── UPLOAD STEP ── */
|
||
.upload-zone{border:2px dashed rgba(159,18,57,.25);border-radius:16px;padding:28px 20px;text-align:center;background:var(--card);cursor:pointer;transition:border-color .2s,background .2s;margin:12px 0}
|
||
.upload-zone:hover{border-color:var(--bg);background:var(--tint)}
|
||
.uz-icon{font-size:32px;margin-bottom:10px}
|
||
.uz-title{font-size:15px;font-weight:700;color:var(--dark);margin-bottom:4px}
|
||
.uz-sub{font-size:12px;color:var(--mut)}
|
||
.upload-paste{width:100%;border:1.5px solid var(--line);border-radius:12px;padding:14px 16px;font-family:inherit;font-size:14px;color:var(--ink);background:var(--card);resize:vertical;min-height:90px;margin:8px 0;display:block}
|
||
.upload-paste:focus{outline:none;border-color:var(--bg)}
|
||
.upload-or{display:flex;align-items:center;gap:12px;color:var(--mut);font-size:12px;margin:4px 0}
|
||
.upload-or::before,.upload-or::after{content:'';flex:1;height:1px;background:var(--line)}
|
||
.upload-box{max-width:560px;margin:0 auto;padding:0 0 24px}
|
||
|
||
/* ── SCAN ANIMATION ── */
|
||
.scan-wrap{display:flex;flex-direction:column;align-items:center;padding:48px 24px 56px;text-align:center}
|
||
.scan-doc-outer{position:relative;width:170px;height:220px;margin:0 auto 32px}
|
||
.scan-doc-card{width:170px;height:220px;background:var(--card);border:1.5px solid var(--line);border-radius:14px;overflow:hidden;position:relative;box-shadow:0 12px 40px rgba(0,0,0,.12)}
|
||
.scan-doc-card::before{content:'';position:absolute;left:22px;right:22px;top:22px;height:7px;background:var(--line);border-radius:4px;
|
||
box-shadow:0 16px 0 var(--line),0 29px 0 var(--line),0 42px 0 var(--line),0 55px 0 rgba(159,18,57,.15),0 68px 0 var(--line),0 81px 0 var(--line),0 94px 0 var(--line),0 107px 0 rgba(159,18,57,.1),0 120px 0 var(--line),0 133px 0 rgba(159,18,57,.08)}
|
||
.scan-beam{position:absolute;left:0;right:0;height:3px;background:linear-gradient(90deg,transparent 0%,rgba(159,18,57,.2) 10%,var(--bg) 50%,rgba(159,18,57,.2) 90%,transparent 100%);box-shadow:0 0 14px 5px rgba(159,18,57,.28);animation:beamDown 2s ease-in-out infinite;z-index:2}
|
||
@keyframes beamDown{0%{top:-3px;opacity:0}6%{opacity:1}94%{opacity:1}100%{top:223px;opacity:0}}
|
||
.scan-av{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:68px;height:68px;border-radius:50%;border:4px solid #fff;object-fit:cover;object-position:center 12%;box-shadow:0 4px 16px rgba(0,0,0,.18);z-index:3;animation:avPulse 2.2s ease-in-out infinite}
|
||
@keyframes avPulse{0%,100%{box-shadow:0 4px 16px rgba(0,0,0,.18),0 0 0 0 rgba(159,18,57,.4)}60%{box-shadow:0 4px 16px rgba(0,0,0,.18),0 0 0 10px rgba(159,18,57,0)}}
|
||
.scan-label{font-size:18px;font-weight:700;color:var(--dark);min-height:28px;margin-bottom:7px;transition:opacity .25s}
|
||
.scan-hint{font-size:13px;color:var(--mut);margin-bottom:20px}
|
||
.scan-dots{display:flex;gap:8px;justify-content:center}
|
||
.scan-dot{width:7px;height:7px;border-radius:50%;background:var(--bg);opacity:.3;animation:dotB 1.4s ease-in-out infinite}
|
||
.scan-dot:nth-child(2){animation-delay:.22s}.scan-dot:nth-child(3){animation-delay:.44s}
|
||
@keyframes dotB{0%,100%{opacity:.25;transform:scale(1)}50%{opacity:1;transform:scale(1.35)}}
|
||
</style></head>
|
||
<body>
|
||
|
||
<!-- ═ 1. СТАРТ / ОФФЕР ═ -->
|
||
<section class="screen on" id="start">
|
||
<div class="hero">
|
||
<div class="hero-logo">
|
||
<img class="hero-logomark" src="logos/logo-wasrusgen1-real.svg" alt="@wasrusgen1">
|
||
<div class="hero-logo-sep"></div>
|
||
<img class="hero-wordmark" src="logos/logo-zashita-word.svg" alt="ЗАЩИТА">
|
||
</div>
|
||
<div class="hero-body">
|
||
<!-- Новый клиент -->
|
||
<div id="hero-new">
|
||
<h1>Договор пишут юристы другой стороны. Кто защищает вас?</h1>
|
||
<p>Елена — ваш персональный юридический ИИ. Ответ готов сразу — без счетов и переговоров.</p>
|
||
<div class="hero-services">
|
||
<span class="hero-svc">📄 Проверить договор</span>
|
||
<span class="hero-svc">✍️ Составить документ</span>
|
||
<span class="hero-svc">📋 Протокол разногласий</span>
|
||
<span class="hero-svc">📑 Доверенность</span>
|
||
<span class="hero-svc">✉️ Претензия</span>
|
||
</div>
|
||
<div class="hero-tw-wrap" id="hw-new"><span class="hero-tw-cur">|</span><span id="hero-tw-new" class="hero-tw-text"></span></div>
|
||
<div class="hero-elena-hint">
|
||
<b>Как это работает:</b> нажмите кнопку → Елена спросит что вам нужно → вы загружаете документ или заполняете форму → результат за несколько секунд
|
||
</div>
|
||
<div class="cta"><button class="btn btn-p" onclick="go('elena')">Проверить договор бесплатно →</button></div>
|
||
<div class="priv">🔒 Без регистрации · данные у вас · первые 3 риска бесплатно</div>
|
||
<div style="margin-top:12px"><button class="btn btn-o" style="font-size:13px;padding:8px 18px" onclick="go('cabinet')">📂 Войти в кабинет</button></div>
|
||
</div>
|
||
<!-- Вернувшийся клиент -->
|
||
<div id="hero-returning" style="display:none">
|
||
<div class="ret-greet">Добро пожаловать обратно —<br>вы в надёжных руках 🤝</div>
|
||
<div class="ret-tw-wrap" id="hw-ret"><span class="hero-tw-cur">|</span><span id="hero-tw-ret" class="hero-tw-text"></span></div>
|
||
<div class="ret-card" id="ret-last-order"></div>
|
||
<div class="cta">
|
||
<button class="btn btn-p" style="min-width:160px" onclick="go('cabinet')">Мои дела →</button>
|
||
<button class="btn btn-o" style="font-size:14px" onclick="go('elena')">+ Новый договор</button>
|
||
</div>
|
||
<div class="priv" style="margin-top:16px">🔒 Данные только у вас</div>
|
||
</div>
|
||
</div>
|
||
<div class="face"><img src="logos/elena-photo.jpg" alt="Елена"><div class="cap">Елена — ваш референт</div></div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ═ 2. ЕЛЕНА / ТИЗЕР ═ -->
|
||
<section class="screen" id="elena">
|
||
<div class="topbar"><img class="topbar-wm" src="logos/logo-zashita-word.svg" alt="ЗАЩИТА"><span class="sep"></span><span class="ttl" id="elena-ttl">Знакомство · Елена</span><span class="back back-link" onclick="go('start')">← в начало</span></div>
|
||
<div id="elena-mode-badge"></div>
|
||
<div class="chatwrap">
|
||
|
||
<!-- ШАГ 1: Диалог Елены — вход v4 -->
|
||
<div id="el-step1">
|
||
<div class="msg elena-anim" style="--d:.08s"><div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div>Здравствуйте 👋 Я Елена — ваш персональный юридический ассистент.</div></div>
|
||
<div class="msg elena-anim" style="--d:.75s"><div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div>Помогаю с договорами, документами и юридическими вопросами — быстро и понятно. Расскажите — чем могу Вам помочь?</div></div>
|
||
<div class="elena-dialog-wrap elena-anim" style="--d:1.3s">
|
||
<div class="elena-dialog-row">
|
||
<input class="elena-main-inp" id="intake-custom" placeholder="Например: хочу проверить договор аренды..." onkeydown="if(event.key==='Enter')elenaIntentFromInput()">
|
||
<button class="voice-btn-sm" id="voice-btn-elena" onclick="toggleVoice('intake-custom')" title="Голосовой ввод">🎙</button>
|
||
<button class="elena-go-btn" onclick="elenaIntentFromInput()">→</button>
|
||
</div>
|
||
</div>
|
||
<div class="elena-quick elena-anim" style="--d:1.95s">
|
||
<div class="elena-q-lbl">или выберите быстро:</div>
|
||
<div class="intent-grid">
|
||
<div class="int-card" onclick="elenaIntent('check')"><div class="int-ico">📄</div><div class="int-body"><div class="int-lbl">Проверить договор</div><div class="int-sub">Найду риски и объясню каждый пункт простым языком</div></div></div>
|
||
<div class="int-card" onclick="elenaIntent('create')"><div class="int-ico">✍️</div><div class="int-body"><div class="int-lbl">Составить документ</div><div class="int-sub">Договор, доверенность, претензию — под ваши параметры</div></div></div>
|
||
<div class="int-card" onclick="elenaIntent('dispute')"><div class="int-ico">📋</div><div class="int-body"><div class="int-lbl">Убрать невыгодные пункты</div><div class="int-sub">Подготовлю протокол разногласий — загрузите договор</div></div></div>
|
||
<div class="int-card" onclick="elenaIntent('question')"><div class="int-ico">💬</div><div class="int-body"><div class="int-lbl">Есть вопрос</div><div class="int-sub">Отвечу без загрузки документа — спросите текстом или голосом</div></div></div>
|
||
<div class="int-card" onclick="elenaIntent('power')"><div class="int-ico">📑</div><div class="int-body"><div class="int-lbl">Нужна доверенность</div><div class="int-sub">Скажите кому и какие полномочия — составлю за несколько секунд</div></div></div>
|
||
<div class="int-card" onclick="elenaIntent('cabinet')"><div class="int-ico">🗂️</div><div class="int-body"><div class="int-lbl">Я уже клиент</div><div class="int-sub">Войти в кабинет и посмотреть мои дела</div></div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ШАГ 1б: загрузка договора -->
|
||
<div id="el-step-upload" style="display:none">
|
||
<div class="msg"><div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div><span id="el-ack"></span></div></div>
|
||
<div class="msg"><div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div>
|
||
Отлично. Загрузите договор или вставьте текст — посмотрю и сразу скажу с чем имеем дело 📄
|
||
</div></div>
|
||
<div class="upload-box">
|
||
<div class="upload-zone" onclick="document.getElementById('el-paste').focus()">
|
||
<div class="uz-icon">📂</div>
|
||
<div class="uz-title">Перетащите файл сюда</div>
|
||
<div class="uz-sub">PDF · DOCX · TXT · данные остаются на вашем устройстве 🔒</div>
|
||
</div>
|
||
<div class="upload-or">или вставьте текст</div>
|
||
<textarea class="upload-paste" id="el-paste" placeholder="Вставьте текст договора..."></textarea>
|
||
<button class="btn btn-p" style="width:100%;margin-top:4px" onclick="startScan()">Проанализировать →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ШАГ 1в: анимация сканирования -->
|
||
<div id="el-step-scan" style="display:none">
|
||
<div class="scan-wrap">
|
||
<div class="scan-doc-outer">
|
||
<div class="scan-doc-card"><div class="scan-beam"></div></div>
|
||
<img class="scan-av" src="logos/elena-photo.jpg" alt="Елена">
|
||
</div>
|
||
<div class="scan-label" id="scan-label">Читаю договор...</div>
|
||
<div class="scan-hint">Ищу риски и спорные условия</div>
|
||
<div class="scan-dots">
|
||
<div class="scan-dot"></div><div class="scan-dot"></div><div class="scan-dot"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ШАГ 2: результаты анализа (скрыт до сканирования) -->
|
||
<div id="el-step2" style="display:none">
|
||
<div class="msg"><div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div>
|
||
Прочитала ваш договор 📄 Это <b id="el-scan-type">агентский договор</b>.<br>
|
||
<span id="el-ctype-note" class="ctype-note"></span>
|
||
Нашла <b>12 моментов</b>, из них <b>5 критичных</b>. <span id="el-intro-tail"></span> Показываю 3:
|
||
<div class="risk-mini">
|
||
<div class="rn">п.1.1 · ст. 4–29 ЗоЗПП</div>
|
||
<div id="r1-quote" class="risk-quote"></div>
|
||
<span id="r1-text"></span>
|
||
</div>
|
||
<div class="risk-mini">
|
||
<div class="rn">п.4.6 · ст. 330 ГК</div>
|
||
<div id="r2-quote" class="risk-quote"></div>
|
||
<span id="r2-text"></span>
|
||
</div>
|
||
<div class="risk-mini">
|
||
<div class="rn">ст. 19.1 ТК</div>
|
||
<div id="r3-quote" class="risk-quote"></div>
|
||
<span id="r3-text"></span>
|
||
</div>
|
||
<div class="lock" id="el-lock"></div>
|
||
</div></div>
|
||
<div id="el-pitch-msg" class="msg" style="display:none"><div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div><span id="el-ctype-pitch"></span></div></div>
|
||
<span id="el-fork-q" style="display:none"></span>
|
||
<div class="deliverables">
|
||
<div id="deliv-protocol" class="deliv" onclick="selectDeliv('protocol')">
|
||
<span class="di">📋</span>
|
||
<div><div class="dn">Протокол разногласий</div><div class="dd2" id="dd2-protocol">Список спорных пунктов + зачем менять каждый</div><a class="sample-link" href="sample-protocol.html" target="_blank" onclick="event.stopPropagation()">📄 Образец →</a></div>
|
||
</div>
|
||
<div id="deliv-redact" class="deliv" onclick="selectDeliv('redact')">
|
||
<span class="di">✏️</span>
|
||
<div><div class="dn">Переработка с комментариями</div><div class="dd2" id="dd2-redact">Новая редакция каждого пункта + пояснение изменений</div><a class="sample-link" href="sample-redact.html" target="_blank" onclick="event.stopPropagation()">📄 Образец →</a></div>
|
||
</div>
|
||
<div id="deliv-clean" class="deliv" onclick="selectDeliv('clean')">
|
||
<span class="di">✅</span>
|
||
<div><div class="dn">Чистая редакция</div><div class="dd2" id="dd2-clean">Договор готов к подписанию — без лишних пояснений</div><a class="sample-link" href="sample-clean.html" target="_blank" onclick="event.stopPropagation()">📄 Образец →</a></div>
|
||
</div>
|
||
<div id="deliv-partner" class="deliv deliv-top" onclick="selectDeliv('partner')">
|
||
<span class="di">🤝</span>
|
||
<div><div class="dn">Партнёрская редакция</div><div class="dd2" id="dd2-partner">Вариант, который устроит обе стороны — без конфликта</div><a class="sample-link" href="sample-partner.html" target="_blank" onclick="event.stopPropagation()">📄 Образец →</a></div>
|
||
<span class="deliv-badge" id="deliv-rec-badge">Рекомендуем</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="deliv-sep">или другой формат</div>
|
||
<div id="deliv-consult" class="deliv" onclick="selectDeliv('consult')">
|
||
<span class="di">💬</span>
|
||
<div><div class="dn">Консультация по договору</div><div class="dd2" id="dd2-consult">Задаёте вопросы — AI разбирает ваш договор и отвечает по вашей ситуации. Быстро, конкретно, без лишнего</div><span class="sample-link" style="cursor:default;border-color:transparent;color:var(--mut)">💬 чат · ответ за 2 часа</span></div>
|
||
</div>
|
||
<div id="deliv-reply" class="deliv" onclick="selectDeliv('reply')">
|
||
<span class="di">📨</span>
|
||
<div><div class="dn">Ответ контрагенту</div><div class="dd2" id="dd2-reply">Готовый текст ответа на отказ или встречные возражения — с аргументами и правовой позицией</div></div>
|
||
</div>
|
||
|
||
<!-- ── СВОЙ ЗАПРОС ── -->
|
||
<div class="custom-req-row">
|
||
<button class="custom-req-toggle" id="custom-req-btn" onclick="toggleCustomReq()">✏️ Нужен другой формат? Опишите задачу →</button>
|
||
</div>
|
||
<div id="custom-req-area" class="custom-req-area" style="display:none">
|
||
<div class="msg" style="margin-top:10px">
|
||
<div class="av"><img src="logos/elena-photo.jpg"></div>
|
||
<div class="bubble"><div class="nm">Елена</div>Опишите что нужно — голосом или текстом. Я передам юристу и мы свяжемся с вами в течение 24 часов.</div>
|
||
</div>
|
||
<div class="custom-input-block">
|
||
<textarea id="custom-text" placeholder="Например: мне нужна только таблица рисков без переработки текста, или нужен разбор одного конкретного пункта…" rows="3"></textarea>
|
||
<div class="custom-input-btns">
|
||
<button class="custom-voice-btn" id="custom-voice-btn" onclick="toggleVoice()" title="Диктовать голосом">🎤</button>
|
||
<button class="btn btn-p" onclick="submitCustomReq()" style="flex:1;font-size:14px">Отправить запрос</button>
|
||
</div>
|
||
</div>
|
||
<div id="custom-confirm" class="msg" style="display:none">
|
||
<div class="av"><img src="logos/elena-photo.jpg"></div>
|
||
<div class="bubble"><div class="nm">Елена</div><span id="custom-confirm-text"></span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
<div class="actbar" id="el-actbar" style="display:none"><div class="inner"><button class="btn btn-p" style="flex:1" onclick="go('pay')">Получить полный разбор</button></div></div>
|
||
</section>
|
||
|
||
<!-- ═ 3. ОПЛАТА ═ -->
|
||
<section class="screen" id="pay">
|
||
<div class="topbar"><img class="topbar-wm" src="logos/logo-zashita-word.svg" alt="ЗАЩИТА"><span class="ttl" id="pay-ttl">Выбор варианта</span><span class="back back-link" onclick="go('elena')">← назад</span></div>
|
||
<div class="pay">
|
||
<h2 id="pay-h2">Что сделаем по вашему договору</h2>
|
||
<div class="s" id="pay-sub">Агентский договор · риск 4/5 · 12 пунктов · цена под ваш случай</div>
|
||
|
||
<!-- Что конкретно делаем -->
|
||
<div class="plan-what">
|
||
<div class="plan-what-title">Что войдёт в работу по вашему договору</div>
|
||
<ul id="pay-what-list">
|
||
<li>п.1.1 — снять личную ответственность перед потребителем (ст. 4–29 ЗоЗПП)</li>
|
||
<li>п.4.6 — установить потолок ответственности = сумма вознаграждения</li>
|
||
<li>п.п. о режиме работы — переформулировать признаки самостоятельности (ст. 19.1 ТК)</li>
|
||
<li>+ ещё 9 пунктов из полного заключения</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<!-- Баланс -->
|
||
<div class="pay-bal" id="pay-bal-block">
|
||
<div class="pay-bal-ico">💳</div>
|
||
<div class="pay-bal-body">
|
||
<div class="pay-bal-lbl">Ваш баланс</div>
|
||
<div class="pay-bal-val"><span id="pay-bal-credits">0</span> кредитов</div>
|
||
<div class="pay-bal-sub" id="pay-bal-sub">Пополните баланс ниже или оплатите разово</div>
|
||
</div>
|
||
<button class="pay-bal-use" id="pay-bal-use-btn" onclick="useBalance()" style="display:none">Списать 1 кредит</button>
|
||
</div>
|
||
|
||
<!-- Переключатель: разовая / подписка -->
|
||
<div class="pay-tabs">
|
||
<div class="pay-tab on" id="ptab-once" onclick="payTab('once')">Разовая покупка</div>
|
||
<div class="pay-tab" id="ptab-sub" onclick="payTab('sub')">Подписка 💛</div>
|
||
</div>
|
||
|
||
<!-- Разовая -->
|
||
<div class="pay-pane on" id="ppane-once">
|
||
<div class="pkg-grid">
|
||
<div class="pkg-card" id="pkg-1" onclick="selectPkg(1,249)">
|
||
<div class="pkg-top"><span class="pkg-name">Одна проверка</span><span class="pkg-price">249 ₽</span></div>
|
||
<div class="pkg-desc">1 кредит — только для этого договора</div>
|
||
<div class="pkg-per">249 ₽ за кредит</div>
|
||
</div>
|
||
<div class="pkg-card rec" id="pkg-2" onclick="selectPkg(2,490)">
|
||
<div class="pkg-top"><span class="pkg-name">Пакет Старт · 3 проверки</span><span class="pkg-price">490 ₽</span></div>
|
||
<div class="pkg-desc">3 кредита — первый сразу на этот договор</div>
|
||
<div class="pkg-per">163 ₽ за кредит · экономия 34%</div>
|
||
</div>
|
||
<div class="pkg-card" id="pkg-3" onclick="selectPkg(3,1290)">
|
||
<div class="pkg-top"><span class="pkg-name">Пакет Бизнес · 10 проверок</span><span class="pkg-price">1 290 ₽</span></div>
|
||
<div class="pkg-desc">10 кредитов — хватит на несколько месяцев</div>
|
||
<div class="pkg-per">129 ₽ за кредит · экономия 48%</div>
|
||
</div>
|
||
<div class="pkg-card" id="pkg-4" onclick="selectPkg(4,2990)">
|
||
<div class="pkg-top"><span class="pkg-name">Пакет Корпоратив · 30 проверок</span><span class="pkg-price">2 990 ₽</span></div>
|
||
<div class="pkg-desc">30 кредитов — для команды или активных сделок</div>
|
||
<div class="pkg-per">100 ₽ за кредит · экономия 60%</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Подписка -->
|
||
<div class="pay-pane" id="ppane-sub">
|
||
<div class="sub-grid">
|
||
<div class="sub-card" id="sub-1" onclick="selectSub(1,990)">
|
||
<div class="sub-top"><span class="sub-name">Старт</span><span class="sub-price">990 ₽<span class="sub-period">/мес</span></span></div>
|
||
<div class="sub-desc">До 10 проверок в месяц</div>
|
||
<div class="sub-feat"><span>Проверка рисков</span><span>Список изменений</span></div>
|
||
</div>
|
||
<div class="sub-card rec" id="sub-2" onclick="selectSub(2,1990)">
|
||
<div class="sub-top"><span class="sub-name">Бизнес</span><span class="sub-price">1 990 ₽<span class="sub-period">/мес</span></span></div>
|
||
<div class="sub-desc">До 30 проверок + комментарии Елены</div>
|
||
<div class="sub-feat"><span>Всё из Старта</span><span>Обоснование изменений</span><span>Сроки из договоров</span></div>
|
||
</div>
|
||
<div class="sub-card" id="sub-3" onclick="selectSub(3,4900)">
|
||
<div class="sub-top"><span class="sub-name">Безлимит</span><span class="sub-price">4 900 ₽<span class="sub-period">/мес</span></span></div>
|
||
<div class="sub-desc">Без ограничений · партнёрские редакции</div>
|
||
<div class="sub-feat"><span>Всё из Бизнес</span><span>Партнёрская редакция</span><span>Приоритетная поддержка</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="pay-refund-note">Отмена подписки — в любой момент. Неиспользованный остаток возвращается пропорционально. <a href="#">Условия возврата →</a></div>
|
||
</div>
|
||
|
||
<!-- Аргументация Елены за 2 дорогих -->
|
||
<div class="plan-pitch">
|
||
<img src="logos/elena-photo.jpg">
|
||
<div class="plan-pitch-body" id="pay-pitch">
|
||
Протокол без обоснования — это список требований. Контрагент вправе просто отказать: ему не нужно объяснять почему.<br><br>
|
||
<b>С обоснованием</b> каждое требование опирается на закон или стандарт отрасли. Это не ваш каприз — это норма. По опыту, такие протоколы принимают в первом же раунде.<br><br>
|
||
<b>Партнёрская версия</b> идёт дальше: мы формулируем так, чтобы контрагенту тоже было выгодно согласиться. Договор, который хочется выполнять 💛
|
||
</div>
|
||
</div>
|
||
|
||
<div class="field"><label>Куда прислать результат</label><input id="pay-contact" placeholder="Telegram или email для чека"></div>
|
||
<div class="pdn">Нажимая «Оплатить», вы соглашаетесь с <a href="oferta.html" target="_blank">офертой</a> и <a href="privacy.html" target="_blank">обработкой ПДн</a>. Данные договора остаются на вашем устройстве.</div>
|
||
<button class="btn btn-p" id="pay-price-btn" style="width:100%" onclick="ykOpen()">Оплатить 490 ₽</button>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
|
||
<!-- ═ СТАТУС ЗАКАЗА ═ -->
|
||
<section class="screen" id="order-status">
|
||
<div class="topbar">
|
||
<img class="topbar-wm" src="logos/logo-zashita-word.svg" alt="ЗАЩИТА">
|
||
<span class="ttl">Заказ принят</span>
|
||
<span class="back-link" onclick="go('cabinet')" style="font-size:13px;color:var(--bg);font-weight:600;cursor:pointer">Мои дела →</span>
|
||
</div>
|
||
<div class="os-wrap">
|
||
|
||
<div class="os-ok">
|
||
<div class="os-ok-icon">✅</div>
|
||
<div class="os-ok-ttl">Оплата подтверждена</div>
|
||
<div class="os-ok-sub" id="os-ok-sub">Заказ передан в работу</div>
|
||
</div>
|
||
|
||
<div class="os-card">
|
||
<div class="oc-ttl" id="os-svc">Экспертиза договора</div>
|
||
<div class="oc-plan" id="os-plan-name">Стандарт</div>
|
||
<div class="oc-price" id="os-price">2 480 ₽</div>
|
||
<div class="oc-id" id="os-orderid">Заказ #—</div>
|
||
</div>
|
||
|
||
<div class="os-steps">
|
||
<div class="os-step done">
|
||
<div class="os-dot">✓</div>
|
||
<div class="os-step-lbl">Оплата<br>получена</div>
|
||
</div>
|
||
<div class="os-step active" id="os-step2">
|
||
<div class="os-dot">▶</div>
|
||
<div class="os-step-lbl" id="os-step2-lbl">Юрист<br>работает</div>
|
||
</div>
|
||
<div class="os-step pending">
|
||
<div class="os-dot">3</div>
|
||
<div class="os-step-lbl" id="os-step3-lbl">Готово</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="os-deadline">
|
||
<div class="od-icon">⏱</div>
|
||
<div class="od-text">
|
||
<strong id="os-deadline-ttl">Срок: до 24 часов</strong>
|
||
<span id="os-deadline-sub">после получения файла договора</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="enote" style="margin-bottom:20px">
|
||
<img src="logos/elena-photo.jpg">
|
||
<div class="et" id="os-elena-msg">
|
||
Заказ получен — уже передала юристу. <b>Пришлите договор</b> в Telegram
|
||
<a href="https://t.me/wasrusgen1" target="_blank">@wasrusgen1</a> —
|
||
без него начать не получится. Как только файл придёт — сразу приступаем 💛
|
||
</div>
|
||
</div>
|
||
|
||
<div class="os-actions">
|
||
<a class="os-tg" href="https://t.me/wasrusgen1" target="_blank">💬 Написать в Telegram</a>
|
||
<button class="btn btn-o" onclick="go('cabinet')">📂 Мои дела</button>
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ═ АНАЛИТИКА CUSTOM-ЗАПРОСОВ ═ -->
|
||
<section class="screen" id="custom-admin">
|
||
<div class="topbar">
|
||
<img class="topbar-wm" src="logos/logo-zashita-word.svg" alt="ЗАЩИТА">
|
||
<span class="ttl">Аналитика: свои запросы</span>
|
||
<span class="back back-link" onclick="history.back();go('start')">← назад</span>
|
||
</div>
|
||
<div class="ca-wrap">
|
||
<div class="ca-title">Нестандартные запросы</div>
|
||
<div class="ca-sub">Что клиенты просят, чего нет в системе — основа для расширения CTYPES и deliverables</div>
|
||
<div id="ca-body"></div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ═ 4–7. КАБИНЕТ (вкладки) ═ -->
|
||
<section class="screen" id="cabinet">
|
||
<div class="app">
|
||
<aside class="side">
|
||
<div class="lg"><img class="topbar-wm" src="logos/logo-zashita-word.svg" alt="ЗАЩИТА"></div>
|
||
<a id="t-cases" class="on" onclick="tab('cases')">🗂️ Мои дела</a>
|
||
<a id="t-case" onclick="tab('case')">📄 Дело: Кухня</a>
|
||
<a id="t-sroki" onclick="tab('sroki')">⏱️ Сроки</a>
|
||
<a id="t-shab" onclick="tab('shab')">📋 Шаблоны</a>
|
||
<a id="t-create" onclick="tab('create')">✍️ Составить документ</a>
|
||
<a id="t-balance" onclick="tab('balance')">💳 Баланс и оплата</a>
|
||
<a onclick="go('start')">↩ Выйти (в начало)</a>
|
||
<a onclick="go('admin')" style="color:#ef4444;font-weight:700">⚙️ Администратор</a>
|
||
<div class="side-clock">
|
||
<div class="side-clock-day" id="sc-day">Среда</div>
|
||
<div class="side-clock-date" id="sc-date">28 мая 2025</div>
|
||
<div class="side-clock-time" id="sc-time">10:52:00</div>
|
||
</div>
|
||
<div class="prof"><div class="pa">РВ</div><div><div class="pn">Руслан Васильев</div><div class="pt">Тариф: Старт</div></div></div>
|
||
</aside>
|
||
<main class="main">
|
||
<!-- Мои дела -->
|
||
<div class="tabpane on" id="p-cases">
|
||
<div class="main-body">
|
||
<div class="crumb">Кабинет</div><h1>Мои дела</h1>
|
||
<!-- KPI -->
|
||
<div class="kpi-row">
|
||
<div class="kpi-card kpi-total"><div class="kc-ico">📁</div><div><div class="kc-num" id="kpi-total">5</div><div class="kc-lbl">Всего дел</div></div></div>
|
||
<div class="kpi-card kpi-work"><div class="kc-ico">🔵</div><div><div class="kc-num" id="kpi-work">3</div><div class="kc-lbl">В работе</div></div></div>
|
||
<div class="kpi-card kpi-urg"><div class="kc-ico">⚠️</div><div><div class="kc-num" id="kpi-urg">1</div><div class="kc-lbl">Срочных</div></div></div>
|
||
<div class="kpi-card kpi-done"><div class="kc-ico">✅</div><div><div class="kc-num" id="kpi-done">2</div><div class="kc-lbl">Завершено</div></div></div>
|
||
</div>
|
||
<!-- Фильтры -->
|
||
<div class="ct-filters">
|
||
<button class="ct-fbtn act" onclick="ctFilter('all',this)">Все</button>
|
||
<button class="ct-fbtn" onclick="ctFilter('open',this)">Открытые</button>
|
||
<button class="ct-fbtn" onclick="ctFilter('closed',this)">Закрытые</button>
|
||
<div class="ct-filter-sep"></div>
|
||
<button class="ct-fbtn" onclick="ctFilter('risk',this)">⚠ Срочные</button>
|
||
</div>
|
||
<!-- Таблица -->
|
||
<table class="ct-table" id="ct-table">
|
||
<thead>
|
||
<tr>
|
||
<th onclick="ctSort('name',this)">Договор</th>
|
||
<th onclick="ctSort('type',this)">Тип</th>
|
||
<th onclick="ctSort('date',this)">Дата</th>
|
||
<th onclick="ctSort('risk',this)">Риск</th>
|
||
<th onclick="ctSort('status',this)">Статус</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="ct-tbody"></tbody>
|
||
</table>
|
||
</div><!-- /main-body -->
|
||
</div>
|
||
<!-- Внутри дела — CRM -->
|
||
<div class="tabpane" id="p-case"><div class="main-body">
|
||
<div class="crumb" style="margin-bottom:14px">Кабинет / <span style="cursor:pointer;color:var(--bg)" onclick="tab('cases')">Мои дела</span> / Кухня — агентский</div>
|
||
|
||
<!-- Шапка дела -->
|
||
<div class="case-hdr">
|
||
<div class="case-hdr-ico">🍽️</div>
|
||
<div class="case-hdr-info">
|
||
<div class="case-hdr-name">Кухня — агентский договор (ЗОВ)</div>
|
||
<div class="case-hdr-meta">
|
||
<span class="chip d">⚠ Высокий риск</span>
|
||
<span class="chip w">🔵 В работе</span>
|
||
<span class="chip n">12 рисков</span>
|
||
<span class="chip n">Агентский · 23.05.2025</span>
|
||
</div>
|
||
</div>
|
||
<div class="case-hdr-actions">
|
||
<button class="btn btn-o" style="font-size:12px;padding:7px 14px" onclick="toast('⬇️ PDF экспортируется')">⬇ PDF</button>
|
||
<button class="btn btn-p" style="font-size:12px;padding:7px 14px" onclick="toast('💬 Открываю чат с Еленой')">💬 Елена</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ⚡ Следующий шаг — ГЛАВНЫЙ БЛОК -->
|
||
<div class="next-step-v2" onclick="toast('📋 Открываю протокол разногласий для согласования')">
|
||
<div class="ns2-pulse">⚡</div>
|
||
<div class="ns2-body">
|
||
<div class="ns2-label">Следующий шаг</div>
|
||
<div class="ns2-action">Отправить протокол разногласий контрагенту<span class="ns2-deadline">до 29.05</span></div>
|
||
<div class="ns2-meta">Протокол готов · 5 пунктов · ст. 22 ЗоЗПП · осталось 1 день</div>
|
||
</div>
|
||
<button class="ns2-btn" onclick="event.stopPropagation();toast('✅ Протокол согласован и готов к отправке')">Согласовать →</button>
|
||
</div>
|
||
|
||
<!-- Панель протокола (появляется когда выбраны пункты) -->
|
||
<div class="protocol-bar" id="protocol-bar">
|
||
<div class="pb-ico">📋</div>
|
||
<div class="pb-body">
|
||
<div class="pb-title">Протокол разногласий</div>
|
||
<div class="pb-sub" id="pb-sub">Выберите пункты во вкладке Риски</div>
|
||
</div>
|
||
<button class="pb-btn" id="pb-generate" onclick="toast('📋 Протокол разногласий формируется — Елена подготовит документ в течение 2 минут')">Сформировать протокол →</button>
|
||
</div>
|
||
|
||
<!-- Вкладки -->
|
||
<div class="case-tabs">
|
||
<div class="case-tab on" onclick="caseTab('overview',this)">Обзор</div>
|
||
<div class="case-tab" onclick="caseTab('risks',this)">Риски <span style="background:#fee2e2;color:#991b1b;border-radius:8px;padding:1px 6px;font-size:10px;font-weight:700">12</span></div>
|
||
<div class="case-tab" onclick="caseTab('docs',this)">Документы <span style="background:#e5e7eb;border-radius:8px;padding:1px 6px;font-size:10px">5</span></div>
|
||
<div class="case-tab" onclick="caseTab('timeline',this)">История</div>
|
||
<div class="case-tab" onclick="caseTab('chat',this)">Переписка <span style="background:#dbeafe;color:#1d4ed8;border-radius:8px;padding:1px 6px;font-size:10px;font-weight:700">1</span></div>
|
||
</div>
|
||
|
||
<!-- Обзор -->
|
||
<div class="case-pane on" id="cp-overview">
|
||
|
||
<!-- Прогресс дела -->
|
||
<div class="case-progress">
|
||
<div class="cp-step done">
|
||
<div class="cps-dot">✓</div>
|
||
<div class="cps-lbl">Загружен</div>
|
||
<div class="cps-date">23.05</div>
|
||
</div>
|
||
<div class="cp-step done">
|
||
<div class="cps-dot">✓</div>
|
||
<div class="cps-lbl">Экспертиза</div>
|
||
<div class="cps-date">23.05</div>
|
||
</div>
|
||
<div class="cp-step done">
|
||
<div class="cps-dot">✓</div>
|
||
<div class="cps-lbl">Новая редакция</div>
|
||
<div class="cps-date">24.05</div>
|
||
</div>
|
||
<div class="cp-step act">
|
||
<div class="cps-dot">⏳</div>
|
||
<div class="cps-lbl">Протокол</div>
|
||
<div class="cps-date">сейчас</div>
|
||
</div>
|
||
<div class="cp-step pend">
|
||
<div class="cps-dot">→</div>
|
||
<div class="cps-lbl">Ответ контрагенту</div>
|
||
<div class="cps-date">до 29.05</div>
|
||
</div>
|
||
<div class="cp-step pend">
|
||
<div class="cps-dot">✍</div>
|
||
<div class="cps-lbl">Подписание</div>
|
||
<div class="cps-date">—</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="overview-grid">
|
||
<div class="ov-card">
|
||
<div class="ov-card-ttl">Параметры дела</div>
|
||
<div class="ov-row"><span class="ov-k">Тип договора</span><span class="ov-v">Агентский</span></div>
|
||
<div class="ov-row"><span class="ov-k">Дата загрузки</span><span class="ov-v">23.05.2025</span></div>
|
||
<div class="ov-row"><span class="ov-k">Риск</span><span class="ov-v"><span class="chip d" style="font-size:11px">⚠ Высокий · 3/5</span></span></div>
|
||
<div class="ov-row"><span class="ov-k">Рисков найдено</span><span class="ov-v">12 (5 критичных)</span></div>
|
||
<div class="ov-row"><span class="ov-k">Статус</span><span class="ov-v">🔵 В работе</span></div>
|
||
</div>
|
||
<div class="ov-card">
|
||
<div class="ov-card-ttl">Текущий этап</div>
|
||
<div class="ov-row"><span class="ov-k">✅ Экспертиза</span><span class="ov-v" style="color:#16a34a">Готово</span></div>
|
||
<div class="ov-row"><span class="ov-k">✅ Новая редакция</span><span class="ov-v" style="color:#16a34a">Получена</span></div>
|
||
<div class="ov-row"><span class="ov-k">⏳ Протокол</span><span class="ov-v" style="color:#d97706">На согласовании</span></div>
|
||
<div class="ov-row"><span class="ov-k">⬜ Ответ контрагенту</span><span class="ov-v" style="color:#9ca3af">Ожидает</span></div>
|
||
<div class="ov-row"><span class="ov-k">⬜ Подписание</span><span class="ov-v" style="color:#9ca3af">Ожидает</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="enote" style="margin-top:4px"><img src="logos/elena-photo.jpg"><div class="et">Протокол разногласий готов — осталось согласовать и отправить контрагенту до 29.05. Я напомню накануне 💛</div></div>
|
||
</div>
|
||
|
||
<!-- Риски -->
|
||
<div class="case-pane" id="cp-risks">
|
||
<div class="risk-summary">
|
||
<div class="risk-sum-item crit">🔴 5 критических</div>
|
||
<div class="risk-sum-item mid">🟡 4 средних</div>
|
||
<div class="risk-sum-item low">🟢 3 низких</div>
|
||
</div>
|
||
<div class="risk-list">
|
||
|
||
<div class="risk-item crit" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge crit">🔴 Критический</span>
|
||
<span class="risk-num">#1</span>
|
||
<span class="risk-title">Одностороннее изменение условий</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 4.2 договора · ст. 450 ГК РФ</div>
|
||
<div class="risk-rec">Агент вправе менять вознаграждение без вашего согласования.</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Агент вправе в одностороннем порядке изменять размер агентского вознаграждения, уведомив Принципала не менее чем за 3 (три) календарных дня»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«Изменение размера агентского вознаграждения допускается исключительно по письменному соглашению сторон, подписанному обеими сторонами»</div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(1,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="risk-item crit" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge crit">🔴 Критический</span>
|
||
<span class="risk-num">#2</span>
|
||
<span class="risk-title">Неограниченная ответственность принципала</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 8.1 договора · ст. 393 ГК РФ</div>
|
||
<div class="risk-rec">Размер убытков, которые агент может взыскать с вас, не ограничен.</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Принципал возмещает Агенту убытки в полном объёме, включая упущенную выгоду, понесённые вследствие ненадлежащего исполнения обязательств»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«Ответственность Принципала ограничена суммой агентского вознаграждения за 3 (три) последних месяца. Упущенная выгода возмещению не подлежит»</div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(2,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="risk-item crit" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge crit">🔴 Критический</span>
|
||
<span class="risk-num">#3</span>
|
||
<span class="risk-title">Автопролонгация без уведомления</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 9.3 договора · ст. 621 ГК РФ</div>
|
||
<div class="risk-rec">Договор продлевается на год автоматически — без явного согласия.</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Договор считается пролонгированным на аналогичный срок, если ни одна из сторон не заявила письменного отказа»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«Пролонгация допускается только при наличии письменного согласия обеих сторон, подписанного не позднее чем за 30 дней до окончания срока договора»</div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(3,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="risk-item crit" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge crit">🔴 Критический</span>
|
||
<span class="risk-num">#4</span>
|
||
<span class="risk-title">Отсутствие порядка сдачи-приёмки</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 5 договора · ст. 720 ГК РФ</div>
|
||
<div class="risk-rec">Нет формы акта и сроков — суд может признать услугу принятой по умолчанию.</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Результат исполнения агентского поручения считается принятым по истечении 5 рабочих дней с момента получения отчёта при отсутствии замечаний»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«Приёмка исполнения оформляется актом по форме Приложения №2. Акт подписывается в течение 3 рабочих дней. При наличии замечаний составляется мотивированный отказ в той же форме»</div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(4,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="risk-item crit" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge crit">🔴 Критический</span>
|
||
<span class="risk-num">#5</span>
|
||
<span class="risk-title">Невыгодная подсудность</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 11.2 договора · ст. 37 АПК РФ</div>
|
||
<div class="risk-rec">Споры рассматриваются по месту агента — вам придётся судиться в другом городе.</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Все споры, вытекающие из настоящего договора, рассматриваются в Арбитражном суде города Москвы»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«Все споры, вытекающие из настоящего договора, рассматриваются в арбитражном суде по месту нахождения Принципала»</div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(5,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="risk-item mid" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge mid">🟡 Средний</span>
|
||
<span class="risk-num">#6</span>
|
||
<span class="risk-title">Размытые сроки отчётности агента</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 6.1 договора · ст. 1008 ГК РФ</div>
|
||
<div class="risk-rec">«В разумный срок» — нет конкретной даты предоставления отчётов.</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Агент представляет отчёт об исполнении поручения в разумный срок после окончания отчётного периода»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«Агент представляет отчёт не позднее 5-го числа месяца, следующего за отчётным, с приложением первичных документов»</div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(6,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="risk-item mid" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge mid">🟡 Средний</span>
|
||
<span class="risk-num">#7</span>
|
||
<span class="risk-title">Нет срока уведомления при расторжении</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 9.2 договора · ст. 1010 ГК РФ</div>
|
||
<div class="risk-rec">Порядок уведомления не прописан — расторжение может прийти в любой момент.</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Каждая из сторон вправе отказаться от договора, уведомив другую сторону о своём намерении»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«Каждая из сторон вправе отказаться от договора, направив письменное уведомление не менее чем за 30 (тридцать) календарных дней до предполагаемой даты расторжения»</div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(7,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="risk-item mid" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge mid">🟡 Средний</span>
|
||
<span class="risk-num">#8</span>
|
||
<span class="risk-title">Вознаграждение без указания НДС</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 3.1 договора · НК РФ ст. 168</div>
|
||
<div class="risk-rec">Риск доначисления НДС и штрафов при налоговой проверке.</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Размер агентского вознаграждения составляет 150 000 (сто пятьдесят тысяч) рублей ежемесячно»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«Размер агентского вознаграждения составляет 150 000 (сто пятьдесят тысяч) рублей ежемесячно, в том числе НДС 20% — 25 000 рублей» <i>(или: «НДС не облагается — основание: применение УСН»)</i></div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(8,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="risk-item mid" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge mid">🟡 Средний</span>
|
||
<span class="risk-num">#9</span>
|
||
<span class="risk-title">Право субагентирования без согласования</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 3.4 договора · ст. 1009 ГК РФ</div>
|
||
<div class="risk-rec">Агент привлекает субагентов без вашего ведома — вы теряете контроль.</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Агент вправе для исполнения поручения привлекать третьих лиц (субагентов) с уведомлением Принципала»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«Привлечение субагентов допускается исключительно с предварительного письменного согласия Принципала в каждом конкретном случае»</div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(9,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="risk-item low" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge low">🟢 Низкий</span>
|
||
<span class="risk-num">#10</span>
|
||
<span class="risk-title">Расплывчатый перечень форс-мажора</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 10 договора · ст. 401 ГК РФ</div>
|
||
<div class="risk-rec">Перечень открытый — контрагент может сослаться на любое «чрезвычайное обстоятельство».</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Стороны освобождаются от ответственности при наступлении обстоятельств непреодолимой силы и иных чрезвычайных обстоятельств»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«Форс-мажорными признаются исключительно: стихийные бедствия, военные действия, режим ЧС, эпидемия по решению ВОЗ, запретительные акты органов государственной власти. Перечень является исчерпывающим»</div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(10,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="risk-item low" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge low">🟢 Низкий</span>
|
||
<span class="risk-num">#11</span>
|
||
<span class="risk-title">Нет упоминания ЭДО и ЭЦП</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 12 договора · 63-ФЗ</div>
|
||
<div class="risk-rec">При дистанционной работе электронные документы могут не иметь юридической силы.</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Уведомления и документы направляются сторонами по почте заказным письмом или курьерской службой»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«Стороны вправе использовать электронный документооборот с применением квалифицированной электронной подписи (КЭП) в соответствии с 63-ФЗ. Документы в ЭДО имеют равную юридическую силу с бумажными оригиналами»</div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(11,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="risk-item low" onclick="toggleRisk(this)">
|
||
<div class="risk-item-hdr">
|
||
<span class="risk-badge low">🟢 Низкий</span>
|
||
<span class="risk-num">#12</span>
|
||
<span class="risk-title">Нет обязанности уведомлять об изменении реквизитов</span>
|
||
<span class="risk-toggle">▼</span>
|
||
</div>
|
||
<div class="risk-norm">п. 12.3 договора</div>
|
||
<div class="risk-rec">Смена реквизитов без предупреждения — оплата уйдёт не туда, но вы останетесь должником.</div>
|
||
<div class="risk-expand">
|
||
<div class="risk-quote"><div class="risk-quote-lbl">📄 Как написано сейчас</div><div class="risk-quote-txt">«Стороны используют реквизиты, указанные в разделе 12 настоящего договора»</div></div>
|
||
<div class="risk-fix"><div class="risk-fix-lbl">✅ Рекомендуемая формулировка</div><div class="risk-fix-txt">«При изменении банковских реквизитов сторона обязана письменно уведомить контрагента не менее чем за 5 (пять) рабочих дней. Платёж по старым реквизитам после получения уведомления не признаётся надлежащим исполнением»</div></div>
|
||
<button class="risk-apply-btn" onclick="event.stopPropagation();applyRisk(12,this)">Применить в протоколе →</button>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Документы -->
|
||
<div class="case-pane" id="cp-docs">
|
||
<div class="doc-upload-btn" onclick="toast('📎 Выберите файл — договор, письмо или любой документ по делу. Данные остаются на вашем устройстве')">
|
||
<div class="doc-upload-ico">📎</div>
|
||
<div class="doc-upload-txt">Загрузить документ в дело
|
||
<span>PDF, DOCX, JPG · до 50 МБ · данные остаются на вашем устройстве</span>
|
||
</div>
|
||
</div>
|
||
<div style="max-width:700px">
|
||
<div class="docrow" onclick="toast('Открываю исходный договор v1')">📄 Исходный договор <span class="ver">v1</span></div>
|
||
<div class="docrow" onclick="toast('Открываю редакцию v2')">📝 Новая редакция <span class="ver">v2</span></div>
|
||
<div class="docrow" onclick="toast('Открываю заключение экспертизы — 12 рисков')">🔍 Заключение экспертизы <span class="ver">готово</span></div>
|
||
<div class="docrow" onclick="toast('Открываю протокол разногласий')">📋 Протокол разногласий <span class="ver">черновик</span></div>
|
||
<div class="docrow" onclick="toast('Открываю ответ контрагента')">⬇️ Ответ контрагента <span class="ver">входящее</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Переписка -->
|
||
<div class="case-pane" id="cp-chat">
|
||
|
||
<!-- Форма составления письма -->
|
||
<div class="chat-compose">
|
||
<div class="chat-compose-ttl">✉️ Составить письмо контрагенту</div>
|
||
<div class="chat-field">
|
||
<label>Кому</label>
|
||
<input type="text" value="ООО «Зов Ресторанс» — info@zov-rest.ru" readonly style="color:var(--mut);background:#f9fafb">
|
||
</div>
|
||
<div class="chat-field">
|
||
<label>Тема</label>
|
||
<input type="text" id="chat-subject" value="Протокол разногласий к агентскому договору от 20.05.2025">
|
||
</div>
|
||
<div class="chat-field">
|
||
<label>Текст письма</label>
|
||
<textarea id="chat-body" rows="6" style="font-size:12px;line-height:1.6">Уважаемые коллеги,
|
||
|
||
Направляем протокол разногласий к агентскому договору от 20.05.2025 г. Просим рассмотреть предложенные изменения и сообщить о Вашем решении в срок до 29.05.2025.
|
||
|
||
Прилагаем: протокол разногласий (1 л.).
|
||
|
||
С уважением,
|
||
Васильев Руслан Геннадьевич
|
||
ИП Васильев Р.Г.</textarea>
|
||
</div>
|
||
<div class="chat-actions">
|
||
<button class="chat-send-btn" onclick="toast('📧 Письмо подготовлено — скопируйте и отправьте из вашей почты. Запись о письме сохранена в истории дела')">Подготовить к отправке</button>
|
||
<button class="chat-copy-btn" onclick="toast('📋 Текст письма скопирован в буфер обмена')">Копировать текст</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- История переписки -->
|
||
<div class="chat-list">
|
||
<div class="chat-list-ttl">История переписки</div>
|
||
|
||
<div class="chat-item inc" onclick="toast('📥 Открываю входящее письмо от контрагента')">
|
||
<div class="chat-arrow">←</div>
|
||
<div class="chat-item-body">
|
||
<div class="chat-item-hdr">
|
||
<span class="chat-item-subj">Ответ на протокол разногласий</span>
|
||
<span class="chat-status new">Новое</span>
|
||
<span class="chat-item-date">24.05</span>
|
||
</div>
|
||
<div class="chat-item-prev">ООО Зов Ресторанс: «Готовы согласовать пп. 1,3,5. По п. 2 просим сохранить текущую редакцию...»</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="chat-item out" onclick="toast('📤 Открываю отправленное письмо')">
|
||
<div class="chat-arrow">→</div>
|
||
<div class="chat-item-body">
|
||
<div class="chat-item-hdr">
|
||
<span class="chat-item-subj">Протокол разногласий (черновик)</span>
|
||
<span class="chat-status sent">Отправлено</span>
|
||
<span class="chat-item-date">23.05</span>
|
||
</div>
|
||
<div class="chat-item-prev">Направляем протокол разногласий к агентскому договору от 20.05.2025...</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="chat-item out" onclick="toast('📤 Открываю запрос реквизитов')">
|
||
<div class="chat-arrow">→</div>
|
||
<div class="chat-item-body">
|
||
<div class="chat-item-hdr">
|
||
<span class="chat-item-subj">Запрос реквизитов и ИНН</span>
|
||
<span class="chat-status read">Прочитано</span>
|
||
<span class="chat-item-date">21.05</span>
|
||
</div>
|
||
<div class="chat-item-prev">В целях проверки контрагента просим предоставить полные реквизиты...</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<!-- История -->
|
||
<div class="case-pane" id="cp-timeline">
|
||
<div class="tl-section" style="margin-top:0">
|
||
<div class="tl">
|
||
<div class="tl-item done"><div class="tl-dot"></div><div class="tl-date">23.05</div><div class="tl-title">Договор загружен</div><div class="tl-ev">Агентский договор ЗОВ — v1</div></div>
|
||
<div class="tl-item done"><div class="tl-dot"></div><div class="tl-date">23.05</div><div class="tl-title">Экспертиза завершена</div><div class="tl-ev">12 рисков, 5 критичных — заключение готово</div></div>
|
||
<div class="tl-item done"><div class="tl-dot"></div><div class="tl-date">24.05</div><div class="tl-title">Получена новая редакция</div><div class="tl-ev">Контрагент прислал v2 — сверка выполнена</div></div>
|
||
<div class="tl-item active"><div class="tl-dot"></div><div class="tl-date">сейчас</div><div class="tl-title">Протокол разногласий</div><div class="tl-ev">Черновик готов · ждёт согласования</div></div>
|
||
<div class="tl-item pending"><div class="tl-dot"></div><div class="tl-date">до 29.05</div><div class="tl-title">Ответ контрагенту</div><div class="tl-ev">Направить протокол разногласий</div></div>
|
||
<div class="tl-item pending"><div class="tl-dot"></div><div class="tl-date">—</div><div class="tl-title">Итоговое подписание</div><div class="tl-ev">После согласования всех пунктов</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Сроки — Gantt -->
|
||
<div class="tabpane" id="p-sroki"><div class="main-body"><div class="crumb">Кабинет</div><h1>Сроки</h1>
|
||
<div class="enote" style="margin-bottom:20px"><img src="logos/elena-photo.jpg"><div class="et"><b>Слежу за сроками из ваших договоров.</b> Если в документе есть даты оплат, уведомлений или расторжения — покажу здесь 💛</div></div>
|
||
<div class="dl-summary" id="dl-summary"></div>
|
||
<div class="dl-filter">
|
||
<div class="dl-ftab on" onclick="dlFilter('all',this)">Все</div>
|
||
<div class="dl-ftab" onclick="dlFilter('urgent',this)">Срочные 🔴🟡</div>
|
||
<div class="dl-ftab" onclick="dlFilter('done',this)">Выполненные</div>
|
||
</div>
|
||
<div class="dl-list" id="dl-list"></div>
|
||
</div></div>
|
||
<!-- Шаблоны -->
|
||
<div class="tabpane" id="p-shab"><div class="main-body"><div class="crumb">Кабинет</div><h1>Шаблоны</h1>
|
||
<div class="enote"><img src="logos/elena-photo.jpg"><div class="et"><b>Готовые документы — заполню под ваш случай.</b> Составлять с нуля не нужно 💛</div></div>
|
||
<div class="tpls">
|
||
<div class="tpl" onclick="toast('✍️ Заполняю «Протокол разногласий» под ваш договор — Елена рядом')"><div class="ti">📝</div><div class="tn">Протокол разногласий</div><div class="td">убрать невыгодные пункты</div></div>
|
||
<div class="tpl" onclick="toast('✍️ Заполняю «Претензию» под ваш случай — оплата / неустойка')"><div class="ti">✉️</div><div class="tn">Претензия</div><div class="td">оплата / неустойка</div></div>
|
||
<div class="tpl" onclick="toast('✍️ Заполняю «Ответ на претензию» — отобьём требование по закону')"><div class="ti">🛡️</div><div class="tn">Ответ на претензию</div><div class="td">отбить требование</div></div>
|
||
<div class="tpl" onclick="toast('✍️ Заполняю «Расторжение» — выйдем без потерь')"><div class="ti">🚪</div><div class="tn">Расторжение</div><div class="td">выйти без потерь</div></div>
|
||
</div>
|
||
</div></div>
|
||
<!-- Составить документ -->
|
||
<div class="tabpane" id="p-create"><div class="main-body">
|
||
<div class="crumb">Кабинет</div><h1>Составить документ</h1>
|
||
<div class="enote" style="margin-bottom:20px"><img src="logos/elena-photo.jpg"><div class="et"><b>Составлю любой документ под ваши параметры.</b> Выберите тип, заполните ключевые данные — черновик будет готов за несколько секунд. 💛</div></div>
|
||
|
||
<!-- Шаги -->
|
||
<div class="create-steps">
|
||
<div class="cstep act" id="cstep-1"><div class="cstep-num">1</div>Тип документа</div>
|
||
<div class="cstep-arrow">›</div>
|
||
<div class="cstep" id="cstep-2"><div class="cstep-num">2</div>Параметры</div>
|
||
<div class="cstep-arrow">›</div>
|
||
<div class="cstep" id="cstep-3"><div class="cstep-num">3</div>Черновик готов</div>
|
||
</div>
|
||
|
||
<!-- Шаг 1: Тип документа -->
|
||
<div class="create-pane on" id="cp-type">
|
||
<div class="doc-type-intro">Выберите тип — Елена подберёт структуру и заполнит шаблон под ваши данные</div>
|
||
<div class="doc-type-grid">
|
||
<div class="doc-type-card sel" onclick="selectDocType('agent',this)">
|
||
<div class="dtc-ico">🤝</div>
|
||
<div class="dtc-name">Агентский договор</div>
|
||
<div class="dtc-desc">поручение + вознаграждение</div>
|
||
</div>
|
||
<div class="doc-type-card" onclick="selectDocType('trust',this)">
|
||
<div class="dtc-ico">📑</div>
|
||
<div class="dtc-name">Доверенность</div>
|
||
<div class="dtc-desc">полномочия представителя</div>
|
||
</div>
|
||
<div class="doc-type-card" onclick="selectDocType('claim',this)">
|
||
<div class="dtc-ico">✉️</div>
|
||
<div class="dtc-name">Претензия</div>
|
||
<div class="dtc-desc">оплата / неустойка</div>
|
||
</div>
|
||
<div class="doc-type-card" onclick="selectDocType('supply',this)">
|
||
<div class="dtc-ico">📦</div>
|
||
<div class="dtc-name">Договор поставки</div>
|
||
<div class="dtc-desc">товар + сроки + ответственность</div>
|
||
</div>
|
||
<div class="doc-type-card" onclick="selectDocType('rent',this)">
|
||
<div class="dtc-ico">🏠</div>
|
||
<div class="dtc-name">Аренда</div>
|
||
<div class="dtc-desc">помещение / оборудование</div>
|
||
</div>
|
||
<div class="doc-type-card" onclick="selectDocType('nda',this)">
|
||
<div class="dtc-ico">🔒</div>
|
||
<div class="dtc-name">NDA / Конфиденциальность</div>
|
||
<div class="dtc-desc">защита данных и ноу-хау</div>
|
||
</div>
|
||
<div class="doc-type-card" onclick="selectDocType('labor',this)">
|
||
<div class="dtc-ico">💼</div>
|
||
<div class="dtc-name">Трудовой договор</div>
|
||
<div class="dtc-desc">оформление сотрудника</div>
|
||
</div>
|
||
<div class="doc-type-card" onclick="selectDocType('dismiss',this)">
|
||
<div class="dtc-ico">🚪</div>
|
||
<div class="dtc-name">Расторжение</div>
|
||
<div class="dtc-desc">выйти без потерь</div>
|
||
</div>
|
||
</div>
|
||
<button class="doc-type-next show" id="doc-type-next" onclick="goCreateStep(2)">Заполнить параметры →</button>
|
||
</div>
|
||
|
||
<!-- Шаг 2: Параметры -->
|
||
<div class="create-pane" id="cp-form">
|
||
<div style="font-size:14px;font-weight:700;color:var(--ink);margin-bottom:16px" id="cf-doc-title">Агентский договор</div>
|
||
<div class="create-form-grid" id="create-form-fields">
|
||
<!-- Поля строятся через JS buildCreateForm() -->
|
||
<div class="cf-group"><label class="cf-label">Принципал (вы)</label><input class="cf-input" placeholder="ИП Васильев Руслан Геннадьевич"><span class="cf-hint">Полное наименование или ФИО</span></div>
|
||
<div class="cf-group"><label class="cf-label">Агент (контрагент)</label><input class="cf-input" placeholder="ООО «Зов Ресторанс»"><span class="cf-hint">Полное наименование</span></div>
|
||
<div class="cf-group wide"><label class="cf-label">Предмет поручения</label><input class="cf-input" placeholder="Поиск и привлечение клиентов для ресторана"><span class="cf-hint">Что именно делает агент</span></div>
|
||
<div class="cf-group"><label class="cf-label">Вознаграждение</label><input class="cf-input" placeholder="150 000 руб./мес."><span class="cf-hint">Сумма и периодичность</span></div>
|
||
<div class="cf-group"><label class="cf-label">Срок договора</label><input class="cf-input" placeholder="1 год с даты подписания"><span class="cf-hint">Начало и окончание</span></div>
|
||
<div class="cf-group"><label class="cf-label">Подсудность</label><input class="cf-input" placeholder="По месту нахождения Принципала"><span class="cf-hint">Суд при спорах</span></div>
|
||
<div class="cf-group"><label class="cf-label">НДС</label><input class="cf-input" placeholder="Не облагается — УСН"><span class="cf-hint">Или: в т.ч. НДС 20%</span></div>
|
||
</div>
|
||
<div class="enote" style="margin-bottom:16px;max-width:740px"><img src="logos/elena-photo.jpg"><div class="et">Заполните ключевые параметры — остальное (нумерацию, ссылки на нормы, форс-мажор, реквизиты) я добавлю автоматически 💛</div></div>
|
||
<div class="create-form-actions">
|
||
<button class="cf-back" onclick="goCreateStep(1)">← Назад</button>
|
||
<button class="cf-generate" onclick="goCreateStep(3)">⚡ Сгенерировать черновик</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Шаг 3: Черновик готов -->
|
||
<div class="create-pane" id="cp-preview">
|
||
|
||
<!-- Спиннер генерации -->
|
||
<div class="doc-generating" id="doc-generating">
|
||
<div class="dg-spinner"></div>
|
||
<div class="dg-text">Елена составляет черновик…</div>
|
||
<div class="dg-sub">Проверяю нормы ГК РФ · подбираю формулировки · займёт несколько секунд</div>
|
||
</div>
|
||
|
||
<!-- Превью документа -->
|
||
<div class="doc-preview-wrap" id="doc-preview-wrap">
|
||
<div class="doc-preview-actions">
|
||
<button class="dpa-btn dpa-dl" onclick="toast('⬇️ Скачиваю агентский договор в формате DOCX — файл будет готов через секунду')">⬇ Скачать DOCX</button>
|
||
<button class="dpa-btn dpa-copy" onclick="toast('📋 Текст договора скопирован в буфер обмена')">📋 Копировать</button>
|
||
<button class="dpa-btn dpa-add" onclick="toast('📁 Черновик добавлен в дело «Кухня — агентский (ЗОВ)»')">➕ В дело</button>
|
||
<button class="cf-back" style="border-radius:10px;padding:10px 16px;font-size:13px" onclick="goCreateStep(1)">← Новый</button>
|
||
</div>
|
||
|
||
<div class="doc-preview">
|
||
<h3>АГЕНТСКИЙ ДОГОВОР № <span class="doc-blank">___</span></h3>
|
||
<div class="doc-city">г. Краснодар <span class="doc-highlight">28 мая 2025 г.</span></div>
|
||
|
||
<div class="doc-parties">
|
||
<b>ПРИНЦИПАЛ:</b> <span class="doc-highlight">ИП Васильев Руслан Геннадьевич</span>, ОГРНИП <span class="doc-blank">____________</span>, ИНН <span class="doc-blank">____________</span>, именуемый в дальнейшем «Принципал»,<br><br>
|
||
<b>АГЕНТ:</b> <span class="doc-highlight">ООО «Зов Ресторанс»</span>, ИНН <span class="doc-blank">____________</span>, КПП <span class="doc-blank">____________</span>, именуемое в дальнейшем «Агент»,<br><br>
|
||
совместно именуемые «Стороны», заключили настоящий договор о нижеследующем:
|
||
</div>
|
||
|
||
<div class="doc-article">1. Предмет договора</div>
|
||
<div class="doc-clause">1.1. Принципал поручает, а Агент обязуется за вознаграждение совершать от имени и за счёт Принципала следующие действия: <span class="doc-highlight">поиск и привлечение клиентов для ресторана</span>.</div>
|
||
<div class="doc-clause">1.2. Агент действует в пределах полномочий, предоставленных настоящим договором и доверенностью (при необходимости).</div>
|
||
|
||
<div class="doc-article">2. Вознаграждение агента</div>
|
||
<div class="doc-clause">2.1. Вознаграждение Агента составляет <span class="doc-highlight">150 000 (сто пятьдесят тысяч) рублей</span> ежемесячно. <span class="doc-highlight">НДС не облагается — Агент применяет УСН.</span></div>
|
||
<div class="doc-clause">2.2. Изменение размера вознаграждения допускается исключительно по письменному соглашению Сторон.</div>
|
||
<div class="doc-clause">2.3. Оплата производится в течение 5 (пяти) рабочих дней с момента подписания акта за отчётный период.</div>
|
||
|
||
<div class="doc-article">3. Порядок исполнения</div>
|
||
<div class="doc-clause">3.1. Агент представляет отчёт не позднее <span class="doc-highlight">5-го числа</span> месяца, следующего за отчётным, с приложением первичных документов.</div>
|
||
<div class="doc-clause">3.2. Принципал вправе заявить возражения по отчёту в течение 3 (трёх) рабочих дней. По истечении данного срока отчёт считается принятым.</div>
|
||
<div class="doc-clause">3.3. Привлечение субагентов допускается исключительно с письменного согласия Принципала.</div>
|
||
|
||
<div class="doc-article">4. Ответственность сторон</div>
|
||
<div class="doc-clause">4.1. Ответственность Принципала ограничена суммой вознаграждения за 3 (три) последних месяца. Упущенная выгода возмещению не подлежит.</div>
|
||
<div class="doc-clause">4.2. За просрочку оплаты Принципал уплачивает пеню в размере 0,1% от суммы за каждый день просрочки.</div>
|
||
|
||
<div class="doc-article">5. Срок и расторжение</div>
|
||
<div class="doc-clause">5.1. Договор вступает в силу с даты подписания и действует <span class="doc-highlight">1 (один) год</span>.</div>
|
||
<div class="doc-clause">5.2. Каждая из Сторон вправе расторгнуть договор, уведомив другую сторону письменно не менее чем за 30 (тридцать) дней.</div>
|
||
<div class="doc-clause">5.3. Пролонгация допускается только при наличии письменного согласия обеих Сторон не позднее 30 дней до окончания срока.</div>
|
||
|
||
<div class="doc-article">6. Разрешение споров</div>
|
||
<div class="doc-clause">6.1. Все споры рассматриваются в арбитражном суде <span class="doc-highlight">по месту нахождения Принципала</span>.</div>
|
||
|
||
<div style="margin-top:24px;font-size:11px;color:var(--mut);border-top:1px solid #e5e7eb;padding-top:12px">
|
||
📌 Черновик сгенерирован ЗАЩИТА · проверен по нормам ГК РФ · внесите правки если нужно · данные хранятся на вашем устройстве
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div></div>
|
||
|
||
|
||
<!-- Баланс и оплата -->
|
||
<div class="tabpane" id="p-balance">
|
||
<div class="main-body">
|
||
<div class="crumb">Кабинет</div><h1>Баланс и оплата</h1>
|
||
<!-- Hero balance -->
|
||
<div class="bal-hero">
|
||
<div class="bal-hero-num"><span id="bal-credits-num">0</span></div>
|
||
<div class="bal-hero-lbl">кредитов на балансе</div>
|
||
<div class="bal-hero-sub" id="bal-sub-status">Подписка не активна</div>
|
||
</div>
|
||
<!-- Actions -->
|
||
<div class="bal-actions">
|
||
<div class="bal-action-btn" onclick="go('pay')">➕ Пополнить баланс</div>
|
||
<div class="bal-action-btn" id="bal-refund-toggle" onclick="toggleRefundForm()">↩ Запросить возврат</div>
|
||
</div>
|
||
<!-- Refund form -->
|
||
<div class="ref-form" id="ref-form" style="display:none">
|
||
<h4>Заявка на возврат средств</h4>
|
||
<div class="ref-form-hint">Возврат производится за неиспользованные кредиты в течение 10 рабочих дней согласно оферте.</div>
|
||
<textarea id="ref-reason" placeholder="Причина возврата (необязательно)..."></textarea>
|
||
<button class="btn" style="width:100%;background:var(--bg);color:#fff;border:none;padding:12px;border-radius:10px;font-weight:700;cursor:pointer" onclick="submitRefund()">Отправить заявку</button>
|
||
</div>
|
||
<!-- History -->
|
||
<div class="admin-section" style="margin-top:8px">
|
||
<div class="admin-section-hdr">
|
||
<div class="admin-section-ttl">История платежей</div>
|
||
</div>
|
||
<div id="bal-history"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</section>
|
||
|
||
<script>
|
||
/* ── СТАТИСТИКА ── */
|
||
function statTrack(mode, custom) {
|
||
const key = 'zashita_intake_stats';
|
||
const stats = JSON.parse(localStorage.getItem(key) || '[]');
|
||
stats.push({ mode, custom: custom||null, ts: new Date().toISOString() });
|
||
localStorage.setItem(key, JSON.stringify(stats));
|
||
renderStats();
|
||
}
|
||
function statGet() {
|
||
const raw = JSON.parse(localStorage.getItem('zashita_intake_stats') || '[]');
|
||
const counts = { novice:0, mid:0, pro:0, custom:0 };
|
||
raw.forEach(r => { if(counts[r.mode]!==undefined) counts[r.mode]++; else counts.custom++; });
|
||
return { counts, total: raw.length, customs: raw.filter(r=>r.mode==='custom').map(r=>r.custom) };
|
||
}
|
||
function renderStats() {
|
||
let el = document.getElementById('stats-pill');
|
||
if (!el) { el = document.createElement('div'); el.id='stats-pill'; el.className='stats-pill'; el.title='Нажать — очистить'; el.onclick=()=>{localStorage.removeItem('zashita_intake_stats');renderStats();}; document.body.appendChild(el); }
|
||
const s = statGet();
|
||
if (!s.total) { el.style.display='none'; return; }
|
||
el.style.display='block';
|
||
el.innerHTML = `<b>Intake-статистика</b> (${s.total})<br>`
|
||
+ `🙋 Новичок: ${s.counts.novice} · 📖 Средний: ${s.counts.mid}<br>`
|
||
+ `⚖️ Юрист: ${s.counts.pro} · ✏️ Другое: ${s.counts.custom}`
|
||
+ (s.customs.length ? `<br><span style="color:rgba(255,255,255,.5);font-size:10px">${s.customs.slice(-2).join(' / ')}</span>` : '');
|
||
}
|
||
|
||
/* ── КОНТЕНТ ПО РЕЖИМУ ── */
|
||
const MODES = {
|
||
novice: {
|
||
badge: '🙋 Режим: объясняем с нуля',
|
||
badgeCls: 'mode-novice',
|
||
ack: 'Хорошо, что сказали 💛 Буду рядом — объясню всё простым языком, без страшных слов. Если что-то непонятно — просто спросите, не стесняйтесь.',
|
||
introTail: 'Не пугайтесь —',
|
||
r1q: '«Агент несёт полную ответственность за качество выполненных работ перед конечным потребителем»',
|
||
r1: 'Смотрите: это значит, что если у клиента сломается мебель или он пожалуется — по этому пункту отвечаете <b>вы лично</b>, а не компания-заказчик. То есть возвраты и штрафы могут прийти на ваш карман. Это типовая ловушка — не переживайте, мы её аккуратно перепишем.',
|
||
r2q: '«Агент обязуется возместить Принципалу все финансовые потери, возникшие вследствие ненадлежащего исполнения обязательств»',
|
||
r2: 'О чём это говорит: вы соглашаетесь покрыть «все финансовые потери компании» — и <b>без верхней границы суммы</b>. По сути это открытый кошелёк. Звучит пугающе, понимаю — но от этого защититься просто, я покажу как.',
|
||
r3q: '«Агент выполняет работы лично, в установленные часы, на оборудовании Принципала, по его инструкциям»',
|
||
r3: 'Это значит что: договор назван агентским, но по описанию работы — он похож на трудовой. Налоговая вправе это заметить и <b>доначислить НДФЛ и взносы задним числом</b>. Звучит тревожно — но от этого реально защититься.',
|
||
lock: '🔒 Это только 3 момента из 12. Есть ещё — и там тоже важное. В полном разборе я объясню каждый пункт простым языком, скажу что именно нужно изменить и почему другая сторона обязана на это согласиться. <b>Вы уйдёте с чётким пониманием что подписываете — и уверенностью, что вас защитили</b> 💛',
|
||
forkQ: 'Чего бы вам хотелось? Объясню каждый путь — выберем вместе:'
|
||
},
|
||
mid: {
|
||
badge: '📖 Режим: по делу, без лишнего',
|
||
badgeCls: 'mode-mid',
|
||
ack: 'Принято. Работаем по делу — цитата из договора, риск, что делать. Без воды.',
|
||
introTail: 'Фиксируем критичные.',
|
||
r1q: '«Агент несёт полную ответственность за качество выполненных работ перед конечным потребителем»',
|
||
r1: '<b>Риск:</b> ответственность перед конечным потребителем переложена на вас. По ЗоЗПП ст. 4–29 — это влечёт прямые претензии и штрафы в ваш адрес, минуя Принципала. <b>Решение:</b> ограничить ответственность агента пределами вознаграждения.',
|
||
r2q: '«Агент обязуется возместить Принципалу все финансовые потери, возникшие вследствие ненадлежащего исполнения»',
|
||
r2: '<b>Риск:</b> неограниченная финансовая ответственность — ст. 330 ГК не требует устанавливать потолок, но без него сумма ничем не ограничена. <b>Решение:</b> добавить cap = сумма вознаграждения по договору.',
|
||
r3q: '«Агент выполняет работы лично, в установленные часы, на оборудовании Принципала, по его инструкциям»',
|
||
r3: '<b>Риск:</b> признаки трудовых отношений по ст. 19.1 ТК. При налоговой проверке — переквалификация и доначисление НДФЛ + взносов. <b>Решение:</b> переформулировать признаки самостоятельности.',
|
||
lock: '🔒 Ещё 9 рисков, из них 2 критичных — в полном заключении с нормами и готовыми формулировками.',
|
||
forkQ: 'Как будем действовать?'
|
||
},
|
||
pro: {
|
||
badge: '⚖️ Профессиональный режим',
|
||
badgeCls: 'mode-pro',
|
||
ack: 'Принял. Цитата → норма → квалификация → рекомендация. Поехали.',
|
||
introTail: 'Выявлено 5 критических.',
|
||
r1q: '«Агент несёт полную ответственность за качество выполненных работ перед конечным потребителем»',
|
||
r1: '<b>Квалификация:</b> прямое возложение ответственности исполнителя перед третьим лицом (потребителем) в нарушение ст. 4, 18, 29 ЗоЗПП — ответственность принципала не исключается, а дублируется. <b>Рекомендация:</b> п.1.1 изложить в редакции: «Агент несёт ответственность перед Принципалом в пределах суммы агентского вознаграждения».',
|
||
r2q: '«Агент обязуется возместить Принципалу все финансовые потери, возникшие вследствие ненадлежащего исполнения»',
|
||
r2: '<b>Квалификация:</b> неограниченная договорная ответственность, ст. 330–333 ГК РФ. Судебная практика: без cap суд снижает по ст. 333 ГК, но только по заявлению. <b>Рекомендация:</b> установить cap = агентское вознаграждение × 2.',
|
||
r3q: '«Агент выполняет работы лично, в установленные часы, на оборудовании Принципала, по его инструкциям»',
|
||
r3: '<b>Квалификация:</b> признаки трудовых отношений по ст. 15, 19.1 ТК РФ: личное исполнение, режим рабочего времени, инструктаж, материально-техническое обеспечение. Риск: переквалификация + ст. 122 НК РФ (недоимка + пени + штраф 20%). <b>Рекомендация:</b> исключить нормы п.п. о личном исполнении и режиме.',
|
||
lock: '📋 Полное заключение: 12 рисков, нормативная база, альтернативные формулировки, протокол разногласий.',
|
||
forkQ: 'Стратегия:'
|
||
}
|
||
};
|
||
|
||
function setMode(mode) {
|
||
const custom = mode === 'custom' ? (document.getElementById('intake-custom').value.trim() || 'не указано') : null;
|
||
if (mode === 'custom' && !custom) { document.getElementById('intake-custom').focus(); return; }
|
||
statTrack(mode, custom);
|
||
|
||
const cfg = MODES[mode] || MODES.mid;
|
||
// badge
|
||
const badge = document.getElementById('elena-mode-badge');
|
||
badge.innerHTML = `<span class="mode-badge ${cfg.badgeCls}">${cfg.badge}</span>`;
|
||
// step2 content
|
||
document.getElementById('el-ack').innerHTML = custom
|
||
? `Понял: «${custom}». Подстроюсь под вас — буду объяснять по ходу.`
|
||
: cfg.ack;
|
||
document.getElementById('el-intro-tail').textContent = cfg.introTail;
|
||
document.getElementById('r1-quote').textContent = cfg.r1q;
|
||
document.getElementById('r1-text').innerHTML = cfg.r1;
|
||
document.getElementById('r2-quote').textContent = cfg.r2q;
|
||
document.getElementById('r2-text').innerHTML = cfg.r2;
|
||
document.getElementById('r3-quote').textContent = cfg.r3q;
|
||
document.getElementById('r3-text').innerHTML = cfg.r3;
|
||
document.getElementById('el-lock').innerHTML = cfg.lock;
|
||
document.getElementById('el-fork-q').textContent = cfg.forkQ;
|
||
// show upload step
|
||
document.getElementById('el-step1').style.display = 'none';
|
||
document.getElementById('el-step-upload').style.display = 'block';
|
||
window.scrollTo(0, 0);
|
||
}
|
||
|
||
/* ── ТИПЫ ДОГОВОРОВ ── */
|
||
const CTYPES = {
|
||
agent: {
|
||
emoji:'🤝', name:'агентский договор',
|
||
comment:'Агент действует от имени или за счёт другой стороны. Главные риски здесь — объём ответственности перед третьими лицами и признаки трудовых отношений.',
|
||
delivRec:'partner',
|
||
intro:'С учётом выявленных нарушений потенциальный ущерб — от <b>120 000 до 350 000 ₽</b>: налоговые доначисления, штрафы от потребителей, неограниченная ответственность перед Принципалом. Три варианта:',
|
||
delivDesc:{
|
||
protocol:'Список требований с нормой закона под каждым. Не «хочу изменить», а «данная редакция противоречит ст. 330 ГК». Контрагенту придётся либо согласиться, либо объяснить почему закон неважен.',
|
||
redact:'Новая редакция каждого спорного пункта + объяснение логики изменений. Контрагент видит аргументы, а не давление — меньше возражений, быстрее к подписи.',
|
||
clean:'Все спорные пункты переписаны и готовы к подписанию — без пояснений для контрагента. Подходит если другая сторона уже согласна на правки.',
|
||
partner:'Договор написан так, чтобы обе стороны видели свою выгоду. Контрагент сам не захочет его менять — его интересы уже учтены. Подписывают без торга 💛'
|
||
}
|
||
},
|
||
realty: {
|
||
emoji:'🏠', name:'договор купли-продажи недвижимости',
|
||
comment:'В недвижимости цена ошибки особенно высока. Проверяю обременения, условия передачи объекта и ответственность за скрытые дефекты.',
|
||
delivRec:'partner',
|
||
intro:'В сделках с недвижимостью любая неточность стоит дорого — вплоть до <b>потери аванса или расторжения сделки</b>. Три варианта:',
|
||
delivDesc:{
|
||
protocol:'Фиксируем спорные условия по передаче, дефектам и срокам — со ссылками. Основа для предметного разговора. Хорошо работает с частными продавцами.',
|
||
redact:'Переписываем проблемные пункты с объяснением зачем. Особенно эффективно с застройщиком — они реагируют на аргументы, а не на просьбы.',
|
||
clean:'Договор полностью переписан и готов к подписанию. Все риски закрыты, формулировки чёткие.',
|
||
partner:'Договор сбалансирован: другая сторона видит, что её интересы учтены. Сделки закрываются быстрее и без претензий после регистрации 💛'
|
||
}
|
||
},
|
||
auto: {
|
||
emoji:'🚗', name:'договор купли-продажи автомобиля',
|
||
comment:'Смотрю на гарантии состояния, скрытые дефекты и условия передачи.',
|
||
delivRec:'clean',
|
||
intro:'Главные риски — <b>скрытые дефекты без гарантии возврата</b>. Потенциальные потери: от стоимости ремонта до полной цены автомобиля. Три пути:',
|
||
delivDesc:{
|
||
protocol:'Гарантии состояния, ответственность за скрытые дефекты, порядок расторжения — со ссылками. Основа для переговоров до подписания.',
|
||
redact:'Новая редакция с объяснением зачем. Продавец понимает логику — реже отказывает. Подходит если продавец настроен на диалог.',
|
||
clean:'Договор полностью готов к подписанию — скрытые дефекты закрыты, условия передачи чёткие. Приходите с текстом, а не со списком претензий 💛',
|
||
partner:'Вариант, где продавец тоже видит свою защиту. Снижает напряжение — подписывают быстро и без претензий.'
|
||
}
|
||
},
|
||
construction: {
|
||
emoji:'🛋️', name:'договор подряда',
|
||
comment:'Договор подряда — здесь критичны сроки, критерии качества результата и ответственность за задержки.',
|
||
delivRec:'redact',
|
||
intro:'Основные риски — <b>штрафы за просрочку без верхней границы</b> и размытые критерии качества. Потенциальные потери: от устранения недостатков до полной переделки. Три варианта:',
|
||
delivDesc:{
|
||
protocol:'Требования к срокам, критериям приёмки и порядку устранения дефектов — с нормами. Заказчику сложнее отказать без обоснования.',
|
||
redact:'Переписываем спорные пункты, объясняем зачем. Обе стороны понимают что подписывают — меньше споров при сдаче. Оптимальный выбор для подряда 💛',
|
||
clean:'Договор переписан и готов к подписанию. Сроки зафиксированы, критерии приёмки чёткие, ответственность ограничена.',
|
||
partner:'Договор учитывает риски заказчика и подрядчика. Заказчик видит защиту своих интересов — соглашается быстрее.'
|
||
}
|
||
},
|
||
services: {
|
||
emoji:'🎯', name:'договор оказания услуг',
|
||
comment:'В услугах часто размыт сам результат и ответственность исполнителя.',
|
||
delivRec:'redact',
|
||
intro:'Главные риски — <b>размытый результат и ответственность за то, что не зависит от вас</b>. Потенциальные потери: от возврата всей суммы до штрафных санкций. Три пути:',
|
||
delivDesc:{
|
||
protocol:'Чёткие требования к тому, что считается результатом, срокам и основаниям для расторжения. Снимает частые точки споров до старта работ.',
|
||
redact:'Новая редакция с объяснением логики. Заказчик понимает условия — меньше конфликтов при сдаче. Лучший выбор для услуг 💛',
|
||
clean:'Договор полностью готов к подписанию — результат зафиксирован, критерии приёмки прописаны, ответственность ограничена.',
|
||
partner:'Договор балансирует интересы исполнителя и заказчика. Работают без конфликтов и платят без задержек.'
|
||
}
|
||
},
|
||
labor: {
|
||
emoji:'📋', name:'трудовой договор',
|
||
comment:'Трудовой договор — смотрю на режим работы, зоны ответственности и условия расторжения.',
|
||
delivRec:'consult',
|
||
intro:'Потенциальные потери — <b>от нескольких окладов до судебного восстановления</b>. Работодатель может переложить ответственность сверх нормы ТК. Три варианта:',
|
||
delivDesc:{
|
||
protocol:'Пункты, противоречащие ТК, с нормами. Основа для переговоров с HR: работодатель видит закон, а не просьбу. Большинство соглашаются на правки 💛',
|
||
redact:'Новые формулировки спорных условий с объяснением. Работодатель понимает запрос — проще найти компромисс.',
|
||
clean:'Договор приведён в соответствие с ТК и готов к подписанию. Ваши права зафиксированы.',
|
||
partner:'Договор учитывает интересы работника и работодателя. Подписывают без споров и работают без неожиданных претензий.'
|
||
}
|
||
},
|
||
loan: {
|
||
emoji:'💰', name:'договор займа',
|
||
comment:'Ключевые риски займа — скрытые проценты, штрафные санкции и условия досрочного требования.',
|
||
delivRec:'redact',
|
||
intro:'При наихудшем сценарии <b>задолженность вырастет в несколько раз</b> от первоначальной суммы. Скрытые проценты и неограниченные штрафы — основной инструмент давления. Три пути:',
|
||
delivDesc:{
|
||
protocol:'Требования по процентам, порядку штрафов и условиям погашения — со ссылками. Кредитору сложнее отказать без объяснений.',
|
||
redact:'Новая редакция ключевых пунктов с объяснением — снимает инструменты давления на заёмщика. Оптимальный выбор для займов с физлицами и МФО 💛',
|
||
clean:'Договор готов к подписанию. Проценты зафиксированы, штрафы ограничены, условия прозрачны.',
|
||
partner:'Договор сбалансирован: кредитор защищён, заёмщик знает точные условия без скрытых ловушек.'
|
||
}
|
||
},
|
||
supply: {
|
||
emoji:'📦', name:'договор поставки',
|
||
comment:'Поставка — проверяю условия приёмки, ответственность за качество и что происходит при просрочке.',
|
||
delivRec:'reply',
|
||
intro:'Основные риски — <b>неограниченная неустойка за просрочку и ответственность за качество без потолка</b>. Потенциальные потери: от стоимости партии до срыва цепочки поставок. Три варианта:',
|
||
delivDesc:{
|
||
protocol:'Требования по приёмке, критериям качества и ограничению неустойки — со ссылками. Контрагент видит закон, а не просьбу.',
|
||
redact:'Новая редакция спорных условий с объяснением. Обе стороны знают правила до старта — меньше споров при исполнении 💛',
|
||
clean:'Договор готов к подписанию. Порядок приёмки чёткий, неустойка ограничена, ответственность зафиксирована.',
|
||
partner:'Договор учитывает интересы поставщика и покупателя. Подписывают быстро и работают без задержек.'
|
||
}
|
||
},
|
||
other: {
|
||
emoji:'📄', name:'договор',
|
||
comment:'Изучила структуру. Нашла пункты, которые стоит проверить внимательнее.',
|
||
delivRec:'consult',
|
||
intro:'Формальные нарушения дешевле устранить <b>до подписания</b>, чем оспаривать потом. Три варианта:',
|
||
delivDesc:{
|
||
protocol:'Список требований с правовым обоснованием. Основа для переговоров если знаете что именно изменить.',
|
||
redact:'Новая редакция спорных пунктов с объяснением. Контрагент понимает зачем — меньше возражений.',
|
||
clean:'Договор полностью готов к подписанию. Риски закрыты, формулировки чёткие 💛',
|
||
partner:'Договор учитывает интересы обеих сторон. Подписывают без торга и выполняют без претензий.'
|
||
}
|
||
}
|
||
};
|
||
|
||
const CTYPES_KEYWORDS = {
|
||
agent: ['агент','принципал','агентск','от имени и за счёт','за счёт принципала'],
|
||
realty: ['квартир','недвижим','жиль','комнат','нежилое','земельн','ипотек','объект недвижим','жилой дом'],
|
||
auto: ['автомобил','транспортн средств','машин','птс','пробег','кузов'],
|
||
construction: ['подряд','мебел','изготовл','монтаж','строител','ремонт','подрядчик','заказчик','результат работ'],
|
||
services: ['оказани','услуг','исполнител','заказчик','сервис','консульт','разработ','дизайн'],
|
||
labor: ['трудов','работодател','работник','должност','оклад','отпуск','увольнен','рабочее время'],
|
||
loan: ['займ','заём','кредит','процент годов','долг','заемщик','заёмщик','сумма займа'],
|
||
supply: ['поставщик','покупател','товар','партия','поставка','отгрузк','накладн']
|
||
};
|
||
|
||
let _demoCtypeIdx = 0;
|
||
const _demoSeq = ['agent','realty','auto','construction','services','labor','loan','supply'];
|
||
|
||
function detectCtype(text) {
|
||
if (text && text.length > 30) {
|
||
const t = text.toLowerCase();
|
||
for (const [key, kws] of Object.entries(CTYPES_KEYWORDS)) {
|
||
if (kws.some(kw => t.includes(kw))) return key;
|
||
}
|
||
return 'other';
|
||
}
|
||
// демо-режим: каждый клик — новый тип
|
||
const key = _demoSeq[_demoCtypeIdx % _demoSeq.length];
|
||
_demoCtypeIdx++;
|
||
return key;
|
||
}
|
||
|
||
function showResults(ctypeKey) {
|
||
_curCtypeKey = ctypeKey || 'other';
|
||
// спрятать предыдущие шаги на случай прямого вызова
|
||
['el-step-upload','el-step-scan','el-step1'].forEach(id => {
|
||
const el = document.getElementById(id);
|
||
if (el) el.style.display = 'none';
|
||
});
|
||
const ctype = CTYPES[ctypeKey] || CTYPES.other;
|
||
|
||
// тип договора в первой реплике
|
||
document.getElementById('el-scan-type').textContent = ctype.emoji + ' ' + ctype.name;
|
||
const noteEl = document.getElementById('el-ctype-note');
|
||
noteEl.textContent = ctype.comment;
|
||
noteEl.style.display = ctype.comment ? 'block' : 'none';
|
||
|
||
// убрать старую подсветку, поставить новую
|
||
document.querySelectorAll('.deliv').forEach(el => {
|
||
el.classList.remove('deliv-highlighted');
|
||
});
|
||
// вступление Елены (оценка ущерба)
|
||
const pitchEl = document.getElementById('el-ctype-pitch');
|
||
const pitchMsg = document.getElementById('el-pitch-msg');
|
||
if (ctype.intro) {
|
||
pitchEl.innerHTML = ctype.intro;
|
||
pitchMsg.style.display = '';
|
||
} else {
|
||
pitchMsg.style.display = 'none';
|
||
}
|
||
|
||
// описания на карточках
|
||
if (ctype.delivDesc) {
|
||
['protocol','redact','clean','partner'].forEach(key => {
|
||
const el = document.getElementById('dd2-' + key);
|
||
if (el && ctype.delivDesc[key]) el.textContent = ctype.delivDesc[key];
|
||
});
|
||
}
|
||
|
||
// убрать badge у всех, потом поставить на нужный
|
||
document.querySelectorAll('.deliv-badge').forEach(b => b.style.display = 'none');
|
||
|
||
if (ctype.delivRec) {
|
||
const recEl = document.getElementById('deliv-' + ctype.delivRec);
|
||
if (recEl) {
|
||
recEl.classList.add('deliv-highlighted');
|
||
let badge = recEl.querySelector('.deliv-badge');
|
||
if (!badge) {
|
||
badge = document.createElement('span');
|
||
badge.className = 'deliv-badge';
|
||
recEl.appendChild(badge);
|
||
}
|
||
badge.textContent = 'Рекомендуем';
|
||
badge.style.display = '';
|
||
}
|
||
}
|
||
|
||
// показать результаты
|
||
document.getElementById('el-step-scan').style.display = 'none';
|
||
document.getElementById('el-step2').style.display = 'block';
|
||
document.getElementById('el-actbar').style.display = 'flex';
|
||
document.getElementById('el-step2').scrollIntoView({ behavior: 'smooth' });
|
||
}
|
||
|
||
/* ── СКАНИРОВАНИЕ ── */
|
||
const SCAN_PHRASES = [
|
||
'Читаю договор...',
|
||
'Проверяю условия сторон...',
|
||
'Ищу скрытые риски...',
|
||
'Анализирую ответственность...',
|
||
'Оцениваю сроки и санкции...',
|
||
'Формирую заключение...'
|
||
];
|
||
|
||
function startScan() {
|
||
const text = (document.getElementById('el-paste').value || '').trim();
|
||
const ctypeKey = detectCtype(text);
|
||
|
||
document.getElementById('el-step-upload').style.display = 'none';
|
||
document.getElementById('el-step-scan').style.display = 'block';
|
||
window.scrollTo(0, 0);
|
||
|
||
let i = 0;
|
||
const lbl = document.getElementById('scan-label');
|
||
const interval = setInterval(() => {
|
||
i = (i + 1) % SCAN_PHRASES.length;
|
||
lbl.style.opacity = '0';
|
||
setTimeout(() => { lbl.textContent = SCAN_PHRASES[i]; lbl.style.opacity = '1'; }, 180);
|
||
}, 800);
|
||
|
||
setTimeout(() => {
|
||
clearInterval(interval);
|
||
lbl.style.opacity = '0';
|
||
setTimeout(() => { showResults(ctypeKey); }, 200);
|
||
}, 4000);
|
||
}
|
||
|
||
/* ── ВЫБОР DELIVERABLE ── */
|
||
const DELIVS = {
|
||
protocol: {
|
||
ttl:'Протокол разногласий', h2:'Протокол разногласий по вашему договору',
|
||
p1:['1 490 ₽','Без комментариев','Все спорные пункты — готовый список изменений без пояснений'],
|
||
p2:['2 190 ₽','С обоснованием','Те же пункты + правовое обоснование каждого требования'],
|
||
p3:['от 3 490 ₽','Партнёрская версия','Протокол с формулировками, выгодными обеим сторонам + Елена сопровождает'],
|
||
pitch:'Когда другая сторона получает просто список требований без объяснений — первая реакция почти всегда «нет». Это не злой умысел, так работает психология переговоров.<br><br><b>С обоснованием</b> каждое требование превращается из вашей «хотелки» в правовую норму. Контрагент уже не может просто отказать — ему придётся объяснить, почему закон не имеет значения. Практически никто не идёт на это.<br><br><b>Партнёрская версия</b> — Елена составляет текст так, чтобы контрагент сам хотел согласиться. Договор, где обе стороны видят свою выгоду, подписывают быстро и выполняют честно 💛',
|
||
def:'2 190 ₽'
|
||
},
|
||
redact: {
|
||
ttl:'Переработка с комментариями', h2:'Переработанный договор по вашему случаю',
|
||
p1:['1 990 ₽','Без комментариев','Новая редакция всех спорных пунктов — чистый текст без объяснений'],
|
||
p2:['2 990 ₽','С комментариями','Та же редакция + пояснение что изменено и зачем по каждому пункту'],
|
||
p3:['от 4 490 ₽','Партнёрская редакция','Договор учитывает интересы обеих сторон + Елена сопровождает до подписи'],
|
||
pitch:'Молча прийти с переделанным договором — контрагент чувствует давление и начинает защищаться. Переписка растягивается на недели.<br><br><b>С комментариями</b> вы открываете диалог: вот что изменено, вот почему это справедливо. Люди принимают изменения, когда понимают логику. Меньше раундов — быстрее к подписи.<br><br><b>Партнёрская редакция</b> — Елена рядом до финала. Если контрагент выдвигает встречные возражения, она держит вашу позицию и не даёт потерять то, что важно 💛',
|
||
def:'2 990 ₽'
|
||
},
|
||
clean: {
|
||
ttl:'Чистая редакция', h2:'Договор готов к подписанию',
|
||
p1:['1 790 ₽','Чистая редакция','Все пункты переписаны — договор готов к подписанию, без пояснений'],
|
||
p2:['2 690 ₽','Редакция с пояснениями','Тот же результат + объяснение каждого изменения для вас и контрагента'],
|
||
p3:['от 3 990 ₽','Партнёрская редакция','Чистый договор с балансом интересов + Елена рядом на переговорах'],
|
||
pitch:'Договор уже защищает вас — осталось только подписать. Но у контрагента будут вопросы: «почему именно так?» Без ответов на них переговоры затягиваются.<br><br><b>С пояснениями</b> он получает и текст, и понимание: что изменено, почему это честно. Вопросы снимаются до того, как возникли. Путь к подписи становится короче.<br><br><b>Партнёрская редакция</b> — Елена пишет так, что контрагент видит баланс, а не давление. Такие договоры подписывают без торга и выполняют без претензий 💛',
|
||
def:'2 690 ₽'
|
||
},
|
||
partner: {
|
||
ttl:'Партнёрская редакция', h2:'Договор, который устроит обе стороны',
|
||
p1:['2 990 ₽','Партнёрская редакция','Все пункты переработаны с учётом интересов обеих сторон, без сопровождения'],
|
||
p2:['3 990 ₽','Редакция с обоснованием','Тот же результат + аргументы для переговоров по каждому пункту'],
|
||
p3:['от 5 900 ₽','Полное сопровождение','Договор + Елена ведёт переписку и переговоры до финальной подписи'],
|
||
pitch:'Партнёрский подход — это не уступки. Это когда текст уже содержит ответ на главный вопрос контрагента: «почему мне это выгодно?». Когда ответ уже в договоре — не о чём торговаться.<br><br><b>С обоснованием</b> у вас есть готовые аргументы на любые встречные возражения. Вы входите в переговоры спокойно — Елена уже предусмотрела ходы за другую сторону.<br><br><b>Полное сопровождение</b> — Елена ведёт переписку сама, держит вашу позицию и доводит до финальной подписи. Ваша задача: согласовать итоговый текст 💛',
|
||
def:'3 990 ₽'
|
||
},
|
||
consult: {
|
||
ttl:'Консультация по договору', h2:'Разбор договора — ответы на ваши вопросы',
|
||
p1:['790 ₽','Базовый разбор','Задаёте до 5 вопросов по договору — AI отвечает развёрнуто по каждому пункту в течение 2 часов'],
|
||
p2:['1 490 ₽','Полный разбор','AI анализирует весь договор, находит все риски и отвечает на любые ваши вопросы без ограничений'],
|
||
p3:['от 2 490 ₽','Разбор + заключение','Полный AI-анализ + письменное заключение с перечнем рисков и конкретными рекомендациями'],
|
||
pitch:'Иногда важнее не документ, а понять — что именно подписываешь и почему это опасно.<br><br><b>Консультация в чате</b> — конкретные вопросы, чёткие ответы письменно. Всё сохраняется, можно перечитать.<br><br><b>Голосовой разбор</b> — живой разговор, юрист читает договор вместе с вами. 30 минут меняют картину полностью.<br><br><b>С заключением</b> — получаете и понимание, и документ на руках. Можно показать другой стороне как независимое правовое мнение 💛',
|
||
def:'1 490 ₽'
|
||
},
|
||
reply: {
|
||
ttl:'Ответ контрагенту', h2:'Ответ на возражения другой стороны',
|
||
p1:['990 ₽','Шаблон ответа','Готовый текст ответа на конкретный отказ — с вашей правовой позицией и нужным тоном'],
|
||
p2:['1 690 ₽','Развёрнутый ответ','Тот же ответ + аргументы на 2–3 хода вперёд: закрываем типичные встречные возражения заранее'],
|
||
p3:['от 2 990 ₽','Переговорное сопровождение','Елена ведёт переписку с контрагентом вместо вас — до момента согласия или официального отказа'],
|
||
pitch:'Когда контрагент отказывает — первый импульс: уступить или спорить наугад. Оба пути проигрышные.<br><br><b>Шаблон ответа</b> — правильная позиция в нужном тоне. Со ссылкой на норму. Контрагент понимает: вы знаете о чём говорите.<br><br><b>Развёрнутый ответ</b> — мы предусматриваем их следующий ход заранее. Вы входите в переписку с ответами на возражения, которые ещё не прозвучали.<br><br><b>Сопровождение</b> — Елена ведёт всю переписку. Вы только согласуете финальные ходы 💛',
|
||
def:'1 690 ₽'
|
||
}
|
||
};
|
||
|
||
function selectDeliv(key) {
|
||
_selDeliv = key;
|
||
const d = DELIVS[key];
|
||
document.getElementById('pay-ttl').textContent = d.ttl;
|
||
document.getElementById('pay-h2').textContent = d.h2;
|
||
document.getElementById('p1-price').textContent = d.p1[0];
|
||
document.getElementById('p1-name').textContent = d.p1[1];
|
||
document.getElementById('p1-desc').textContent = d.p1[2];
|
||
document.getElementById('p2-price').textContent = d.p2[0];
|
||
document.getElementById('p2-name').textContent = d.p2[1];
|
||
document.getElementById('p2-desc').textContent = d.p2[2];
|
||
document.getElementById('p3-price').textContent = d.p3[0];
|
||
document.getElementById('p3-name').textContent = d.p3[1];
|
||
document.getElementById('p3-desc').textContent = d.p3[2];
|
||
document.getElementById('pay-pitch').innerHTML = d.pitch;
|
||
// субтитр: тип договора из детекции
|
||
const ct = CTYPES[_curCtypeKey] || CTYPES.other;
|
||
const ctName = ct.name.charAt(0).toUpperCase() + ct.name.slice(1);
|
||
document.getElementById('pay-sub').textContent = ct.emoji + ' ' + ctName + ' · цена под ваш случай';
|
||
// сбросить выбор на средний план и показать инструкции
|
||
selectPlan(2);
|
||
go('pay');
|
||
}
|
||
|
||
/* ── ТОСТ ── */
|
||
let _toastT;
|
||
function toast(msg){
|
||
let el=document.getElementById('toast');
|
||
if(!el){el=document.createElement('div');el.id='toast';el.className='toast';document.body.appendChild(el);}
|
||
el.innerHTML='<span class="tk">✓</span>'+msg;
|
||
el.classList.add('show'); clearTimeout(_toastT);
|
||
_toastT=setTimeout(()=>el.classList.remove('show'),2600);
|
||
}
|
||
function go(id){document.querySelectorAll('.screen').forEach(s=>s.classList.toggle('on',s.id===id));
|
||
if(id==='admin' && typeof _initAdmin==='function') setTimeout(_initAdmin,50);;window.scrollTo(0,0);}
|
||
/* ── СВОЙ ЗАПРОС ── */
|
||
let _customOpen = false;
|
||
let _voiceRec = null;
|
||
|
||
function toggleCustomReq() {
|
||
_customOpen = !_customOpen;
|
||
const area = document.getElementById('custom-req-area');
|
||
const btn = document.getElementById('custom-req-btn');
|
||
area.style.display = _customOpen ? 'block' : 'none';
|
||
btn.textContent = _customOpen ? '✕ Закрыть' : '✏️ Нужен другой формат? Опишите задачу →';
|
||
if (_customOpen) {
|
||
area.scrollIntoView({ behavior: 'smooth' });
|
||
setTimeout(() => document.getElementById('custom-text').focus(), 350);
|
||
}
|
||
}
|
||
|
||
function toggleVoice() {
|
||
const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
|
||
const btn = document.getElementById('custom-voice-btn');
|
||
if (!SR) { btn.title='Не поддерживается — введите текстом'; btn.style.opacity='.4'; return; }
|
||
if (_voiceRec) { _voiceRec.stop(); return; }
|
||
_voiceRec = new SR();
|
||
_voiceRec.lang = 'ru-RU';
|
||
_voiceRec.continuous = true;
|
||
_voiceRec.interimResults = true;
|
||
const ta = document.getElementById('custom-text');
|
||
const base = ta.value;
|
||
_voiceRec.onresult = e => {
|
||
let t = '';
|
||
for (let i = e.resultIndex; i < e.results.length; i++) t += e.results[i][0].transcript;
|
||
ta.value = (base ? base + ' ' : '') + t;
|
||
};
|
||
_voiceRec.onerror = _voiceRec.onend = () => {
|
||
_voiceRec = null;
|
||
btn.classList.remove('recording');
|
||
btn.innerHTML = '🎤';
|
||
};
|
||
_voiceRec.start();
|
||
btn.classList.add('recording');
|
||
btn.innerHTML = '⏹';
|
||
}
|
||
|
||
function submitCustomReq() {
|
||
const text = (document.getElementById('custom-text').value || '').trim();
|
||
if (!text) { document.getElementById('custom-text').focus(); return; }
|
||
if (_voiceRec) { _voiceRec.stop(); }
|
||
// Сохраняем в localStorage для анализа
|
||
const key = 'zashita_custom_delivs';
|
||
const arr = JSON.parse(localStorage.getItem(key) || '[]');
|
||
arr.push({
|
||
ts: new Date().toISOString(),
|
||
ctype: (document.getElementById('el-scan-type') || {}).textContent || '',
|
||
text: text
|
||
});
|
||
localStorage.setItem(key, JSON.stringify(arr));
|
||
renderCustomStats();
|
||
// Скрываем форму, показываем подтверждение
|
||
document.querySelector('.custom-input-block').style.display = 'none';
|
||
document.getElementById('custom-req-btn').style.display = 'none';
|
||
const short = text.length > 90 ? text.slice(0, 90) + '…' : text;
|
||
document.getElementById('custom-confirm-text').innerHTML =
|
||
`Записала! Передам юристу:<br><b>«${short}»</b><br><br>Свяжемся с вами в течение 24 часов. Обычно — быстрее 🙂`;
|
||
const conf = document.getElementById('custom-confirm');
|
||
conf.style.display = 'flex';
|
||
conf.scrollIntoView({ behavior: 'smooth' });
|
||
}
|
||
|
||
function renderCustomStats() {
|
||
const arr = JSON.parse(localStorage.getItem('zashita_custom_delivs') || '[]');
|
||
let el = document.getElementById('custom-stats-pill');
|
||
if (!arr.length) { if (el) el.style.display = 'none'; return; }
|
||
if (!el) {
|
||
el = document.createElement('div'); el.id = 'custom-stats-pill';
|
||
el.className = 'stats-pill'; el.style.bottom = '52px';
|
||
el.title = 'Открыть аналитику';
|
||
el.onclick = () => { renderCustomAdmin(); go('custom-admin'); };
|
||
document.body.appendChild(el);
|
||
}
|
||
el.style.display = 'block';
|
||
el.innerHTML = `<b>Свои запросы (${arr.length})</b><br>`
|
||
+ arr.slice(-3).map(r =>
|
||
`<span style="color:rgba(255,255,255,.6);font-size:10px">· ${(r.ctype||'').trim().slice(0,20)} — ${(r.text||'').slice(0,38)}</span>`
|
||
).join('<br>');
|
||
}
|
||
|
||
|
||
/* ── ПОДРОБНЫЕ ИНСТРУКЦИИ ПО ПЛАНУ ── */
|
||
let _selDeliv = 'protocol';
|
||
let _selPlan = 2;
|
||
let _curCtypeKey = 'other';
|
||
|
||
const PLAN_PITCH = {
|
||
protocol: {
|
||
1: `<b>Что вы получите</b><br>Готовый протокол разногласий — наши формулировки вместо ваших проблемных пунктов. Чистый файл, без пояснений.<br><br><b>Как использовать:</b><div class="pi-step"><span class="pi-n">1</span><span>Отправьте файл контрагенту — мессенджер, e-mail или распечатка.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Добавьте текст: <i>«Направляю протокол разногласий к договору. Прошу подтвердить принятие или предоставить мотивированный отказ в течение 5 рабочих дней».</i></span></div><div class="pi-step"><span class="pi-n">3</span><span>Если откажут без обоснования — потребуйте письменный мотивированный ответ. Чаще всего его не дают, и переговоры возобновляются на ваших условиях.</span></div><div class="pi-meta">⏱ Готово через 24 часа · При вопросах пишите Елене в чат</div>`,
|
||
|
||
2: `<b>Что вы получите</b><br>Протокол разногласий + к каждому пункту — ссылка на норму закона. Это превращает ваши требования из «хотелок» в правовые обязанности.<br><br><b>Как использовать:</b><div class="pi-step"><span class="pi-n">1</span><span>Отправьте протокол с сопроводительным текстом: <i>«Каждая позиция основана на нормах действующего законодательства, указанных в документе».</i></span></div><div class="pi-step"><span class="pi-n">2</span><span>Если возражают — один вопрос: <i>«Укажите норму права, на основании которой вы отклоняете это требование».</i> Практически никто не отвечает — это уже победа.</span></div><div class="pi-step"><span class="pi-n">3</span><span>Если сложный ответ всё же пришёл — пришлите Елене, она подготовит вашу следующую реплику.</span></div><div class="pi-meta">⏱ Готово через 24 часа · Поддержка по ответам контрагента включена</div>`,
|
||
|
||
3: `<b>Что вы получите</b><br>Протокол, сформулированный так, чтобы контрагент сам захотел согласиться — без ощущения давления с вашей стороны.<br><br><span class="pi-tag pi-incl">✓ Включено</span><b>Что входит:</b><div class="pi-step"><span class="pi-n">1</span><span>Протокол с формулировками win-win по всем спорным пунктам.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Готовое сопроводительное письмо от вашего имени.</span></div><div class="pi-step"><span class="pi-n">3</span><span>Елена отвечает на любые встречные возражения контрагента — вы пересылаете их нам, мы готовим вашу реплику.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Помогаем зафиксировать итоговую редакцию — до финальной подписи.</span></div><div class="pi-meta">⏱ Первый ответ: 4 часа · Финал: 48–72 часа · Елена рядом на каждом шаге 💛</div>`
|
||
},
|
||
|
||
redact: {
|
||
1: `<b>Что вы получите</b><br>Новая редакция всех спорных пунктов договора — чистый текст, готовый заменить проблемные формулировки. Без пояснений.<br><br><b>Как использовать:</b><div class="pi-step"><span class="pi-n">1</span><span>Откройте оригинал договора. Замените помеченные пункты на наши формулировки.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Направьте обновлённый договор контрагенту: <i>«Прошу рассмотреть актуализированную редакцию договора и подтвердить согласие».</i></span></div><div class="pi-step"><span class="pi-n">3</span><span>Если контрагент запросит объяснения — закажите версию «С комментариями» или обратитесь к Елене отдельно.</span></div><div class="pi-meta">⏱ Готово через 24 часа · Подходит если контрагент уже готов к диалогу</div>`,
|
||
|
||
2: `<b>Что вы получите</b><br>Переработанный договор + к каждому изменённому пункту — короткое пояснение: что изменено, почему это справедливо, на какой закон опирается.<br><br><b>Как использовать:</b><div class="pi-step"><span class="pi-n">1</span><span>Отправьте документ контрагенту со словами: <i>«К каждому изменению приложено обоснование — это поможет нам быстрее прийти к согласию».</i></span></div><div class="pi-step"><span class="pi-n">2</span><span>Если контрагент не согласен с конкретным пунктом — пришлите его возражение Елене. Она подготовит контраргумент.</span></div><div class="pi-step"><span class="pi-n">3</span><span>Комментарии снимают большинство вопросов до того, как они превращаются в споры — переписка сокращается в разы.</span></div><div class="pi-meta">⏱ Готово через 24 часа · По опыту: 70% договоров с комментариями подписывают с первого раунда</div>`,
|
||
|
||
3: `<b>Что вы получите</b><br>Договор, переработанный с учётом интересов обеих сторон — контрагент видит не давление, а честное предложение. Плюс Елена рядом до финала.<br><br><span class="pi-tag pi-incl">✓ Включено</span><b>Что входит:</b><div class="pi-step"><span class="pi-n">1</span><span>Полная переработка всех спорных пунктов — с балансом интересов.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Готовое сопроводительное письмо с нужной тональностью.</span></div><div class="pi-step"><span class="pi-n">3</span><span>Елена держит вашу позицию при встречных возражениях — вы не теряете важное в процессе переговоров.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Финальная сверка перед подписанием: убеждаемся, что итоговая редакция вас защищает.</span></div><div class="pi-meta">⏱ Первый ответ: 4 часа · Поддержка до подписи включена 💛</div>`
|
||
},
|
||
|
||
clean: {
|
||
1: `<b>Что вы получите</b><br>Договор с переписанными спорными пунктами — готов к подписанию. Никаких пояснений, только чистый текст.<br><br><b>Как использовать:</b><div class="pi-step"><span class="pi-n">1</span><span>Получаете файл → сравниваете с оригиналом по выделенным пунктам → убеждаетесь, что всё устраивает.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Направляете контрагенту: <i>«Предлагаю подписать актуальную редакцию договора».</i></span></div><div class="pi-step"><span class="pi-n">3</span><span>Если контрагент спросит «почему изменено?» — вы можете дозаказать пояснения к уже готовому тексту. Или воспользоваться версией с обоснованием сразу.</span></div><div class="pi-meta">⏱ Готово через 24 часа · Подходит если контрагент уже согласен на изменения</div>`,
|
||
|
||
2: `<b>Что вы получите</b><br>Готовый к подписанию договор + пояснения к каждому изменению — для вас и для контрагента. Вы понимаете каждый пункт, контрагент понимает логику.<br><br><b>Как использовать:</b><div class="pi-step"><span class="pi-n">1</span><span>Изучите пояснения сами — убедитесь, что всё отражает ваши интересы.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Отправьте контрагенту договор вместе с пояснительной частью: <i>«К каждому изменению есть обоснование — посмотрите, это справедливо для обеих сторон».</i></span></div><div class="pi-step"><span class="pi-n">3</span><span>Вопросов по тексту практически не остаётся — путь к подписи короткий.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Если всё же есть спорный момент — напишите Елене, она поможет с ответом.</span></div><div class="pi-meta">⏱ Готово через 24 часа · Пояснения снимают 80% возражений на старте</div>`,
|
||
|
||
3: `<b>Что вы получите</b><br>Договор с балансом интересов, где контрагент видит свою выгоду — и соглашается без торга. Плюс Елена ведёт вас до подписи.<br><br><span class="pi-tag pi-incl">✓ Включено</span><b>Что входит:</b><div class="pi-step"><span class="pi-n">1</span><span>Договор переписан так, чтобы обе стороны видели: условия честные.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Сопроводительное письмо с нужной тональностью для переговоров.</span></div><div class="pi-step"><span class="pi-n">3</span><span>Если контрагент возражает — Елена готовит ответ за вас. Вы только согласуете финальный текст.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Перед подписанием — финальная проверка: убеждаемся, что ничего важного не потеряно в процессе переговоров.</span></div><div class="pi-meta">⏱ Первый ответ: 4 часа · Договоры с балансом подписывают и выполняют честно 💛</div>`
|
||
},
|
||
|
||
|
||
consult: {
|
||
1: `<b>Что вы получите</b><br>Письменный разбор: задаёте до 5 вопросов по договору — AI отвечает на каждый развёрнуто в течение 2 часов.<br><br><b>Как работает:</b><div class="pi-step"><span class="pi-n">1</span><span>После оплаты Елена откроет чат и пришлёт инструкцию.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Отправляете текст договора + список вопросов (или пишете «найди риски сам»).</span></div><div class="pi-step"><span class="pi-n">3</span><span>AI разбирает каждый вопрос письменно — конкретно, со ссылкой на закон и рекомендацией.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Переписку можно сохранить и использовать в переговорах.</span></div><div class="pi-meta">⏱ Ответ в течение 2 часов · Подходит если есть конкретные вопросы</div>`,
|
||
|
||
2: `<b>Что вы получите</b><br>Полный AI-разбор всего договора: все риски, проблемные пункты, ответы на любые вопросы без ограничений.<br><br><b>Как работает:</b><div class="pi-step"><span class="pi-n">1</span><span>После оплаты Елена откроет чат.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Отправляете договор — AI сам проходит весь текст и находит все риски.</span></div><div class="pi-step"><span class="pi-n">3</span><span>Задаёте любые вопросы — AI отвечает конкретно по вашей ситуации. Без ограничений по количеству.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Понимаете что подписываете — и что делать дальше.</span></div><div class="pi-meta">⏱ Первый ответ в течение 2 часов · Вопросы без ограничений</div>`,
|
||
|
||
3: `<b>Что вы получите</b><br>Полный AI-анализ + письменное заключение: перечень всех рисков, конкретные рекомендации, ссылки на нормы закона.<br><br><span class="pi-tag pi-incl">✓ Включено</span><b>Что входит:</b><div class="pi-step"><span class="pi-n">1</span><span>AI проходит весь договор и находит все риски — критичные, средние, незначительные.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Отвечает на ваши вопросы без ограничений — по каждому пункту, по вашей ситуации.</span></div><div class="pi-step"><span class="pi-n">3</span><span>Письменное заключение: риски, рекомендации, нормы закона — документ у вас на руках.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Заключение можно показать другой стороне как независимую экспертизу.</span></div><div class="pi-meta">⏱ Разбор в течение 2 часов · Заключение: в течение 24 часов 💛</div>`
|
||
},
|
||
|
||
reply: {
|
||
1: `<b>Что вы получите</b><br>Готовый текст ответа на конкретный отказ или возражение контрагента — с вашей правовой позицией, в нужном тоне.<br><br><b>Как использовать:</b><div class="pi-step"><span class="pi-n">1</span><span>Пришлите нам текст возражения контрагента и ваш договор.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Юрист составляет ответ: спокойный тон + чёткая позиция + ссылка на норму права.</span></div><div class="pi-step"><span class="pi-n">3</span><span>Отправляете контрагенту без изменений или адаптируете под свой стиль.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Такой ответ показывает: вы знаете о чём говорите. Большинство контрагентов после этого соглашаются.</span></div><div class="pi-meta">⏱ Готово через 12 часов · Работает на любом этапе переговоров</div>`,
|
||
|
||
2: `<b>Что вы получите</b><br>Развёрнутый ответ + аргументы на 2–3 шага вперёд: мы предусматриваем их следующие возражения и закрываем их заранее.<br><br><b>Как использовать:</b><div class="pi-step"><span class="pi-n">1</span><span>Пришлите текст возражения контрагента и все предыдущие сообщения по переговорам.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Юрист анализирует всю цепочку и составляет ответ с закрытием типичных контраргументов.</span></div><div class="pi-step"><span class="pi-n">3</span><span>В документе — основной ответ + «шпаргалка» на случай если всё же возразят снова.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Вы входите в следующий раунд уже подготовленными.</span></div><div class="pi-meta">⏱ Готово через 12 часов · Включает шпаргалку для продолжения диалога</div>`,
|
||
|
||
3: `<b>Что вы получите</b><br>Елена ведёт переписку с контрагентом от вашего имени — до тех пор пока сторона не соглашается или не фиксирует официальный отказ.<br><br><span class="pi-tag pi-incl">✓ Включено</span><b>Как работает:</b><div class="pi-step"><span class="pi-n">1</span><span>Передаёте нам историю переписки и доступ к каналу общения (или пересылаете сообщения).</span></div><div class="pi-step"><span class="pi-n">2</span><span>Елена готовит каждый ответ — вы видите текст до отправки и можете скорректировать.</span></div><div class="pi-step"><span class="pi-n">3</span><span>При нестандартных ходах контрагента — юрист адаптирует стратегию в режиме реального времени.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Финал: либо подписанное соглашение, либо официальный отказ — с основанием для суда если потребуется.</span></div><div class="pi-meta">⏱ Первый ответ: 4 часа · Ведём до результата 💛</div>`
|
||
},
|
||
|
||
partner: {
|
||
1: `<b>Что вы получите</b><br>Договор, переработанный с учётом интересов обеих сторон. Контрагент не чувствует давления — он видит предложение, от которого сложно отказаться.<br><br><b>Как использовать:</b><div class="pi-step"><span class="pi-n">1</span><span>Изучите договор — обратите внимание на пункты с пометкой «↔ обе стороны»: в них мы специально вписали выгоду для контрагента.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Отправьте с простым сопроводительным текстом: <i>«Подготовил(а) редакцию, которая учитывает интересы обеих сторон — посмотри».</i></span></div><div class="pi-step"><span class="pi-n">3</span><span>При возражениях — обратитесь к Елене отдельно или закажите версию с сопровождением.</span></div><div class="pi-meta">⏱ Готово через 24–48 часов · Партнёрские договоры подписывают без торга</div>`,
|
||
|
||
2: `<b>Что вы получите</b><br>Партнёрская редакция + к каждому пункту — аргумент, почему это выгодно для контрагента. У вас есть ответ на любое возражение ещё до того, как оно прозвучало.<br><br><b>Как использовать:</b><div class="pi-step"><span class="pi-n">1</span><span>Изучите аргументы — они написаны под вашу конкретную ситуацию, не шаблонные.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Отправьте договор контрагенту. Если он не согласен с каким-то пунктом — у вас уже готов ответ.</span></div><div class="pi-step"><span class="pi-n">3</span><span>Нестандартная реакция — пришлите Елене, она поможет с ответной позицией.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Вы входите в переговоры с полной картиной — спокойно и уверенно.</span></div><div class="pi-meta">⏱ Готово через 24–48 часов · Поддержка по возражениям включена</div>`,
|
||
|
||
3: `<b>Что вы получите</b><br>Елена ведёт переговоры вместе с вами — от отправки договора до финальной подписи. Ваша задача: согласовать итоговый текст.<br><br><span class="pi-tag pi-incl">✓ Включено</span><b>Полное сопровождение:</b><div class="pi-step"><span class="pi-n">1</span><span>Партнёрская редакция договора + сопроводительное письмо от вашего имени.</span></div><div class="pi-step"><span class="pi-n">2</span><span>Елена анализирует ответ контрагента и готовит вашу следующую реплику.</span></div><div class="pi-step"><span class="pi-n">3</span><span>При встречных правках — определяем, что можно уступить без потерь, а что держим твёрдо.</span></div><div class="pi-step"><span class="pi-n">4</span><span>Финальная проверка перед подписанием: убеждаемся, что ваша защита сохранена в итоговом тексте.</span></div><div class="pi-meta">⏱ Первый ответ: 4 часа · Ведём до подписи · Среднее время закрытия сделки: 3–5 дней 💛</div>`
|
||
}
|
||
};
|
||
|
||
function selectPlan(n) {
|
||
_selPlan = n;
|
||
// подсветка
|
||
[1,2,3].forEach(i => {
|
||
const el = document.getElementById('pay-plan-' + i);
|
||
if (el) el.classList.toggle('sel', i === n);
|
||
});
|
||
// цена в кнопке
|
||
const priceEl = document.getElementById('p' + n + '-price');
|
||
if (priceEl) {
|
||
const priceText = priceEl.textContent;
|
||
const btn = document.getElementById('pay-price-btn');
|
||
if (btn) btn.textContent = 'Оплатить ' + priceText.replace('от ', '');
|
||
}
|
||
// инструкции Елены
|
||
const pitchEl = document.getElementById('pay-pitch');
|
||
if (pitchEl && PLAN_PITCH[_selDeliv] && PLAN_PITCH[_selDeliv][n]) {
|
||
pitchEl.innerHTML = PLAN_PITCH[_selDeliv][n];
|
||
}
|
||
}
|
||
|
||
|
||
/* ── ЮKASSA ВИДЖЕТ ── */
|
||
function ykOpen() {
|
||
const priceEl = document.getElementById('pay-price-btn');
|
||
const price = priceEl ? priceEl.textContent.replace('Оплатить ', '') : '';
|
||
const set = (id, v) => { const el = document.getElementById(id); if (el) el.textContent = v; };
|
||
set('yk-amount', price);
|
||
set('yk-btn-amount', price);
|
||
document.getElementById('yk-overlay').classList.add('open');
|
||
document.getElementById('yk-form').style.display = '';
|
||
document.getElementById('yk-success').style.display = 'none';
|
||
document.getElementById('yk-card').value = '';
|
||
document.getElementById('yk-exp').value = '';
|
||
document.getElementById('yk-cvv').value = '';
|
||
}
|
||
|
||
function ykClose(e) {
|
||
if (e && e.target !== document.getElementById('yk-overlay')) return;
|
||
document.getElementById('yk-overlay').classList.remove('open');
|
||
}
|
||
|
||
function ykFmtCard(el) {
|
||
let v = el.value.replace(/\D/g,'').slice(0,16);
|
||
el.value = v.match(/.{1,4}/g)?.join(' ') || v;
|
||
}
|
||
function ykFmtExp(el) {
|
||
let v = el.value.replace(/\D/g,'').slice(0,4);
|
||
if (v.length >= 3) v = v.slice(0,2) + ' / ' + v.slice(2);
|
||
el.value = v;
|
||
}
|
||
|
||
function ykPaySBP() {
|
||
// В проде: редирект на deeplink СБП с payment_id
|
||
ykFinish();
|
||
}
|
||
|
||
function ykSubmit() {
|
||
const card = document.getElementById('yk-card').value.replace(/\s/g,'');
|
||
const exp = document.getElementById('yk-exp').value;
|
||
const cvv = document.getElementById('yk-cvv').value;
|
||
let ok = true;
|
||
if (card.length < 16) { document.getElementById('yk-card').classList.add('yk-error'); ok = false; }
|
||
else document.getElementById('yk-card').classList.remove('yk-error');
|
||
if (exp.length < 7) { document.getElementById('yk-exp').classList.add('yk-error'); ok = false; }
|
||
else document.getElementById('yk-exp').classList.remove('yk-error');
|
||
if (cvv.length < 3) { document.getElementById('yk-cvv').classList.add('yk-error'); ok = false; }
|
||
else document.getElementById('yk-cvv').classList.remove('yk-error');
|
||
if (!ok) return;
|
||
|
||
const btn = document.getElementById('yk-pay-btn');
|
||
btn.disabled = true;
|
||
btn.innerHTML = '<div class="yk-spinner" style="display:inline-block"></div>';
|
||
|
||
// В проде: POST на /api/payment → получить payment_id → confirm
|
||
setTimeout(ykFinish, 1600);
|
||
}
|
||
|
||
function ykFinish() {
|
||
document.getElementById('yk-form').style.display = 'none';
|
||
document.getElementById('yk-success').style.display = 'block';
|
||
setTimeout(() => {
|
||
document.getElementById('yk-overlay').classList.remove('open');
|
||
// Сохраняем последний заказ для приветствия
|
||
try {
|
||
const d = DELIVS[_selDeliv] || {};
|
||
const p = d['p'+_selPlan] || [];
|
||
localStorage.setItem('zashita_last_order', JSON.stringify({ ttl: d.ttl||'', plan: p[1]||'', price: p[0]||'' }));
|
||
} catch(e) {}
|
||
showOrderStatus();
|
||
go('order-status');
|
||
}, 1200);
|
||
}
|
||
|
||
function startTypewriter(el, phrases, speed) {
|
||
if (!el) return;
|
||
var pi = 0, ci = 0, deleting = false, pause = 0;
|
||
speed = speed || 62;
|
||
function tick() {
|
||
var ph = phrases[pi];
|
||
if (pause > 0) { pause--; setTimeout(tick, 80); return; }
|
||
if (!deleting) {
|
||
ci++;
|
||
el.textContent = ph.slice(0, ci);
|
||
if (ci >= ph.length) { deleting = true; pause = 32; }
|
||
} else {
|
||
ci--;
|
||
el.textContent = ph.slice(0, ci);
|
||
if (ci <= 0) { deleting = false; pause = 10; pi = (pi + 1) % phrases.length; }
|
||
}
|
||
setTimeout(tick, deleting ? Math.round(speed / 3) : speed);
|
||
}
|
||
tick();
|
||
}
|
||
|
||
function checkReturning() {
|
||
const stats = JSON.parse(localStorage.getItem('zashita_intake_stats') || '[]');
|
||
const lastOrder = JSON.parse(localStorage.getItem('zashita_last_order') || 'null');
|
||
const isReturning = stats.length > 0 || !!lastOrder;
|
||
|
||
const n = document.getElementById('hero-new');
|
||
const r = document.getElementById('hero-returning');
|
||
|
||
if (!isReturning) {
|
||
// ── НОВЫЙ КЛИЕНТ: typewriter с USP-фразами
|
||
if (n) n.style.display = '';
|
||
if (r) r.style.display = 'none';
|
||
startTypewriter(document.getElementById('hero-tw-new'), [
|
||
'Первые 3 риска — бесплатно',
|
||
'Результат за несколько секунд',
|
||
'Работаю 24/7 — без очередей и звонков',
|
||
'Данные только на вашем устройстве 🔒',
|
||
'Защищаю людей — не только бизнес',
|
||
], 68);
|
||
} else {
|
||
// ── ВЕРНУВШИЙСЯ: personalized typewriter
|
||
if (n) n.style.display = 'none';
|
||
if (r) r.style.display = '';
|
||
// карточка последнего заказа
|
||
if (lastOrder && lastOrder.ttl) {
|
||
const el = document.getElementById('ret-last-order');
|
||
if (el) el.innerHTML =
|
||
'<div class="ret-ord-lbl">Последний заказ</div>' +
|
||
'<div class="ret-ord-name">' + lastOrder.ttl + ' · ' + lastOrder.plan + '</div>' +
|
||
'<div class="ret-ord-price">' + lastOrder.price + '</div>';
|
||
}
|
||
// персональные фразы
|
||
var retPhrases = ['Готова продолжить — чем Вам помочь сегодня?'];
|
||
if (lastOrder && lastOrder.ttl) {
|
||
retPhrases.unshift('ваш договор на проверке: ' + lastOrder.ttl);
|
||
}
|
||
retPhrases.push('новый документ — за несколько секунд');
|
||
retPhrases.push('все ваши дела в кабинете 📂');
|
||
startTypewriter(document.getElementById('hero-tw-ret'), retPhrases, 55);
|
||
}
|
||
}
|
||
window.addEventListener('DOMContentLoaded', checkReturning);
|
||
|
||
|
||
|
||
/* ── MS-PROJECT GANTT ── */
|
||
(function(){
|
||
// Данные
|
||
var DATA = [
|
||
{ num:1, group:true, name:'🍽️ Кухня — агентский', dur:'18 дн', start:'23.05', end:'10.06', s:'2025-05-23', e:'2025-06-10', cls:'b-group', go:"tab('case')" },
|
||
{ num:2, group:false, name:' Анализ рисков', dur:'2 дн', start:'23.05', end:'24.05', s:'2025-05-23', e:'2025-05-24', cls:'b-done', go:"tab('case')" },
|
||
{ num:3, group:false, name:' Протокол разногласий', dur:'3 дн', start:'24.05', end:'27.05', s:'2025-05-24', e:'2025-05-27', cls:'b-urgent', go:"tab('case')" },
|
||
{ num:4, group:false, name:' Ответ контрагенту', dur:'2 дн', start:'27.05', end:'29.05', s:'2025-05-27', e:'2025-05-29', cls:'b-pending', go:"tab('case')" },
|
||
{ num:5, group:true, name:'💼 Трудовой договор', dur:'15 дн', start:'21.05', end:'05.06', s:'2025-05-21', e:'2025-06-05', cls:'b-group', go:"tab('case')" },
|
||
{ num:6, group:false, name:' Первичный анализ', dur:'1 дн', start:'21.05', end:'22.05', s:'2025-05-21', e:'2025-05-22', cls:'b-done', go:"tab('case')" },
|
||
{ num:7, group:false, name:' Допсоглашение', dur:'8 дн', start:'22.05', end:'30.05', s:'2025-05-22', e:'2025-05-30', cls:'b-active', go:"tab('case')" },
|
||
{ num:8, group:false, name:' Проверка финала', dur:'5 дн', start:'30.05', end:'05.06', s:'2025-05-30', e:'2025-06-05', cls:'b-pending', go:"tab('case')" },
|
||
{ num:9, group:true, name:'🏠 ДДУ (новая редакция)', dur:'17 дн', start:'19.05', end:'05.06', s:'2025-05-19', e:'2025-06-05', cls:'b-group', go:"tab('case')" },
|
||
{ num:10, group:false, name:' Сверка версий', dur:'8 дн', start:'19.05', end:'27.05', s:'2025-05-19', e:'2025-05-27', cls:'b-active', go:"tab('case')" },
|
||
{ num:11, group:false, name:' Финальное заключение', dur:'9 дн', start:'27.05', end:'05.06', s:'2025-05-27', e:'2025-06-05', cls:'b-pending', go:"tab('case')" },
|
||
];
|
||
|
||
var RS = new Date('2025-05-17T00:00:00');
|
||
var RE = new Date('2025-06-15T00:00:00');
|
||
var TOT = (RE - RS) / 86400000;
|
||
|
||
function pct(str) {
|
||
var dt = new Date(str + 'T00:00:00');
|
||
return Math.max(0, Math.min(100, (dt - RS) / 86400000 / TOT * 100));
|
||
}
|
||
|
||
// Построить тики дат
|
||
function buildDateTicks() {
|
||
var ticks = []; var cur = new Date(RS);
|
||
while(cur <= RE) { ticks.push(new Date(cur)); cur.setDate(cur.getDate()+7); }
|
||
return ticks;
|
||
}
|
||
|
||
// Построить сетку (колонки = дни)
|
||
function buildGridCols() {
|
||
var cols = ''; var cur = new Date(RS);
|
||
while(cur < RE) {
|
||
var d = cur.getDay();
|
||
cols += '<div class="msp-grid-col' + (d===0||d===6?' weekend':'') + '"></div>';
|
||
cur.setDate(cur.getDate()+1);
|
||
}
|
||
return cols;
|
||
}
|
||
|
||
function render() {
|
||
var root = document.getElementById('msp-root');
|
||
if (!root) return;
|
||
|
||
var today = new Date(); today.setHours(0,0,0,0);
|
||
var todayPct = pct(today.toISOString().slice(0,10));
|
||
|
||
var ticks = buildDateTicks();
|
||
var gridCols = buildGridCols();
|
||
var m = ['янв','фев','мар','апр','май','июн','июл','авг','сен','окт','ноя','дек'];
|
||
|
||
// Шапка дат
|
||
var ticksHTML = ticks.map(function(dt){
|
||
return '<div class="msp-date-tick" style="left:'+pct(dt.toISOString().slice(0,10)).toFixed(2)+'%">'+
|
||
dt.getDate()+' '+m[dt.getMonth()]+'</div>';
|
||
}).join('');
|
||
|
||
// HEAD
|
||
var head = '<div class="msp-head">' +
|
||
'<div class="msp-left">' +
|
||
'<div class="msp-hcol msp-c-num">#</div>' +
|
||
'<div class="msp-hcol msp-c-name">Название задачи</div>' +
|
||
'<div class="msp-hcol msp-c-dur">Длит.</div>' +
|
||
'<div class="msp-hcol msp-c-start">Начало</div>' +
|
||
'<div class="msp-hcol msp-c-end">Окончание</div>' +
|
||
'</div>' +
|
||
'<div class="msp-right">' +
|
||
'<div class="msp-date-hdr">' + ticksHTML + '</div>' +
|
||
'</div>' +
|
||
'</div>';
|
||
|
||
// ROWS
|
||
var rows = DATA.map(function(r){
|
||
var left_pct = pct(r.s);
|
||
var right_pct = pct(r.e);
|
||
var w = Math.max(0.5, right_pct - left_pct);
|
||
var barLabel = r.group ? '' : r.end;
|
||
var isDone = r.cls === 'b-done';
|
||
var isActive = r.cls === 'b-active' || r.cls === 'b-urgent';
|
||
var rowCls = 'msp-row' + (r.group?' msp-group':'') + (isDone?' msp-done':'') + (isActive?' msp-active-row':'');
|
||
|
||
return '<div class="'+rowCls+'" onclick="'+r.go+'">' +
|
||
'<div class="msp-left">' +
|
||
'<div class="msp-cell msp-c-num">'+r.num+'</div>' +
|
||
'<div class="msp-cell msp-c-name'+(r.group?'':' ind')+'">'+(isDone&&!r.group?'✅ ':'')+r.name+'</div>' +
|
||
'<div class="msp-cell msp-c-dur">'+r.dur+'</div>' +
|
||
'<div class="msp-cell msp-c-start">'+r.start+'</div>' +
|
||
'<div class="msp-cell msp-c-end">'+r.end+'</div>' +
|
||
'</div>' +
|
||
'<div class="msp-right">' +
|
||
'<div class="msp-grid-bg">'+gridCols+'</div>' +
|
||
'<div class="msp-bar-wrap">' +
|
||
'<div class="msp-today" style="left:'+todayPct.toFixed(2)+'%"></div>' +
|
||
'<div class="msp-bar '+r.cls+'" style="left:'+left_pct.toFixed(2)+'%;width:'+w.toFixed(2)+'%">'+barLabel+'</div>' +
|
||
'</div>' +
|
||
'</div>' +
|
||
'</div>';
|
||
}).join('');
|
||
|
||
root.innerHTML = head + rows;
|
||
}
|
||
|
||
// Рендерим при открытии кабинета и при tab('cases')
|
||
var _origTab = window.tab;
|
||
window.tab = function(id) {
|
||
if (_origTab) _origTab(id);
|
||
if (id === 'cases') setTimeout(render, 50);
|
||
};
|
||
var _origGo = window.go;
|
||
window.go = function(id) {
|
||
if (_origGo) _origGo(id);
|
||
if (id === 'cabinet') setTimeout(render, 80);
|
||
};
|
||
window.addEventListener('DOMContentLoaded', function(){
|
||
var el = document.getElementById('p-cases');
|
||
if (el && el.classList.contains('on')) render();
|
||
});
|
||
})();
|
||
|
||
/* ── ТАБЛИЦА ДОГОВОРОВ ── */
|
||
(function(){
|
||
var CT_DATA = [
|
||
{ ico:'🍽️', name:'Кухня — агентский (ЗОВ)', type:'Агентский', date:'23.05', dateSort:20250523, risk:'high', riskLbl:'⚠ Высокий', status:'work', open:true, go:"tab('case')" },
|
||
{ ico:'💼', name:'Трудовой договор', type:'Трудовой', date:'21.05', dateSort:20250521, risk:'mid', riskLbl:'Средний', status:'work', open:true, go:"tab('case')" },
|
||
{ ico:'🏠', name:'Квартира — ДДУ (новая ред.)',type:'ДДУ', date:'19.05', dateSort:20250519, risk:'low', riskLbl:'Низкий', status:'wait', open:true, go:"tab('case')" },
|
||
{ ico:'📄', name:'Аренда офиса 2024', type:'Аренда', date:'12.03', dateSort:20250312, risk:'low', riskLbl:'Низкий', status:'done', open:false, go:"toast('📄 Открываю архивное дело')" },
|
||
{ ico:'📄', name:'Поставка оборудования', type:'Поставка',date:'01.02', dateSort:20250201, risk:'mid', riskLbl:'Средний', status:'done', open:false, go:"toast('📄 Открываю архивное дело')" },
|
||
];
|
||
|
||
var STATUS_MAP = {
|
||
'paid': { lbl:'Оплачено', cls:'chip n' },
|
||
'wait': { lbl:'⏳ Ожидает договор', cls:'chip w' },
|
||
'work': { lbl:'🔵 В работе', cls:'chip n' },
|
||
'ready': { lbl:'📥 Готово', cls:'chip ok' },
|
||
'done': { lbl:'✅ Завершён', cls:'chip ok' },
|
||
};
|
||
|
||
var _filter = 'all';
|
||
var _sortField = 'date';
|
||
var _sortDir = -1; // -1 = desc (новые сверху)
|
||
|
||
function riskOrder(r){ return r==='high'?0:r==='mid'?1:2; }
|
||
|
||
function filtered() {
|
||
return CT_DATA.filter(function(r){
|
||
if (_filter === 'open') return r.open;
|
||
if (_filter === 'closed') return !r.open;
|
||
if (_filter === 'risk') return r.risk === 'high';
|
||
return true;
|
||
}).sort(function(a,b){
|
||
var va, vb;
|
||
if (_sortField === 'date') { va=a.dateSort; vb=b.dateSort; }
|
||
else if (_sortField === 'risk') { va=riskOrder(a.risk); vb=riskOrder(b.risk); }
|
||
else if (_sortField === 'name') { va=a.name; vb=b.name; }
|
||
else if (_sortField === 'type') { va=a.type; vb=b.type; }
|
||
else if (_sortField === 'status') { va=a.status; vb=b.status; }
|
||
else { va=a.dateSort; vb=b.dateSort; }
|
||
if (va < vb) return -1 * _sortDir;
|
||
if (va > vb) return 1 * _sortDir;
|
||
return 0;
|
||
});
|
||
}
|
||
|
||
function riskChipCls(r){ return r==='high'?'chip d':r==='mid'?'chip w':'chip n'; }
|
||
|
||
function render() {
|
||
var tbody = document.getElementById('ct-tbody');
|
||
if (!tbody) return;
|
||
var rows = filtered();
|
||
if (!rows.length) { tbody.innerHTML='<tr><td colspan="6" style="padding:20px;text-align:center;color:var(--mut)">Нет дел по фильтру</td></tr>'; return; }
|
||
tbody.innerHTML = rows.map(function(r){
|
||
return '<tr class="'+(r.open?'':'ct-closed')+'" onclick="'+r.go+'">' +
|
||
'<td class="ct-name">'+r.ico+' '+r.name+'</td>' +
|
||
'<td><span class="ct-type-badge">'+r.type+'</span></td>' +
|
||
'<td style="color:var(--mut)">'+r.date+'</td>' +
|
||
'<td><span class="'+riskChipCls(r.risk)+'">'+r.riskLbl+'</span></td>' +
|
||
'<td><span class="'+(STATUS_MAP[r.status]||{cls:'chip n'}).cls+'">'+(STATUS_MAP[r.status]||{lbl:r.status}).lbl+'</span></td>' +
|
||
'<td class="ct-open">→</td>' +
|
||
'</tr>';
|
||
}).join('');
|
||
}
|
||
|
||
window.ctFilter = function(f, btn) {
|
||
_filter = f;
|
||
document.querySelectorAll('.ct-fbtn').forEach(function(b){ b.classList.remove('act'); });
|
||
if (btn) btn.classList.add('act');
|
||
render();
|
||
};
|
||
|
||
window.ctSort = function(field, th) {
|
||
if (_sortField === field) { _sortDir *= -1; }
|
||
else { _sortField = field; _sortDir = 1; }
|
||
document.querySelectorAll('.ct-table thead th').forEach(function(h){ h.classList.remove('sort-asc','sort-desc'); });
|
||
if (th) th.classList.add(_sortDir === 1 ? 'sort-asc' : 'sort-desc');
|
||
render();
|
||
};
|
||
|
||
// Рендер при открытии вкладки cases и cabinet
|
||
var _origTab2 = window.tab;
|
||
window.tab = function(id) {
|
||
if (_origTab2) _origTab2(id);
|
||
if (id === 'cases') setTimeout(render, 50);
|
||
};
|
||
var _origGo2 = window.go;
|
||
window.go = function(id) {
|
||
if (_origGo2) _origGo2(id);
|
||
if (id === 'cabinet') setTimeout(render, 80);
|
||
};
|
||
window.addEventListener('DOMContentLoaded', function(){
|
||
var el = document.getElementById('ct-tbody');
|
||
if (el) render();
|
||
});
|
||
})();
|
||
|
||
/* ── ELENA INTAKE v2 ── */
|
||
function elenaIntentFromInput() {
|
||
var txt = (document.getElementById('intake-custom').value || '').trim();
|
||
if (!txt) { document.getElementById('intake-custom').focus(); return; }
|
||
var t = txt.toLowerCase();
|
||
var intent = 'question';
|
||
if (/доверенност/.test(t)) { intent = 'power'; }
|
||
else if (/протокол|разногласи|убрат|невыгод/.test(t)) { intent = 'dispute'; }
|
||
else if (/претензи|жалоб/.test(t)) { intent = 'check'; }
|
||
else if (/состав|написат|создат|подготов/.test(t) && !/проверит|анализ/.test(t)) { intent = 'create'; }
|
||
else if (/проверит|анализ|посмотр|риск/.test(t)) { intent = 'check'; }
|
||
else if (/договор|контракт|соглашени/.test(t)) { intent = 'check'; }
|
||
else if (/кабинет|войт|мои дел/.test(t)) { intent = 'cabinet'; }
|
||
elenaIntent(intent);
|
||
}
|
||
|
||
function elenaIntent(intent) {
|
||
// cabinet — сразу в кабинет
|
||
if (intent === 'cabinet') { go('cabinet'); return; }
|
||
|
||
// question — показываем текстовое поле без загрузки
|
||
if (intent === 'question') {
|
||
document.querySelectorAll('#el-step1 .int-card').forEach(function(c){ c.style.opacity='.45'; c.style.pointerEvents='none'; });
|
||
var qBox = document.createElement('div');
|
||
qBox.className = 'msg';
|
||
qBox.innerHTML = '<div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div>Конечно — спрашивайте 💛 Опишите ситуацию, я отвечу по нормам ГК/ТК/ЗоЗПП. Или включите микрофон 🎙</div>';
|
||
document.getElementById('el-step1').appendChild(qBox);
|
||
return;
|
||
}
|
||
|
||
// create — переходим к wizard созданию документа
|
||
if (intent === 'create') { go('cabinet'); setTimeout(function(){ tab('create'); }, 200); return; }
|
||
|
||
// check / dispute / power — переходим к загрузке
|
||
var ackMap = {
|
||
check: 'Отлично — проверю договор 📄 Найду все риски и объясню каждый понятно.',
|
||
dispute: 'Хорошо — подготовлю протокол разногласий 📋 Загрузите договор, уберём невыгодные пункты.',
|
||
power: 'Доверенность — без проблем 📑 Загрузите образец или расскажите кому и какие полномочия.',
|
||
custom: 'Понял вас. Загрузите документ или опишите подробнее — разберёмся.',
|
||
};
|
||
document.querySelectorAll('#el-step1, #el-step-create').forEach(function(el){ el.style.display='none'; });
|
||
var upload = document.getElementById('el-step-upload');
|
||
if(upload) upload.style.display='';
|
||
var ack = document.getElementById('el-ack');
|
||
if(ack) ack.innerHTML = ackMap[intent] || '';
|
||
}
|
||
|
||
function elenaCreate(type) {
|
||
var msgs = {
|
||
contract: 'Договор — отличный выбор. Уточните: какой тип и между кем? Например: «договор оказания услуг между ИП и физлицом». Чем точнее — тем лучше результат.',
|
||
power: 'Доверенность готовлю быстро. Укажите: кто доверяет, кому, и что именно разрешает делать (продать авто, представлять в суде, получить документы)?',
|
||
claim: 'Претензию составлю под вашу ситуацию. Опишите: к кому претензия, что нарушили и какой результат хотите (возврат денег, замена товара, неустойка)?',
|
||
other: 'Расскажите что нужно составить — постараюсь помочь или подберу ближайший шаблон.',
|
||
};
|
||
var msg = msgs[type] || msgs.other;
|
||
document.getElementById('el-step-create').style.display = 'none';
|
||
// Показываем ответ Елены и поле ввода
|
||
var wrap = document.querySelector('.chatwrap');
|
||
var div = document.createElement('div');
|
||
div.innerHTML = '<div class="msg"><div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div>' + msg + '</div></div>' +
|
||
'<div class="voice-input-row" style="margin-left:0">' +
|
||
'<input id="create-input" placeholder="Опишите детали…" style="flex:1;border:1.5px solid var(--line);border-radius:11px;padding:11px 14px;font-size:14px;font-family:inherit;outline:none">' +
|
||
'<button class="voice-btn" onclick="toggleVoice(\'create-input\')" title="Голосовой ввод">🎤</button>' +
|
||
'<button class="send-btn" onclick="toast(\'✍️ Принято — начинаю составлять документ по вашему запросу\')">→</button>' +
|
||
'</div>';
|
||
wrap.appendChild(div);
|
||
div.scrollIntoView({behavior:'smooth'});
|
||
}
|
||
|
||
/* ── DEADLINES ── */
|
||
// Структура: { id, caseId, caseName, title, type, date (YYYY-MM-DD),
|
||
// quote, done }
|
||
// В проде: заполняется при анализе договора через Claude API
|
||
// Промпт парсинга (см. архитектуру ниже):
|
||
// "Извлеки все сроки из договора: даты оплат, уведомлений, пролонгации,
|
||
// расторжения, штрафных триггеров. Формат: [{title, type, date, quote}]"
|
||
|
||
var _DEADLINES = [
|
||
{ id:1, caseId:'case-kitchen', caseName:'Кухня · Договор аренды',
|
||
title:'Оплата аренды за май',
|
||
type:'Оплата', date:'2026-05-25',
|
||
quote:'«Арендная плата вносится не позднее 25-го числа текущего месяца»',
|
||
done:false },
|
||
{ id:2, caseId:'case-kitchen', caseName:'Кухня · Договор аренды',
|
||
title:'Уведомить арендодателя о непродлении',
|
||
type:'Уведомление', date:'2026-06-04',
|
||
quote:'«Сторона обязана уведомить о намерении не продлевать договор не менее чем за 30 дней»',
|
||
done:false },
|
||
{ id:3, caseId:'case-kitchen', caseName:'Кухня · Договор аренды',
|
||
title:'Плановое продление договора',
|
||
type:'Пролонгация', date:'2026-07-01',
|
||
quote:'«Договор пролонгируется автоматически на 12 месяцев при отсутствии уведомления»',
|
||
done:false },
|
||
{ id:4, caseId:'case-kitchen', caseName:'Кухня · Договор аренды',
|
||
title:'Оплата обеспечительного депозита (возврат)',
|
||
type:'Оплата', date:'2026-07-15',
|
||
quote:'«Обеспечительный платёж возвращается в течение 45 дней после окончания аренды»',
|
||
done:false },
|
||
];
|
||
|
||
var _dlFilter = 'all';
|
||
var _dlDone = new Set();
|
||
|
||
function _dlStatus(dateStr) {
|
||
var today = new Date(); today.setHours(0,0,0,0);
|
||
var d = new Date(dateStr); d.setHours(0,0,0,0);
|
||
var diff = Math.round((d - today) / 86400000);
|
||
if (diff < 0) return { cls:'overdue', badge:'Просрочено ' + Math.abs(diff) + ' дн.', days: diff };
|
||
if (diff <= 7) return { cls:'soon', badge:'Через ' + diff + ' дн.', days: diff };
|
||
return { cls:'ok', badge:'Через ' + diff + ' дн.', days: diff };
|
||
}
|
||
|
||
function _fmtDate(dateStr) {
|
||
var m = ['янв','фев','мар','апр','мая','июн','июл','авг','сен','окт','ноя','дек'];
|
||
var p = dateStr.split('-');
|
||
return p[2].replace(/^0/,'') + ' ' + m[parseInt(p[1])-1] + ' ' + p[0];
|
||
}
|
||
|
||
function renderDeadlines() {
|
||
var list = document.getElementById('dl-list');
|
||
var sumEl = document.getElementById('dl-summary');
|
||
if (!list) return;
|
||
|
||
var items = _DEADLINES.map(function(d) {
|
||
var isDone = _dlDone.has(d.id) || d.done;
|
||
var st = isDone ? {cls:'done', badge:'Выполнено', days:999} : _dlStatus(d.date);
|
||
return Object.assign({}, d, {isDone: isDone, st: st});
|
||
});
|
||
|
||
// Сводка
|
||
var nOver = items.filter(function(i){ return i.st.cls==='overdue'; }).length;
|
||
var nSoon = items.filter(function(i){ return i.st.cls==='soon'; }).length;
|
||
var nOk = items.filter(function(i){ return i.st.cls==='ok'; }).length;
|
||
if (sumEl) sumEl.innerHTML =
|
||
'<div class="dl-sum-card red"><div class="dl-sum-num">'+nOver+'</div><div class="dl-sum-lbl">Просрочено</div></div>' +
|
||
'<div class="dl-sum-card yellow"><div class="dl-sum-num">'+nSoon+'</div><div class="dl-sum-lbl">Скоро</div></div>' +
|
||
'<div class="dl-sum-card green"><div class="dl-sum-num">'+nOk+'</div><div class="dl-sum-lbl">В срок</div></div>';
|
||
|
||
// Фильтрация
|
||
var filtered = items.filter(function(i) {
|
||
if (_dlFilter === 'done') return i.isDone;
|
||
if (_dlFilter === 'urgent') return !i.isDone && (i.st.cls==='overdue'||i.st.cls==='soon');
|
||
return true;
|
||
});
|
||
|
||
// Сортировка: overdue → soon → ok → done
|
||
filtered.sort(function(a,b){ return a.st.days - b.st.days; });
|
||
|
||
if (!filtered.length) {
|
||
list.innerHTML = '<div class="dl-empty"><div class="dl-empty-ico">✅</div><div class="dl-empty-txt">Активных сроков нет</div><div class="dl-empty-sub">Елена найдёт сроки автоматически при загрузке договора</div></div>';
|
||
return;
|
||
}
|
||
|
||
list.innerHTML = filtered.map(function(d) {
|
||
var btnHtml = d.isDone
|
||
? '<button class="dl-btn done-btn" disabled>✅ Выполнено</button>'
|
||
: '<button class="dl-btn" onclick="markDeadlineDone('+d.id+')">Отметить выполненным</button>';
|
||
return '<div class="dl-card '+d.st.cls+'">' +
|
||
'<div class="dl-dot"></div>' +
|
||
'<div class="dl-body">' +
|
||
'<div class="dl-title">'+d.title+'</div>' +
|
||
'<div class="dl-meta">'+d.caseName+' · '+d.type+'</div>' +
|
||
'<div class="dl-quote">'+d.quote+'</div>' +
|
||
btnHtml +
|
||
'</div>' +
|
||
'<div class="dl-right">' +
|
||
'<div class="dl-date">'+_fmtDate(d.date)+'</div>' +
|
||
'<div class="dl-badge '+d.st.cls+'">'+d.st.badge+'</div>' +
|
||
'</div>' +
|
||
'</div>';
|
||
}).join('');
|
||
}
|
||
|
||
function dlFilter(name, el) {
|
||
_dlFilter = name;
|
||
document.querySelectorAll('.dl-ftab').forEach(function(t){ t.classList.remove('on'); });
|
||
if (el) el.classList.add('on');
|
||
renderDeadlines();
|
||
}
|
||
|
||
function markDeadlineDone(id) {
|
||
_dlDone.add(id);
|
||
renderDeadlines();
|
||
toast('✅ Срок отмечен выполненным');
|
||
}
|
||
|
||
// Добавить дедлайн из анализа договора (вызывается при парсинге)
|
||
function addDeadlinesFromContract(caseId, caseName, deadlines) {
|
||
deadlines.forEach(function(d) {
|
||
var maxId = Math.max.apply(null, _DEADLINES.map(function(x){return x.id;})) || 0;
|
||
_DEADLINES.push({ id: maxId+1, caseId: caseId, caseName: caseName,
|
||
title: d.title, type: d.type, date: d.date, quote: d.quote||'', done: false });
|
||
});
|
||
if (document.getElementById('dl-list')) renderDeadlines();
|
||
}
|
||
|
||
window.addEventListener('DOMContentLoaded', function() {
|
||
if (document.getElementById('dl-list')) renderDeadlines();
|
||
});
|
||
|
||
/* ── PAY HYBRID ── */
|
||
var _payMode = 'once'; // once | sub
|
||
var _selPkg = 2; // selected package id
|
||
var _selSub = 2; // selected sub id
|
||
var _selPkgPrice = 490;
|
||
var _selSubPrice = 1990;
|
||
var _ykMethod = 'sbp';
|
||
|
||
var _PKG_PRICES = {1:249, 2:490, 3:1290, 4:2990};
|
||
var _PKG_CREDITS = {1:1, 2:3, 3:10, 4:30};
|
||
var _SUB_PRICES = {1:990, 2:1990, 3:4900};
|
||
|
||
function payTab(mode) {
|
||
_payMode = mode;
|
||
document.getElementById('ptab-once').classList.toggle('on', mode==='once');
|
||
document.getElementById('ptab-sub').classList.toggle('on', mode==='sub');
|
||
document.getElementById('ppane-once').classList.toggle('on', mode==='once');
|
||
document.getElementById('ppane-sub').classList.toggle('on', mode==='sub');
|
||
_updatePayBtn();
|
||
}
|
||
|
||
function selectPkg(id, price) {
|
||
_selPkg = id; _selPkgPrice = price;
|
||
document.querySelectorAll('.pkg-card').forEach(function(c){ c.classList.remove('sel'); });
|
||
var el = document.getElementById('pkg-'+id);
|
||
if (el) el.classList.add('sel');
|
||
_updatePayBtn();
|
||
}
|
||
|
||
function selectSub(id, price) {
|
||
_selSub = id; _selSubPrice = price;
|
||
document.querySelectorAll('.sub-card').forEach(function(c){ c.classList.remove('sel'); });
|
||
var el = document.getElementById('sub-'+id);
|
||
if (el) el.classList.add('sel');
|
||
_updatePayBtn();
|
||
}
|
||
|
||
function _updatePayBtn() {
|
||
var price = _payMode === 'once' ? _selPkgPrice : _selSubPrice;
|
||
var suffix = _payMode === 'sub' ? '/мес' : '';
|
||
var btn = document.getElementById('pay-price-btn');
|
||
if (btn) btn.textContent = 'Оплатить ' + price.toLocaleString('ru') + ' ₽' + suffix;
|
||
var ykBtn = document.getElementById('yk-pay-btn');
|
||
var ykAmt = document.getElementById('yk-amount');
|
||
if (ykBtn) ykBtn.textContent = 'Оплатить ' + price.toLocaleString('ru') + ' ₽' + suffix;
|
||
if (ykAmt) ykAmt.textContent = price.toLocaleString('ru') + ' ₽';
|
||
var ykTtl = document.getElementById('yk-ttl');
|
||
if (ykTtl) ykTtl.textContent = _payMode === 'sub' ? 'Подписка · первый платёж' : 'Пополнение баланса';
|
||
}
|
||
|
||
function _refreshBalance() {
|
||
var bal = parseInt(localStorage.getItem('zashita_credits') || '0');
|
||
var el = document.getElementById('pay-bal-credits');
|
||
var sub = document.getElementById('pay-bal-sub');
|
||
var btn = document.getElementById('pay-bal-use-btn');
|
||
if (el) el.textContent = bal;
|
||
if (bal > 0) {
|
||
if (sub) sub.textContent = 'Спишем 1 кредит на эту проверку';
|
||
if (btn) btn.style.display = '';
|
||
} else {
|
||
if (sub) sub.textContent = 'Пополните баланс ниже или оплатите разово';
|
||
if (btn) btn.style.display = 'none';
|
||
}
|
||
}
|
||
|
||
function useBalance() {
|
||
var bal = parseInt(localStorage.getItem('zashita_credits') || '0');
|
||
if (bal <= 0) return;
|
||
localStorage.setItem('zashita_credits', bal - 1);
|
||
// record usage
|
||
var hist = JSON.parse(localStorage.getItem('zashita_pay_history') || '[]');
|
||
hist.unshift({date: new Date().toISOString(), type: 'use', amount: 0, desc: 'Использован 1 кредит'});
|
||
localStorage.setItem('zashita_pay_history', JSON.stringify(hist));
|
||
toast('✅ 1 кредит использован — запускаю полный анализ');
|
||
setTimeout(function(){ go('cabinet'); tab('cases'); }, 1200);
|
||
}
|
||
|
||
// ЮKassa modal
|
||
function ykOpen() {
|
||
_updatePayBtn();
|
||
document.getElementById('yk-overlay').classList.add('on');
|
||
}
|
||
function ykClose(e) {
|
||
if (!e || e.target === document.getElementById('yk-overlay')) {
|
||
document.getElementById('yk-overlay').classList.remove('on');
|
||
}
|
||
}
|
||
function ykMethod(m, el) {
|
||
_ykMethod = m;
|
||
document.querySelectorAll('.yk-method').forEach(function(x){ x.classList.remove('sel'); });
|
||
if (el) el.classList.add('sel');
|
||
document.getElementById('yk-card-form').style.display = (m === 'card') ? '' : 'none';
|
||
}
|
||
function fmtCard(inp) {
|
||
var v = inp.value.replace(/\D/g,'').substring(0,16);
|
||
inp.value = v.replace(/(\d{4})(?=\d)/g,'$1 ');
|
||
}
|
||
function ykPay() {
|
||
var price = _payMode === 'once' ? _selPkgPrice : _selSubPrice;
|
||
var credits = _payMode === 'once' ? _PKG_CREDITS[_selPkg] : 999;
|
||
// Mock: зачислить кредиты
|
||
if (_payMode === 'once') {
|
||
var cur = parseInt(localStorage.getItem('zashita_credits') || '0');
|
||
localStorage.setItem('zashita_credits', cur + credits);
|
||
} else {
|
||
localStorage.setItem('zashita_sub_plan', _selSub);
|
||
localStorage.setItem('zashita_sub_since', new Date().toISOString());
|
||
}
|
||
// Save to payment history
|
||
var hist = JSON.parse(localStorage.getItem('zashita_pay_history') || '[]');
|
||
hist.unshift({
|
||
date: new Date().toISOString(),
|
||
type: _payMode,
|
||
amount: price,
|
||
credits: _payMode === 'once' ? credits : null,
|
||
method: _ykMethod,
|
||
status: 'paid',
|
||
desc: _payMode === 'once' ? 'Пополнение баланса +' + credits + ' кредитов' : 'Подписка · ' + ['','Старт','Бизнес','Безлимит'][_selSub]
|
||
});
|
||
localStorage.setItem('zashita_pay_history', JSON.stringify(hist));
|
||
// Save last order for hero screen
|
||
localStorage.setItem('zashita_last_order', JSON.stringify({
|
||
ttl: 'Баланс пополнен', plan: _payMode === 'once' ? credits + ' кредитов' : 'Подписка',
|
||
price: price.toLocaleString('ru') + ' ₽'
|
||
}));
|
||
ykClose();
|
||
toast('✅ Оплата прошла — кредиты зачислены!');
|
||
_refreshBalance();
|
||
setTimeout(function(){ go('cabinet'); }, 1500);
|
||
}
|
||
|
||
window.addEventListener('DOMContentLoaded', function(){
|
||
// default: select pkg-2
|
||
selectPkg(2, 490);
|
||
_refreshBalance();
|
||
});
|
||
|
||
/* ── ADMIN + BALANCE ── */
|
||
|
||
// ── Admin dashboard ──
|
||
var _ADM_PAYS = [
|
||
{date:'28.05.2026',client:'Р.В.',type:'Пакет Бизнес',amount:1290,status:'paid'},
|
||
{date:'28.05.2026',client:'М.С.',type:'Подписка Бизнес',amount:1990,status:'paid'},
|
||
{date:'27.05.2026',client:'А.П.',type:'Разовая',amount:249,status:'paid'},
|
||
{date:'27.05.2026',client:'О.К.',type:'Пакет Старт',amount:490,status:'paid'},
|
||
{date:'26.05.2026',client:'В.Н.',type:'Подписка Старт',amount:990,status:'paid'},
|
||
{date:'25.05.2026',client:'Т.Ю.',type:'Пакет Бизнес',amount:1290,status:'ref'},
|
||
];
|
||
|
||
var _ADM_REFUNDS = [
|
||
{id:1,client:'Т.Ю.',date:'25.05.2026',amount:1290,credits:7,
|
||
reason:'Не понравился формат отчёта',urgent:true},
|
||
{id:2,client:'С.В.',date:'22.05.2026',amount:490,credits:2,
|
||
reason:'Дублирующая покупка',urgent:false},
|
||
];
|
||
|
||
function _initAdmin() {
|
||
// Chart
|
||
var vals = [28,32,18,45,22,38,29,52,41,34,47,56,39,44,31,58,42,37,49,53,36,41,55,62,48,44,57,59,43,47];
|
||
var max = Math.max.apply(null, vals);
|
||
var bars = document.getElementById('adm-chart');
|
||
var lbls = document.getElementById('adm-chart-lbl');
|
||
if (!bars) return;
|
||
bars.innerHTML = vals.map(function(v, i){
|
||
var h = Math.round((v/max)*100);
|
||
return '<div class="chart-bar'+(i===vals.length-1?' cur':'')+'" style="height:'+h+'%" title="'+v+'00 ₽"></div>';
|
||
}).join('');
|
||
if (lbls) {
|
||
var days = [];
|
||
for (var i=vals.length;i>0;i--) {
|
||
if (i===vals.length||i===vals.length-7||i===vals.length-14||i===vals.length-21||i===1) {
|
||
days.push(i+'д');
|
||
} else { days.push(''); }
|
||
}
|
||
lbls.innerHTML = days.map(function(d){ return '<span>'+d+'</span>'; }).join('');
|
||
}
|
||
// Payments table
|
||
var tbody = document.getElementById('adm-pay-table');
|
||
if (tbody) {
|
||
tbody.innerHTML = _ADM_PAYS.map(function(p){
|
||
var badge = p.status==='paid'?'<span class="pay-badge paid">Оплачено</span>':
|
||
p.status==='ref'?'<span class="pay-badge ref">Возврат</span>':
|
||
'<span class="pay-badge pend">Ожидание</span>';
|
||
return '<tr><td>'+p.date+'</td><td>'+p.client+'</td><td>'+p.type+'</td><td><b>'+p.amount.toLocaleString('ru')+'₽</b></td><td>'+badge+'</td></tr>';
|
||
}).join('');
|
||
}
|
||
// Refunds
|
||
var rlist = document.getElementById('adm-refunds-list');
|
||
if (rlist) {
|
||
if (_ADM_REFUNDS.length === 0) {
|
||
rlist.innerHTML = '<div style="text-align:center;padding:24px;color:var(--mut);font-size:13px">✅ Активных заявок нет</div>';
|
||
} else {
|
||
rlist.innerHTML = _ADM_REFUNDS.map(function(r){
|
||
return '<div class="refund-card'+(r.urgent?' urgent':'')+'" id="rcard-'+r.id+'">'
|
||
+'<div class="refund-body">'
|
||
+'<div class="refund-ttl">'+r.client+' · '+r.date+'</div>'
|
||
+'<div class="refund-meta">'+r.reason+'</div>'
|
||
+'<div class="refund-meta">Неиспользованных кредитов: '+r.credits+'</div>'
|
||
+'<div class="refund-actions">'
|
||
+'<button class="refund-btn approve" onclick="admRefund('+r.id+',true)">✅ Вернуть '+Math.round(r.amount*(r.credits/(r.credits+1))).toLocaleString('ru')+'₽</button>'
|
||
+'<button class="refund-btn decline" onclick="admRefund('+r.id+',false)">✕ Отклонить</button>'
|
||
+'</div></div>'
|
||
+'<div class="refund-amt">'+r.amount.toLocaleString('ru')+'₽</div>'
|
||
+'</div>';
|
||
}).join('');
|
||
}
|
||
}
|
||
}
|
||
|
||
function admRefund(id, approve) {
|
||
var card = document.getElementById('rcard-'+id);
|
||
if (card) card.style.opacity = '.4';
|
||
toast(approve ? '✅ Возврат одобрен — отправлен в ЮKassa' : '✕ Заявка отклонена — клиент уведомлён');
|
||
setTimeout(function(){ if(card) card.remove(); }, 800);
|
||
}
|
||
|
||
// ── Balance tab ──
|
||
function _refreshBalanceTab() {
|
||
var credits = parseInt(localStorage.getItem('zashita_credits') || '0');
|
||
var subPlan = localStorage.getItem('zashita_sub_plan');
|
||
var el = document.getElementById('bal-credits-num');
|
||
var sub = document.getElementById('bal-sub-status');
|
||
if (el) el.textContent = credits;
|
||
if (sub) {
|
||
var subNames = {1:'Старт', 2:'Бизнес', 3:'Безлимит'};
|
||
sub.textContent = subPlan ? ('Подписка ' + (subNames[subPlan]||'') + ' активна 💛') : 'Подписка не активна';
|
||
}
|
||
// History
|
||
var hist = JSON.parse(localStorage.getItem('zashita_pay_history') || '[]');
|
||
var hel = document.getElementById('bal-history');
|
||
if (hel) {
|
||
if (!hist.length) {
|
||
hel.innerHTML = '<div style="text-align:center;padding:24px;color:var(--mut);font-size:13px">Платежей пока нет</div>';
|
||
} else {
|
||
hel.innerHTML = hist.slice(0,10).map(function(h){
|
||
var d = new Date(h.date);
|
||
var ds = d.getDate()+'.'+(d.getMonth()+1)+'.'+d.getFullYear();
|
||
var isCredit = h.type === 'use';
|
||
return '<div class="pay-hist-item">'
|
||
+'<div class="phi-left"><div class="phi-desc">'+h.desc+'</div><div class="phi-date">'+ds+'</div></div>'
|
||
+'<div class="phi-right"><div class="phi-amt '+(isCredit?'db':'cr')+'">'
|
||
+(isCredit?'−1 кредит':'+'+(h.credits||'∞')+' кредитов')+'</div>'
|
||
+(h.amount?'<div class="phi-status">'+h.amount.toLocaleString('ru')+'₽</div>':'')
|
||
+'</div></div>';
|
||
}).join('');
|
||
}
|
||
}
|
||
}
|
||
|
||
function toggleRefundForm() {
|
||
var f = document.getElementById('ref-form');
|
||
if (f) f.style.display = f.style.display === 'none' ? '' : 'none';
|
||
}
|
||
|
||
function submitRefund() {
|
||
var reason = (document.getElementById('ref-reason')||{}).value || '';
|
||
var credits = parseInt(localStorage.getItem('zashita_credits') || '0');
|
||
if (credits <= 0) { toast('⚠ Неиспользованных кредитов нет'); return; }
|
||
// Save refund request
|
||
var refs = JSON.parse(localStorage.getItem('zashita_refund_requests') || '[]');
|
||
refs.push({date: new Date().toISOString(), credits: credits, reason: reason, status: 'pending'});
|
||
localStorage.setItem('zashita_refund_requests', JSON.stringify(refs));
|
||
toggleRefundForm();
|
||
toast('✅ Заявка отправлена — ответим в течение 10 рабочих дней');
|
||
}
|
||
|
||
// Hook into tab switch
|
||
var _origTab = typeof tab === 'function' ? tab : null;
|
||
window.addEventListener('DOMContentLoaded', function(){
|
||
_initAdmin();
|
||
_refreshBalanceTab();
|
||
});
|
||
|
||
/* ── ГОЛОСОВОЙ ВВОД ── */
|
||
var _voiceActive = false;
|
||
var _voiceRecog = null;
|
||
|
||
function toggleVoice(targetId) {
|
||
var inputId = targetId || 'intake-custom';
|
||
var btn = document.getElementById('voice-btn');
|
||
|
||
var SR = window.SpeechRecognition || window.webkitSpeechRecognition;
|
||
if (!SR) {
|
||
var hint = document.getElementById('voice-hint');
|
||
if (hint) hint.textContent = '⚠ Голосовой ввод не поддерживается в этом браузере';
|
||
return;
|
||
}
|
||
|
||
if (_voiceActive) {
|
||
if (_voiceRecog) _voiceRecog.stop();
|
||
return;
|
||
}
|
||
|
||
_voiceRecog = new SR();
|
||
_voiceRecog.lang = 'ru-RU';
|
||
_voiceRecog.interimResults = true;
|
||
_voiceRecog.continuous = false;
|
||
|
||
_voiceRecog.onstart = function() {
|
||
_voiceActive = true;
|
||
if (btn) { btn.classList.add('recording'); btn.textContent = '🔴'; }
|
||
var hint = document.getElementById('voice-hint');
|
||
if (hint) hint.textContent = '🎙 Говорите…';
|
||
};
|
||
|
||
_voiceRecog.onresult = function(e) {
|
||
var transcript = '';
|
||
for (var i = e.resultIndex; i < e.results.length; i++) {
|
||
transcript += e.results[i][0].transcript;
|
||
}
|
||
var inp = document.getElementById(inputId);
|
||
if (inp) inp.value = transcript;
|
||
};
|
||
|
||
_voiceRecog.onend = function() {
|
||
_voiceActive = false;
|
||
if (btn) { btn.classList.remove('recording'); btn.textContent = '🎤'; }
|
||
var hint = document.getElementById('voice-hint');
|
||
if (hint) hint.textContent = '';
|
||
};
|
||
|
||
_voiceRecog.onerror = function(e) {
|
||
_voiceActive = false;
|
||
if (btn) { btn.classList.remove('recording'); btn.textContent = '🎤'; }
|
||
var hint = document.getElementById('voice-hint');
|
||
if (hint) hint.textContent = e.error === 'not-allowed' ? '⚠ Разрешите доступ к микрофону' : '⚠ Ошибка записи: ' + e.error;
|
||
};
|
||
|
||
_voiceRecog.start();
|
||
}
|
||
|
||
// Скрыть mic если нет поддержки
|
||
window.addEventListener('DOMContentLoaded', function() {
|
||
var SR = window.SpeechRecognition || window.webkitSpeechRecognition;
|
||
if (!SR) {
|
||
var btn = document.getElementById('voice-btn');
|
||
if (btn) btn.classList.add('no-support');
|
||
}
|
||
});
|
||
|
||
/* ── CRM CABINET ── */
|
||
function ctSearchFilter(q) {
|
||
q = q.toLowerCase();
|
||
var rows = document.querySelectorAll('#ct-tbody tr');
|
||
rows.forEach(function(r){ r.style.display = q && !r.textContent.toLowerCase().includes(q) ? 'none' : ''; });
|
||
}
|
||
|
||
function updateKPI() {
|
||
if (!window.CT_DATA) return;
|
||
var total = CT_DATA.length;
|
||
var work = CT_DATA.filter(function(r){ return r.status==='work'; }).length;
|
||
var urg = CT_DATA.filter(function(r){ return r.risk==='high' && r.open; }).length;
|
||
var done = CT_DATA.filter(function(r){ return r.status==='done'; }).length;
|
||
var set = function(id,v){ var el=document.getElementById(id); if(el) el.textContent=v; };
|
||
set('kpi-total', total); set('kpi-work', work); set('kpi-urg', urg); set('kpi-done', done);
|
||
var b = document.getElementById('side-badge-cases');
|
||
if(b) b.textContent = CT_DATA.filter(function(r){ return r.open; }).length;
|
||
}
|
||
|
||
var TAB_TITLES = { cases:'Мои дела', case:'Текущее дело', sroki:'Сроки', shab:'Шаблоны' };
|
||
var _origTabCRM = window.tab;
|
||
window.tab = function(id) {
|
||
if (_origTabCRM) _origTabCRM(id);
|
||
var t = document.getElementById('main-hdr-title');
|
||
if (t) t.textContent = TAB_TITLES[id] || 'Кабинет';
|
||
// Показать/скрыть пункт "Текущее дело" в сайдбаре
|
||
var caseLink = document.getElementById('t-case');
|
||
if (caseLink) caseLink.style.display = id === 'case' ? 'flex' : 'none';
|
||
if (id === 'cases') setTimeout(updateKPI, 60);
|
||
};
|
||
|
||
window.addEventListener('DOMContentLoaded', function(){
|
||
setTimeout(updateKPI, 100);
|
||
});
|
||
|
||
/* ── СОЗДАНИЕ ДОКУМЕНТА ── */
|
||
var _selectedDocType = null;
|
||
|
||
var _DOC_FORMS = {
|
||
agent: {
|
||
title: 'Агентский договор',
|
||
fields: [
|
||
{id:'df-principal',label:'Принципал (вы)',placeholder:'ИП Васильев Руслан Геннадьевич',hint:'Полное наименование или ФИО',col:'half'},
|
||
{id:'df-agent',label:'Агент (контрагент)',placeholder:'ООО «Зов Ресторанс»',hint:'Полное наименование',col:'half'},
|
||
{id:'df-subject',label:'Предмет поручения',placeholder:'Поиск и привлечение клиентов для ресторана',hint:'Что именно делает агент',col:'full'},
|
||
{id:'df-fee',label:'Вознаграждение',placeholder:'150 000 руб./мес.',hint:'Сумма и периодичность',col:'half'},
|
||
{id:'df-term',label:'Срок договора',placeholder:'1 год с даты подписания',hint:'Дата начала и окончания',col:'half'},
|
||
{id:'df-court',label:'Подсудность',placeholder:'По месту нахождения Принципала',hint:'Суд при возникновении споров',col:'half'},
|
||
{id:'df-nds',label:'НДС',placeholder:'Не облагается — УСН',hint:'Или: в т.ч. НДС 20%',col:'half'},
|
||
]
|
||
},
|
||
trust: {
|
||
title: 'Доверенность',
|
||
fields: [
|
||
{id:'df-principal',label:'Доверитель',placeholder:'ИП Васильев Руслан Геннадьевич',hint:'ФИО и паспортные данные',col:'half'},
|
||
{id:'df-attorney',label:'Поверенный',placeholder:'Иванов Иван Иванович',hint:'ФИО и паспортные данные',col:'half'},
|
||
{id:'df-powers',label:'Полномочия',placeholder:'Подписание договоров, переговоры с контрагентами',hint:'Что может делать поверенный',col:'full'},
|
||
{id:'df-term',label:'Срок действия',placeholder:'1 год',hint:'Дата выдачи и срок',col:'half'},
|
||
{id:'df-subst',label:'Передоверие',placeholder:'Без права передоверия',hint:'Разрешено ли передоверие',col:'half'},
|
||
]
|
||
},
|
||
claim: {
|
||
title: 'Претензия',
|
||
fields: [
|
||
{id:'df-sender',label:'Отправитель',placeholder:'ИП Васильев Р.Г.',hint:'Ваши данные',col:'half'},
|
||
{id:'df-receiver',label:'Получатель',placeholder:'ООО «Контрагент»',hint:'Кому направляете',col:'half'},
|
||
{id:'df-basis',label:'Основание',placeholder:'Договор поставки № 12 от 01.04.2025',hint:'Договор или обязательство',col:'full'},
|
||
{id:'df-violation',label:'Нарушение',placeholder:'Не оплачена поставка товара на сумму 500 000 руб.',hint:'Что нарушено',col:'full'},
|
||
{id:'df-demand',label:'Требование',placeholder:'Оплатить в течение 10 дней',hint:'Что требуете и в какой срок',col:'full'},
|
||
{id:'df-penalty',label:'Неустойка',placeholder:'0,1% за каждый день просрочки',hint:'Размер пени по договору или ст. 395 ГК',col:'half'},
|
||
]
|
||
},
|
||
supply: {
|
||
title: 'Договор поставки',
|
||
fields: [
|
||
{id:'df-supplier',label:'Поставщик',placeholder:'ООО «Поставщик»',hint:'Полное наименование поставщика',col:'half'},
|
||
{id:'df-buyer',label:'Покупатель (вы)',placeholder:'ИП Васильев Р.Г.',hint:'Ваши данные',col:'half'},
|
||
{id:'df-goods',label:'Товар',placeholder:'Кухонное оборудование, ассортимент по спецификации',hint:'Наименование и описание товара',col:'full'},
|
||
{id:'df-price',label:'Сумма поставки',placeholder:'850 000 руб. в т.ч. НДС 20%',hint:'Общая сумма и НДС',col:'half'},
|
||
{id:'df-shipdate',label:'Срок поставки',placeholder:'30 дней с даты оплаты',hint:'Когда должен быть доставлен товар',col:'half'},
|
||
{id:'df-quality',label:'Гарантия качества',placeholder:'12 месяцев с даты поставки',hint:'Срок гарантии и условия возврата',col:'half'},
|
||
{id:'df-penalty',label:'Неустойка за просрочку',placeholder:'0,1% в день от стоимости непоставленного',hint:'Размер пени',col:'half'},
|
||
]
|
||
},
|
||
rent: {
|
||
title: 'Договор аренды',
|
||
fields: [
|
||
{id:'df-landlord',label:'Арендодатель',placeholder:'ООО «Бизнес-Центр Плюс»',hint:'Кто сдаёт',col:'half'},
|
||
{id:'df-tenant',label:'Арендатор (вы)',placeholder:'ИП Васильев Р.Г.',hint:'Ваши данные',col:'half'},
|
||
{id:'df-object',label:'Объект аренды',placeholder:'Офис 305, ул. Красная, 1, г. Краснодар, 45 кв.м',hint:'Адрес, площадь, кадастровый номер',col:'full'},
|
||
{id:'df-rent',label:'Арендная плата',placeholder:'80 000 руб./мес. без НДС',hint:'Размер и периодичность оплаты',col:'half'},
|
||
{id:'df-term',label:'Срок аренды',placeholder:'1 год с 01.06.2025',hint:'Дата начала и конца',col:'half'},
|
||
{id:'df-deposit',label:'Обеспечительный платёж',placeholder:'160 000 руб. (2 месяца)',hint:'Размер и условия возврата',col:'half'},
|
||
{id:'df-repair',label:'Ремонт и улучшения',placeholder:'Только с письменного согласия арендодателя',hint:'Кто несёт расходы',col:'half'},
|
||
]
|
||
},
|
||
nda: {
|
||
title: 'NDA / Конфиденциальность',
|
||
fields: [
|
||
{id:'df-party1',label:'Сторона 1 (вы)',placeholder:'ИП Васильев Р.Г.',hint:'Ваши данные',col:'half'},
|
||
{id:'df-party2',label:'Сторона 2',placeholder:'ООО «Партнёр»',hint:'Контрагент',col:'half'},
|
||
{id:'df-info',label:'Что является конфиденциальным',placeholder:'Бизнес-планы, клиентская база, технологии производства',hint:'Конкретный перечень закрытой информации',col:'full'},
|
||
{id:'df-term',label:'Срок действия NDA',placeholder:'3 года с даты подписания',hint:'Период действия обязательств',col:'half'},
|
||
{id:'df-exceptions',label:'Исключения',placeholder:'Общедоступная информация, данные от третьих лиц',hint:'Что НЕ является конфиденциальным',col:'half'},
|
||
{id:'df-penalty',label:'Ответственность за разглашение',placeholder:'500 000 руб. за каждый случай',hint:'Штраф или способ расчёта убытков',col:'half'},
|
||
]
|
||
},
|
||
labor: {
|
||
title: 'Трудовой договор',
|
||
fields: [
|
||
{id:'df-employer',label:'Работодатель',placeholder:'ИП Васильев Р.Г.',hint:'Наименование или ФИО ИП',col:'half'},
|
||
{id:'df-employee',label:'Работник',placeholder:'Иванова Мария Петровна',hint:'ФИО, паспортные данные',col:'half'},
|
||
{id:'df-position',label:'Должность',placeholder:'Менеджер по работе с клиентами',hint:'Точное наименование должности',col:'full'},
|
||
{id:'df-salary',label:'Оклад',placeholder:'60 000 руб./мес. до вычета НДФЛ',hint:'Размер оклада и доп. выплаты',col:'half'},
|
||
{id:'df-schedule',label:'График работы',placeholder:'Пн–Пт, 09:00–18:00',hint:'Режим рабочего времени',col:'half'},
|
||
{id:'df-start',label:'Дата начала',placeholder:'01.06.2025',hint:'Когда приступает к работе',col:'half'},
|
||
{id:'df-probation',label:'Испытательный срок',placeholder:'3 месяца',hint:'Или «без испытания»',col:'half'},
|
||
]
|
||
},
|
||
dismiss: {
|
||
title: 'Соглашение о расторжении',
|
||
fields: [
|
||
{id:'df-party1',label:'Сторона 1 (вы)',placeholder:'ИП Васильев Р.Г.',hint:'Ваши данные',col:'half'},
|
||
{id:'df-party2',label:'Сторона 2',placeholder:'ООО «Зов Ресторанс»',hint:'Контрагент',col:'half'},
|
||
{id:'df-contract',label:'Расторгаемый договор',placeholder:'Агентский договор № 5 от 01.03.2025',hint:'Название, номер, дата',col:'full'},
|
||
{id:'df-date',label:'Дата расторжения',placeholder:'01.06.2025',hint:'Когда договор прекращает действие',col:'half'},
|
||
{id:'df-settlement',label:'Взаиморасчёты',placeholder:'Стороны не имеют взаимных претензий',hint:'Долги, возвраты, штрафы',col:'half'},
|
||
{id:'df-return',label:'Возврат имущества',placeholder:'Переданные материалы возвращены по акту',hint:'Что нужно вернуть',col:'full'},
|
||
]
|
||
}
|
||
};
|
||
|
||
function selectDocType(type, el) {
|
||
_selectedDocType = type;
|
||
document.querySelectorAll('.doc-type-card').forEach(function(c){ c.classList.remove('sel'); });
|
||
if(el) el.classList.add('sel');
|
||
var btn = document.getElementById('doc-type-next');
|
||
if(btn){ btn.classList.add('show'); btn.textContent = 'Заполнить параметры →'; }
|
||
}
|
||
|
||
function goCreateStep(step) {
|
||
document.querySelectorAll('.create-pane').forEach(function(p){ p.classList.remove('on'); });
|
||
document.querySelectorAll('.cstep').forEach(function(s,i){
|
||
s.classList.toggle('act', i+1 === step);
|
||
s.classList.toggle('done', i+1 < step);
|
||
var num = s.querySelector('.cstep-num');
|
||
if(num) num.textContent = (i+1 < step) ? '✓' : (i+1);
|
||
});
|
||
if(step === 1){ document.getElementById('cp-type').classList.add('on'); }
|
||
else if(step === 2){ buildCreateForm(); document.getElementById('cp-form').classList.add('on'); }
|
||
else if(step === 3){ document.getElementById('cp-preview').classList.add('on'); startDocGeneration(); }
|
||
window.scrollTo(0,0);
|
||
}
|
||
|
||
function buildCreateForm() {
|
||
var type = _selectedDocType || 'agent';
|
||
var def = _DOC_FORMS[type] || _DOC_FORMS.agent;
|
||
var title = document.getElementById('cf-doc-title');
|
||
if(title) title.textContent = def.title;
|
||
var grid = document.getElementById('create-form-fields');
|
||
if(!grid) return;
|
||
grid.innerHTML = def.fields.map(function(f){
|
||
var cls = f.col === 'full' ? 'cf-group wide' : 'cf-group';
|
||
return '<div class="'+cls+'"><label class="cf-label">'+f.label+'</label><input class="cf-input" id="'+f.id+'" placeholder="'+f.placeholder+'"><span class="cf-hint">'+f.hint+'</span></div>';
|
||
}).join('');
|
||
}
|
||
|
||
function startDocGeneration() {
|
||
var spinner = document.getElementById('doc-generating');
|
||
var preview = document.getElementById('doc-preview-wrap');
|
||
if(spinner){ spinner.classList.add('show'); }
|
||
if(preview){ preview.classList.remove('show'); }
|
||
setTimeout(function(){
|
||
if(spinner) spinner.classList.remove('show');
|
||
if(preview) preview.classList.add('show');
|
||
}, 2200);
|
||
}
|
||
|
||
/* ── ЧАСЫ ── */
|
||
(function(){
|
||
var DAYS = ['Воскресенье','Понедельник','Вторник','Среда','Четверг','Пятница','Суббота'];
|
||
var MONTHS = ['января','февраля','марта','апреля','мая','июня','июля','августа','сентября','октября','ноября','декабря'];
|
||
function tickClock(){
|
||
var now = new Date();
|
||
var dayEl = document.getElementById('sc-day');
|
||
var dateEl = document.getElementById('sc-date');
|
||
var timeEl = document.getElementById('sc-time');
|
||
if(dayEl) dayEl.textContent = DAYS[now.getDay()];
|
||
if(dateEl) dateEl.textContent = now.getDate() + ' ' + MONTHS[now.getMonth()] + ' ' + now.getFullYear();
|
||
if(timeEl){
|
||
var h = String(now.getHours()).padStart(2,'0');
|
||
var m = String(now.getMinutes()).padStart(2,'0');
|
||
var s = String(now.getSeconds()).padStart(2,'0');
|
||
timeEl.textContent = h + ':' + m + ':' + s;
|
||
}
|
||
}
|
||
setInterval(tickClock, 1000);
|
||
window.addEventListener('DOMContentLoaded', tickClock);
|
||
})();
|
||
|
||
/* ── СЧЁТЧИК ПРОТОКОЛА ── */
|
||
var _riskApplied = new Set();
|
||
function applyRisk(num, btn) {
|
||
_riskApplied.add(num);
|
||
btn.textContent = '✅ Применено';
|
||
btn.disabled = true;
|
||
btn.style.background = '#16a34a';
|
||
btn.style.cursor = 'default';
|
||
_updateProtocolBar();
|
||
toast('✅ Пункт #' + num + ' добавлен в протокол разногласий');
|
||
}
|
||
function _updateProtocolBar() {
|
||
var n = _riskApplied.size;
|
||
var bar = document.getElementById('protocol-bar');
|
||
var sub = document.getElementById('pb-sub');
|
||
var btn = document.getElementById('pb-generate');
|
||
if (!bar) return;
|
||
if (n > 0) {
|
||
bar.classList.add('show');
|
||
if (sub) sub.textContent = 'Выбрано пунктов: ' + n + ' из 12 — готов к формированию';
|
||
if (btn) btn.textContent = 'Сформировать протокол (' + n + ') →';
|
||
}
|
||
}
|
||
|
||
/* ── RISK ACCORDION ── */
|
||
function toggleRisk(el) {
|
||
var wasOpen = el.classList.contains('expanded');
|
||
document.querySelectorAll('.risk-item.expanded').forEach(function(r){ r.classList.remove('expanded'); });
|
||
if (!wasOpen) el.classList.add('expanded');
|
||
}
|
||
|
||
/* ── CASE TABS ── */
|
||
function caseTab(id, el) {
|
||
document.querySelectorAll('.case-pane').forEach(function(p){ p.classList.remove('on'); });
|
||
document.querySelectorAll('.case-tab').forEach(function(t){ t.classList.remove('on'); });
|
||
var pane = document.getElementById('cp-' + id);
|
||
if (pane) pane.classList.add('on');
|
||
if (el) el.classList.add('on');
|
||
}
|
||
|
||
/* ── СТАТУС ЗАКАЗА ── */
|
||
const OS_DEADLINES = {
|
||
protocol: { 1:'до 12 часов', 2:'до 24 часов', 3:'до 48 часов', sub:'после получения файла договора' },
|
||
redact: { 1:'до 12 часов', 2:'до 24 часов', 3:'до 48 часов', sub:'после получения файла договора' },
|
||
clean: { 1:'до 24 часов', 2:'до 48 часов', 3:'до 72 часов', sub:'после получения файла договора' },
|
||
partner: { 1:'до 24 часов', 2:'до 48 часов', 3:'до 72 часов', sub:'после получения файла договора' },
|
||
consult: { 1:'2 часа', 2:'сегодня', 3:'24 часа', sub:'отвечаем после получения оплаты' },
|
||
reply: { 1:'до 12 часов', 2:'до 12 часов', 3:'до результата', sub:'после получения переписки с контрагентом' }
|
||
};
|
||
const OS_STEP2 = {
|
||
protocol:'Юрист изучает договор',
|
||
redact:'Юрист готовит редакцию',
|
||
clean:'Юрист чистит текст',
|
||
partner:'Юрист пишет партнёрскую версию',
|
||
consult:'Юрист готовится к консультации',
|
||
reply:'Юрист составляет ответ'
|
||
};
|
||
const OS_ELENA = {
|
||
protocol:'Заказ получен — уже передала юристу. <b>Пришлите договор</b> в Telegram <a href="https://t.me/wasrusgen1" target="_blank">@wasrusgen1</a> — без него начать не получится. Как только файл придёт — сразу приступаем 💛',
|
||
redact:'Заказ получен. <b>Пришлите договор</b> в Telegram <a href="https://t.me/wasrusgen1" target="_blank">@wasrusgen1</a> — и обозначьте что хотите изменить, если есть конкретные пункты. Начнём сразу 💛',
|
||
clean:'Заказ получен. <b>Пришлите договор</b> в Telegram <a href="https://t.me/wasrusgen1" target="_blank">@wasrusgen1</a> — юрист сделает его читаемым и структурированным. Жду файл 💛',
|
||
partner:'Заказ получен. <b>Пришлите договор</b> в Telegram <a href="https://t.me/wasrusgen1" target="_blank">@wasrusgen1</a> — и кратко опишите вашу позицию в переговорах. Это поможет сделать текст работающим 💛',
|
||
consult:'Заказ получен. <b>Пришлите договор</b> в Telegram <a href="https://t.me/wasrusgen1" target="_blank">@wasrusgen1</a> — и список вопросов, или просто напишите «разбери сам». AI найдёт все риски и ответит по вашей ситуации. Отвечаем в течение 2 часов 💛',
|
||
reply:'Заказ получен. <b>Пришлите переписку с контрагентом и текст возражения</b> в Telegram <a href="https://t.me/wasrusgen1" target="_blank">@wasrusgen1</a> — юрист составит ответ с вашей правовой позицией 💛'
|
||
};
|
||
|
||
function showOrderStatus() {
|
||
const d = DELIVS[_selDeliv] || {};
|
||
const pKey = 'p' + _selPlan;
|
||
const pArr = d[pKey] || [];
|
||
const dl = (OS_DEADLINES[_selDeliv] || {})[_selPlan] || 'уточним';
|
||
const dlSub = (OS_DEADLINES[_selDeliv] || {}).sub || '';
|
||
|
||
const set = (id, val) => { const el = document.getElementById(id); if (el) el.innerHTML = val; };
|
||
set('os-svc', d.ttl || 'Юридическая услуга');
|
||
set('os-plan-name', pArr[1] || ('Тариф ' + _selPlan));
|
||
set('os-price', pArr[0] || '');
|
||
set('os-orderid', 'Заказ #' + Math.floor(1000 + Math.random() * 8999));
|
||
set('os-step2-lbl', (OS_STEP2[_selDeliv] || 'Юрист работает').replace(' ', '<br>'));
|
||
set('os-deadline-ttl', 'Срок: ' + dl);
|
||
set('os-deadline-sub', dlSub);
|
||
set('os-elena-msg', OS_ELENA[_selDeliv] || OS_ELENA.protocol);
|
||
set('os-ok-sub', 'Заказ №' + Math.floor(1000 + Math.random() * 8999) + ' передан в работу');
|
||
}
|
||
|
||
/* ── АНАЛИТИКА CUSTOM-ЗАПРОСОВ ── */
|
||
const CA_STOPWORDS = new Set(['и','в','на','с','по','для','что','это','как','не','а','но','из','к','о','от','за','до','при','без','под','над','со','об','же','бы','ли','ещё','уже','когда','если','мне','мы','я','вы','он','она','они','то','так','ну','ладно','просто','только','очень','нет','да','быть','есть','это','свой','мой','ваш','наш','его','её','их','все','всё','один','одна','других','другой','которые','который','можно','нужно','надо','хочу','хочется','нужна','нужен','нужно','получить','сделать','чтобы','также']);
|
||
|
||
function caWordFreq(arr) {
|
||
const freq = {};
|
||
arr.forEach(r => {
|
||
const words = (r.text || '').toLowerCase()
|
||
.replace(/[^а-яёa-z\s]/g, ' ')
|
||
.split(/\s+/)
|
||
.filter(w => w.length > 3 && !CA_STOPWORDS.has(w));
|
||
words.forEach(w => { freq[w] = (freq[w] || 0) + 1; });
|
||
});
|
||
return Object.entries(freq)
|
||
.sort((a, b) => b[1] - a[1])
|
||
.slice(0, 15);
|
||
}
|
||
|
||
function caFmtDate(ts) {
|
||
try {
|
||
const d = new Date(ts);
|
||
return d.toLocaleDateString('ru-RU', {day:'2-digit',month:'short',hour:'2-digit',minute:'2-digit'});
|
||
} catch(e) { return ts; }
|
||
}
|
||
|
||
function caAddToSystem(idx) {
|
||
const arr = JSON.parse(localStorage.getItem('zashita_custom_delivs') || '[]');
|
||
if (arr[idx]) { arr[idx].added = true; localStorage.setItem('zashita_custom_delivs', JSON.stringify(arr)); }
|
||
renderCustomAdmin();
|
||
}
|
||
|
||
function caCopyText(text) {
|
||
navigator.clipboard.writeText(text).catch(() => {});
|
||
showToast('Скопировано');
|
||
}
|
||
|
||
function caExportCSV() {
|
||
const arr = JSON.parse(localStorage.getItem('zashita_custom_delivs') || '[]');
|
||
if (!arr.length) return;
|
||
const rows = [['Дата','Тип договора','Запрос','Добавлено в систему']];
|
||
arr.forEach(r => rows.push([
|
||
r.ts || '', (r.ctype || '').replace(/,/g,''),
|
||
'"' + (r.text || '').replace(/"/g,'""') + '"',
|
||
r.added ? 'да' : 'нет'
|
||
]));
|
||
const csv = rows.map(r => r.join(',')).join('\n');
|
||
const a = document.createElement('a');
|
||
a.href = 'data:text/csv;charset=utf-8,' + encodeURIComponent('' + csv);
|
||
a.download = 'zashita_custom_' + new Date().toISOString().slice(0,10) + '.csv';
|
||
a.click();
|
||
}
|
||
|
||
function caExportJSON() {
|
||
const arr = JSON.parse(localStorage.getItem('zashita_custom_delivs') || '[]');
|
||
navigator.clipboard.writeText(JSON.stringify(arr, null, 2))
|
||
.then(() => showToast('JSON скопирован в буфер'))
|
||
.catch(() => showToast('Ошибка копирования'));
|
||
}
|
||
|
||
function caClearAll() {
|
||
if (!confirm('Удалить все custom-запросы?')) return;
|
||
localStorage.removeItem('zashita_custom_delivs');
|
||
renderCustomStats();
|
||
renderCustomAdmin();
|
||
}
|
||
|
||
function renderCustomAdmin() {
|
||
const arr = JSON.parse(localStorage.getItem('zashita_custom_delivs') || '[]');
|
||
const body = document.getElementById('ca-body');
|
||
if (!body) return;
|
||
|
||
if (!arr.length) {
|
||
body.innerHTML = '<div class="ca-empty"><div class="ce-icon">📭</div>Пока нет запросов.<br>Они появятся когда клиент нажмёт «Отправить запрос».</div>';
|
||
return;
|
||
}
|
||
|
||
const ctypes = [...new Set(arr.map(r => (r.ctype||'').trim()).filter(Boolean))];
|
||
const words = caWordFreq(arr);
|
||
const added = arr.filter(r => r.added).length;
|
||
|
||
// Статистика
|
||
let html = `<div class="ca-stats">
|
||
<div class="ca-stat"><div class="sv">${arr.length}</div><div class="sl">Всего запросов</div></div>
|
||
<div class="ca-stat"><div class="sv">${ctypes.length || '—'}</div><div class="sl">Типов договора</div></div>
|
||
<div class="ca-stat"><div class="sv">${added}</div><div class="sl">Добавлено в систему</div></div>
|
||
</div>`;
|
||
|
||
// Частотный анализ
|
||
if (words.length) {
|
||
html += '<div class="ca-section">Частые темы запросов</div><div class="ca-words">';
|
||
const maxCnt = words[0][1];
|
||
words.forEach(([w, c]) => {
|
||
const isTop = c === maxCnt;
|
||
html += `<div class="ca-word${isTop?' w-top':''}">${w}<span class="wc">${c}</span></div>`;
|
||
});
|
||
html += '</div>';
|
||
}
|
||
|
||
// Список запросов
|
||
html += '<div class="ca-section">Все запросы</div>';
|
||
arr.slice().reverse().forEach((r, i) => {
|
||
const realIdx = arr.length - 1 - i;
|
||
const ctypeLabel = (r.ctype||'').trim() || 'тип не определён';
|
||
html += `<div class="ca-card${r.added?' ca-done':''}">
|
||
<div class="cc-head">
|
||
<span class="cc-ctype">${ctypeLabel}</span>
|
||
<span class="cc-ts">${caFmtDate(r.ts)}</span>
|
||
</div>
|
||
<div class="cc-text">${r.text || ''}</div>
|
||
<div class="cc-actions">
|
||
<button class="cc-add" onclick="caAddToSystem(${realIdx})" ${r.added?'disabled':''}>
|
||
${r.added ? '✓ Добавлено в систему' : '+ Добавить в систему'}
|
||
</button>
|
||
<button class="cc-copy" onclick="caCopyText(${JSON.stringify(r.text||'')})">Копировать</button>
|
||
</div>
|
||
</div>`;
|
||
});
|
||
|
||
// Экспорт
|
||
html += `<div class="ca-export">
|
||
<button onclick="caExportCSV()">⬇ Скачать CSV</button>
|
||
<button onclick="caExportJSON()">📋 Копировать JSON</button>
|
||
<button onclick="caClearAll()" style="color:#b91c1c;border-color:#fecaca">🗑 Очистить всё</button>
|
||
</div>`;
|
||
|
||
body.innerHTML = html;
|
||
}
|
||
|
||
function showToast(msg) {
|
||
let t = document.getElementById('ca-toast');
|
||
if (!t) {
|
||
t = document.createElement('div'); t.id = 'ca-toast';
|
||
t.style.cssText = 'position:fixed;bottom:90px;left:50%;transform:translateX(-50%);background:#0C0608;color:#fff;padding:9px 18px;border-radius:10px;font-size:13px;z-index:99999;pointer-events:none;transition:opacity .3s';
|
||
document.body.appendChild(t);
|
||
}
|
||
t.textContent = msg; t.style.opacity = '1';
|
||
clearTimeout(t._to); t._to = setTimeout(() => { t.style.opacity = '0'; }, 2000);
|
||
}
|
||
|
||
window.addEventListener('DOMContentLoaded', renderStats);
|
||
window.addEventListener('DOMContentLoaded', renderCustomStats);
|
||
window.addEventListener('DOMContentLoaded', renderCustomAdmin);
|
||
function handleHash() {
|
||
const h = window.location.hash.slice(1);
|
||
if (!h) return;
|
||
const [screen, deliv, plan] = h.split(':');
|
||
if (deliv) _selDeliv = deliv;
|
||
if (plan) _selPlan = parseInt(plan) || 2;
|
||
if (screen === 'order-status') { showOrderStatus(); go('order-status'); }
|
||
else if (screen) go(screen);
|
||
}
|
||
window.addEventListener('DOMContentLoaded', handleHash);
|
||
window.addEventListener('hashchange', handleHash);
|
||
function tab(name){
|
||
document.querySelectorAll('.tabpane').forEach(p=>p.classList.toggle('on',p.id==='p-'+name));
|
||
if(name==='sroki' && typeof renderDeadlines==='function') renderDeadlines();
|
||
if(name==='balance' && typeof _refreshBalanceTab==='function') _refreshBalanceTab();;
|
||
document.querySelectorAll('.side a').forEach(a=>a.classList.remove('on'));
|
||
const map={cases:'t-cases',case:'t-case',sroki:'t-sroki',shab:'t-shab',create:'t-create'};
|
||
const el=document.getElementById(map[name]); if(el) el.classList.add('on');
|
||
window.scrollTo(0,0);
|
||
}
|
||
</script>
|
||
|
||
|
||
</div>
|
||
|
||
<!-- ── ЮKASSA ВИДЖЕТ ── -->
|
||
<div class="yk-overlay" id="yk-overlay" onclick="ykClose(event)">
|
||
<div class="yk-sheet" id="yk-sheet">
|
||
<button class="yk-close" onclick="ykClose()">✕</button>
|
||
|
||
<div id="yk-form">
|
||
<div class="yk-header">
|
||
<div class="yk-logo">ЮMoney<span>·</span>Kassa</div>
|
||
<div class="yk-amount" id="yk-amount">2 480 ₽</div>
|
||
</div>
|
||
|
||
<button class="yk-sbp" onclick="ykPaySBP()">
|
||
<div class="yk-sbp-icon">СБП</div>
|
||
Оплатить через СБП
|
||
</button>
|
||
|
||
<div class="yk-sep">или картой</div>
|
||
|
||
<div class="yk-field">
|
||
<label>Номер карты</label>
|
||
<input id="yk-card" type="text" inputmode="numeric" placeholder="0000 0000 0000 0000" maxlength="19" oninput="ykFmtCard(this)" autocomplete="cc-number">
|
||
</div>
|
||
<div class="yk-row">
|
||
<div class="yk-field">
|
||
<label>Срок действия</label>
|
||
<input id="yk-exp" type="text" inputmode="numeric" placeholder="ММ / ГГ" maxlength="7" oninput="ykFmtExp(this)" autocomplete="cc-exp">
|
||
</div>
|
||
<div class="yk-field">
|
||
<label>CVV / CVC</label>
|
||
<input id="yk-cvv" type="password" inputmode="numeric" placeholder="•••" maxlength="4" autocomplete="cc-csc">
|
||
</div>
|
||
</div>
|
||
|
||
<button class="yk-pay-btn" id="yk-pay-btn" onclick="ykSubmit()">Оплатить <span id="yk-btn-amount">2 480 ₽</span></button>
|
||
<div class="yk-footer">
|
||
Платёж защищён · <a href="https://yookassa.ru" target="_blank">ЮKassa</a> ·
|
||
<a href="oferta.html" target="_blank">Оферта</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="yk-success" id="yk-success">
|
||
<div class="yk-check">✅</div>
|
||
<div class="yk-sttl">Оплата прошла!</div>
|
||
<div class="yk-ssub">Переходим к заказу…</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ЮKassa payment modal -->
|
||
<div class="yk-overlay" id="yk-overlay" onclick="ykClose(event)">
|
||
<div class="yk-modal" onclick="event.stopPropagation()">
|
||
<div class="yk-hdr">
|
||
<div class="yk-ttl" id="yk-ttl">Оплата</div>
|
||
<button class="yk-close" onclick="ykClose()">✕</button>
|
||
</div>
|
||
<div class="yk-amount" id="yk-amount">490 ₽</div>
|
||
<div class="yk-methods">
|
||
<div class="yk-method yk-sbp sel" onclick="ykMethod('sbp',this)">
|
||
<div class="yk-method-ico">📲</div>
|
||
<div class="yk-method-lbl">СБП</div>
|
||
</div>
|
||
<div class="yk-method" onclick="ykMethod('card',this)">
|
||
<div class="yk-method-ico">💳</div>
|
||
<div class="yk-method-lbl">Карта</div>
|
||
</div>
|
||
<div class="yk-method" onclick="ykMethod('mir',this)">
|
||
<div class="yk-method-ico">🇷🇺</div>
|
||
<div class="yk-method-lbl">Мир Pay</div>
|
||
</div>
|
||
<div class="yk-method" onclick="ykMethod('qr',this)">
|
||
<div class="yk-method-ico">📱</div>
|
||
<div class="yk-method-lbl">QR-код</div>
|
||
</div>
|
||
</div>
|
||
<div class="yk-card-form" id="yk-card-form" style="display:none">
|
||
<input placeholder="Номер карты" maxlength="19" oninput="fmtCard(this)">
|
||
<div class="yk-card-row">
|
||
<input placeholder="ММ / ГГ" maxlength="5">
|
||
<input placeholder="CVV" maxlength="3" type="password">
|
||
</div>
|
||
</div>
|
||
<button class="yk-pay-btn" id="yk-pay-btn" onclick="ykPay()">Оплатить 490 ₽</button>
|
||
<div class="yk-secure">🔒 Защищено ЮKassa · 3D Secure · чек на email</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ═ ADMIN SCREEN ═ -->
|
||
<div class="screen" id="admin">
|
||
<div class="topbar">
|
||
<img class="topbar-wm" src="logos/logo-zashita-word.svg" alt="ЗАЩИТА">
|
||
<span class="ttl">Кабинет администратора</span>
|
||
<span class="back back-link" onclick="go('start')">← выйти</span>
|
||
</div>
|
||
<div class="admin-wrap">
|
||
<div class="crumb">Администратор</div>
|
||
<h1 style="margin-bottom:20px">Дашборд</h1>
|
||
|
||
<!-- KPI -->
|
||
<div class="admin-kpi">
|
||
<div class="akpi">
|
||
<div class="akpi-num" style="color:var(--bg)" id="adm-rev">47 300 ₽</div>
|
||
<div class="akpi-lbl">Выручка за месяц</div>
|
||
<div class="akpi-trend up" id="adm-rev-tr">↑ +18% к прошлому</div>
|
||
</div>
|
||
<div class="akpi">
|
||
<div class="akpi-num" id="adm-clients">134</div>
|
||
<div class="akpi-lbl">Клиентов всего</div>
|
||
<div class="akpi-trend up">↑ +12 новых</div>
|
||
</div>
|
||
<div class="akpi">
|
||
<div class="akpi-num" id="adm-subs">28</div>
|
||
<div class="akpi-lbl">Активных подписок</div>
|
||
<div class="akpi-trend up">↑ +3 этой неделе</div>
|
||
</div>
|
||
<div class="akpi">
|
||
<div class="akpi-num" style="color:#ef4444" id="adm-refunds">2</div>
|
||
<div class="akpi-lbl">Заявки на возврат</div>
|
||
<div class="akpi-trend dn">⚠ Требуют решения</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Revenue chart -->
|
||
<div class="admin-chart">
|
||
<div class="admin-section-hdr">
|
||
<div class="admin-section-ttl">Выручка — последние 30 дней</div>
|
||
<div class="admin-section-link" onclick="adminChartMode()">По неделям</div>
|
||
</div>
|
||
<div class="chart-bars" id="adm-chart"></div>
|
||
<div class="chart-lbl" id="adm-chart-lbl"></div>
|
||
</div>
|
||
|
||
<!-- Recent payments -->
|
||
<div class="admin-section">
|
||
<div class="admin-section-hdr">
|
||
<div class="admin-section-ttl">Последние платежи</div>
|
||
<div class="admin-section-link">Все платежи →</div>
|
||
</div>
|
||
<table class="pay-table">
|
||
<thead><tr><th>Дата</th><th>Клиент</th><th>Тип</th><th>Сумма</th><th>Статус</th></tr></thead>
|
||
<tbody id="adm-pay-table"></tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- Refund requests -->
|
||
<div class="admin-section">
|
||
<div class="admin-section-hdr">
|
||
<div class="admin-section-ttl">Заявки на возврат</div>
|
||
</div>
|
||
<div id="adm-refunds-list"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</body></html>
|