<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="https://www.pandoraburo.ru/" xml:lang="ru">
  <id>https://www.pandoraburo.ru/stropy-gruzopodemnoe-oborudovanie-kryuki-trosa</id>
  <link href="https://www.pandoraburo.ru/stropy-gruzopodemnoe-oborudovanie-kryuki-trosa.xml" rel="self"/>
  <title>Стропы Грузоподьемное оборудование Крюки Троса</title>
  <subtitle type="html">&lt;html lang="ru"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Каталог · Стропы, крюки, канаты, колёса, фланцы, барабаны · Арсенал-Деталь&lt;/title&gt;
&lt;style&gt;
  :root{
    --gold:#FFD700;--gold-light:#FFE55C;--gold-deep:#B8860B;
    --bg:#0a0a0a;--muted:#9a8040;--border:rgba(212,175,55,.35);
    --accent:#FF8C00;--ok:#7dff7d;--bad:#ff9a9a;--cyan:#6ee8e4;
    --green:#7dff7d;--green-dark:#3aa03a;
  }
  *{box-sizing:border-box;margin:0;padding:0}
  body{background:#050505;color:#e8e8e8;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif;padding:20px 14px 160px;line-height:1.5;}
  .wrap{max-width:1600px;margin:0 auto}

  .banner{max-width:640px;margin:0 auto 14px;background:radial-gradient(120% 120% at 20% 0%,rgba(255,215,0,.18),transparent 55%),linear-gradient(135deg,#111,#0a0a0a);border:1px solid var(--gold);border-radius:14px;padding:24px;text-align:center;box-shadow:0 6px 22px rgba(0,0,0,.6);}
  .banner-tag{display:inline-block;background:var(--gold);color:#0a0a0a;font-size:10px;font-weight:800;letter-spacing:2px;padding:3px 12px;border-radius:999px;margin-bottom:12px;}
  .banner-title{font-weight:800;font-size:22px;line-height:1.15;color:#fff;margin-bottom:10px;}
  .banner-phone{font-size:18px;font-weight:800;color:var(--gold);margin-bottom:4px;}
  .banner-note{font-size:12px;color:var(--muted);}

  .ticker{display:flex;align-items:stretch;background:var(--bg);border:1px solid var(--gold);border-radius:8px;overflow:hidden;margin-bottom:14px;height:44px;}
  .ticker-label{background:var(--gold);color:#0a0a0a;font-weight:800;font-size:12px;letter-spacing:1.5px;padding:0 16px;display:flex;align-items:center;white-space:nowrap;}
  .ticker-vp{flex:1;overflow:hidden;position:relative}
  .ticker-track{display:inline-flex;align-items:center;height:100%;white-space:nowrap;animation:tickerMove 50s linear infinite;padding-left:20px;}
  .ticker-item{color:var(--gold);font-size:13px;padding:0 10px}
  .ticker-item b{color:var(--gold-light);font-weight:700}
  .ticker-dot{color:var(--gold);font-size:10px}
  @keyframes tickerMove{0%{transform:translateX(0)}100%{transform:translateX(-50%)}}

  .ad-strip{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:14px;}
  @media(max-width:700px){.ad-strip{grid-template-columns:1fr}}
  .ad-item{display:flex;align-items:center;gap:12px;padding:14px 18px;background:linear-gradient(135deg,rgba(255,215,0,.1) 0%,rgba(10,15,30,.7) 100%);border:1px solid var(--border);border-radius:14px;text-decoration:none;transition:all .25s;}
  .ad-item:hover{border-color:var(--gold);box-shadow:0 0 20px rgba(255,215,0,.3);transform:translateY(-2px);}
  .ad-tag{background:var(--gold);color:#0a0a0a;font-size:.68rem;font-weight:800;letter-spacing:.8px;text-transform:uppercase;padding:4px 10px;border-radius:999px;flex-shrink:0;}
  .ad-text{color:#e8f4ff;font-size:.9rem;font-weight:600;flex:1;}
  .ad-cta{color:var(--gold);font-size:.85rem;font-weight:800;letter-spacing:.5px;white-space:nowrap;}
  .ad-item:hover .ad-cta{color:var(--gold-light);text-shadow:0 0 8px var(--gold-light);}

  .header{background:radial-gradient(120% 120% at 20% 0%,rgba(255,215,0,.25),transparent 55%),linear-gradient(135deg,#1a1408,#0a0a0a);border:2px solid var(--gold);border-radius:14px;padding:32px 24px;text-align:center;margin-bottom:16px;box-shadow:0 0 40px rgba(255,215,0,.25),0 6px 22px rgba(0,0,0,.6);}
  .tag{display:inline-block;background:var(--gold);color:#0a0a0a;font-size:10px;font-weight:800;letter-spacing:2px;padding:4px 14px;border-radius:999px;margin-bottom:14px;box-shadow:0 0 16px rgba(255,215,0,.7);}
  .header h1{font-size:28px;font-weight:900;letter-spacing:3px;color:var(--gold);text-transform:uppercase;margin-bottom:12px;text-shadow:0 0 10px rgba(255,215,0,.95),0 0 25px rgba(255,199,0,.8),0 0 45px rgba(255,170,0,.6);animation:goldPulse 3s ease-in-out infinite;}
  @keyframes goldPulse{0%,100%{text-shadow:0 0 10px rgba(255,215,0,.95),0 0 25px rgba(255,199,0,.8),0 0 45px rgba(255,170,0,.6);}50%{text-shadow:0 0 15px rgba(255,215,0,1),0 0 35px rgba(255,199,0,.95),0 0 60px rgba(255,170,0,.8);}}
  .line{width:80px;height:3px;background:var(--gold);margin:0 auto 14px;border-radius:2px;box-shadow:0 0 15px var(--gold);}
  .header p{color:var(--gold-light);font-size:14px;opacity:.95;}

  .tabs{display:flex;gap:8px;margin-bottom:16px;flex-wrap:wrap;}
  .tab{display:inline-flex;align-items:center;gap:8px;padding:12px 22px;border-radius:10px;border:2px solid var(--gold);background:var(--bg);color:var(--gold);font-size:14px;font-weight:800;cursor:pointer;transition:.2s;font-family:inherit;letter-spacing:.5px;}
  .tab:hover{background:rgba(255,215,0,.12);}
  .tab.active{background:linear-gradient(135deg,#FFD700,#FF8C00);color:#0a0a0a;border-color:#FFD700;box-shadow:0 0 20px rgba(255,215,0,.5);}
  .tab .cnt{background:rgba(0,0,0,.25);color:inherit;font-size:11px;font-weight:800;padding:2px 8px;border-radius:999px;}
  .tab.active .cnt{background:rgba(0,0,0,.2);}

  .subcats{display:flex;gap:6px;margin-bottom:14px;flex-wrap:wrap;}
  .subcat{padding:8px 16px;border-radius:999px;border:1px solid var(--gold);background:transparent;color:var(--gold);font-size:12px;font-weight:700;cursor:pointer;transition:.15s;font-family:inherit;}
  .subcat:hover{background:rgba(255,215,0,.12);}
  .subcat.active{background:var(--gold);color:#0a0a0a;}

  .discount-banner{
    background:linear-gradient(135deg,rgba(125,255,125,.12),rgba(10,10,10,.9));
    border:3px solid var(--green);border-radius:16px;
    padding:22px 26px;margin-bottom:16px;
    text-align:center;position:relative;
    box-shadow:0 0 40px rgba(125,255,125,.2);
    transition:all .4s;
  }
  .discount-banner.active{
    background:linear-gradient(135deg,rgba(125,255,125,.25),rgba(10,10,10,.9));
    box-shadow:0 0 60px rgba(125,255,125,.5),inset 0 0 30px rgba(125,255,125,.15);
    animation:discountActive 1.5s ease-in-out infinite;
  }
  @keyframes discountActive{
    0%,100%{box-shadow:0 0 60px rgba(125,255,125,.5),inset 0 0 30px rgba(125,255,125,.15);}
    50%{box-shadow:0 0 80px rgba(125,255,125,.8),inset 0 0 40px rgba(125,255,125,.25);}
  }
  .discount-banner::before{
    content:'★ СКИДКА ОТ СУММЫ ★';
    position:absolute;top:-14px;left:50%;transform:translateX(-50%);
    background:#0a0a0a;color:var(--green);
    padding:4px 22px;border:2px solid var(--green);border-radius:999px;
    font-size:12px;font-weight:900;letter-spacing:3px;
    text-shadow:0 0 15px rgba(125,255,125,1);
    white-space:nowrap;box-shadow:0 0 20px rgba(125,255,125,.6);
  }
  .discount-banner h3{
    color:var(--green);font-size:20px;font-weight:900;
    letter-spacing:1.5px;text-transform:uppercase;
    margin-bottom:12px;
    text-shadow:0 0 15px rgba(125,255,125,.7);
  }
  .discount-banner p{
    color:#c8e8c8;font-size:14px;
    margin-bottom:16px;line-height:1.6;
  }
  .discount-banner p b{color:#fff;}

  .progress-wrap{
    max-width:700px;margin:0 auto 16px;
    background:#0a0a0a;border:2px solid var(--green);
    border-radius:999px;height:36px;position:relative;overflow:hidden;
  }
  .progress-fill{
    height:100%;background:linear-gradient(90deg,#3aa03a,#7dff7d,#3aa03a);
    background-size:200% 100%;
    width:0%;transition:width .5s ease-out;
    animation:progressShine 2s linear infinite;
    border-radius:999px;
    box-shadow:0 0 20px rgba(125,255,125,.7);
  }
  @keyframes progressShine{0%{background-position:200% 0;}100%{background-position:-200% 0;}}
  .progress-label{
    position:absolute;inset:0;
    display:flex;align-items:center;justify-content:center;
    color:#fff;font-size:13px;font-weight:900;
    text-shadow:0 1px 3px rgba(0,0,0,.9);
    z-index:2;letter-spacing:.5px;
  }
  .progress-label b{color:var(--gold);font-size:14px;}

  .discount-stats{
    display:grid;grid-template-columns:repeat(3,1fr);
    gap:12px;max-width:800px;margin:0 auto;
  }
  @media(max-width:600px){.discount-stats{grid-template-columns:1fr;}}
  .discount-stat{
    background:rgba(0,0,0,.5);border:1px solid var(--green);
    border-radius:10px;padding:12px;
    display:flex;flex-direction:column;gap:4px;text-align:center;
  }
  .discount-stat .lbl{
    font-size:9px;font-weight:800;text-transform:uppercase;
    letter-spacing:1.2px;color:var(--green);opacity:.8;
  }
  .discount-stat .val{
    font-size:18px;font-weight:900;color:var(--green);
    font-variant-numeric:tabular-nums;
  }

  .cta-block{background:linear-gradient(135deg,rgba(255,215,0,.15),rgba(10,10,10,.9));border:3px solid var(--gold);border-radius:16px;padding:24px 20px;margin-bottom:16px;text-align:center;box-shadow:0 0 40px rgba(255,215,0,.3);position:relative;}
  .cta-block::before{content:'★';position:absolute;top:-18px;left:50%;transform:translateX(-50%);background:#0a0a0a;color:var(--gold);padding:0 18px;font-size:26px;text-shadow:0 0 20px rgba(255,215,0,1);animation:starPulse 1.5s ease-in-out infinite;}
  @keyframes starPulse{0%,100%{transform:translateX(-50%) scale(1);}50%{transform:translateX(-50%) scale(1.2);}}
  .cta-block h2{color:var(--gold);font-size:22px;font-weight:900;letter-spacing:2px;text-transform:uppercase;margin-bottom:10px;text-shadow:0 0 15px rgba(255,215,0,.7);}
  .cta-block p{color:var(--gold-light);font-size:15px;margin-bottom:16px;line-height:1.6;}
  .cta-block p b{color:#fff;}
  .cta-counter{display:inline-block;background:#0a0a0a;border:2px solid var(--gold);border-radius:999px;padding:10px 24px;color:var(--gold);font-size:16px;font-weight:900;letter-spacing:1px;margin-bottom:14px;}
  .cta-counter b{color:#fff;font-size:22px;}
  .cta-buttons{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-top:14px;}
  .btn-big{display:inline-flex;align-items:center;gap:10px;padding:16px 32px;border-radius:999px;border:2px solid var(--gold);background:transparent;color:var(--gold);font-size:16px;font-weight:900;cursor:pointer;transition:.2s;font-family:inherit;letter-spacing:1px;text-transform:uppercase;}
  .btn-big:hover{background:var(--gold);color:#0a0a0a;transform:scale(1.03);}
  .btn-big.primary{background:linear-gradient(135deg,#FFD700,#FF8C00);color:#0a0a0a;border-color:#FFD700;box-shadow:0 0 25px rgba(255,215,0,.6);animation:btnPulse 2s ease-in-out infinite;}
  @keyframes btnPulse{0%,100%{box-shadow:0 0 25px rgba(255,215,0,.6);}50%{box-shadow:0 0 40px rgba(255,215,0,.9),0 0 70px rgba(255,140,0,.5);}}
  .btn-big.primary:hover{transform:scale(1.05);}

  .stats{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px;}
  @media(max-width:800px){.stats{grid-template-columns:repeat(2,1fr);}}
  @media(max-width:500px){.stats{grid-template-columns:1fr;}}
  .stat{background:var(--bg);border:1px solid var(--gold);border-radius:12px;padding:16px;text-align:center;}
  .lbl{font-size:10px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--gold);opacity:.7;margin-bottom:6px;}
  .val{font-size:22px;font-weight:800;color:var(--gold-light);line-height:1.1;}
  .val.sm{font-size:16px;}

  .toolbar{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px;}
  .btn{display:inline-flex;align-items:center;gap:6px;padding:10px 16px;border-radius:9px;border:1px solid var(--gold);background:transparent;color:var(--gold);font-size:13px;font-weight:700;cursor:pointer;transition:.15s;font-family:inherit;letter-spacing:.3px;}
  .btn:hover{background:var(--gold);color:#0a0a0a;}
  .btn.primary{background:var(--gold);color:#0a0a0a;}

  .filter{background:var(--bg);border:1px solid var(--gold);border-radius:14px;padding:16px;margin-bottom:16px;}
  .filter-row{display:grid;grid-template-columns:2fr 1fr;gap:12px;margin-bottom:12px;}
  @media(max-width:700px){.filter-row{grid-template-columns:1fr;}}
  .filter-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;}
  @media(max-width:1000px){.filter-grid{grid-template-columns:repeat(3,1fr);}}
  @media(max-width:700px){.filter-grid{grid-template-columns:1fr 1fr;}}
  @media(max-width:450px){.filter-grid{grid-template-columns:1fr;}}
  .fld{display:flex;flex-direction:column;gap:5px;}
  .fld label{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:1px;color:var(--gold);opacity:.85;}
  .fld input,.fld select{padding:10px 12px;border:1px solid var(--gold);border-radius:9px;font-size:13px;background:var(--bg);color:var(--gold-light);outline:none;font-family:inherit;font-variant-numeric:tabular-nums;width:100%;}
  .fld input::placeholder{color:rgba(212,175,55,.35);}
  .search{width:100%;padding:13px 16px;border:2px solid var(--gold);border-radius:9px;font-size:14px;background:var(--bg);color:var(--gold-light);outline:none;font-family:inherit;font-weight:600;}
  .search::placeholder{color:rgba(212,175,55,.4);}
  .counter{color:var(--gold);font-size:14px;white-space:nowrap;padding:13px 18px;border:1px solid var(--gold);border-radius:9px;background:var(--bg);font-weight:800;display:flex;align-items:center;justify-content:center;}
  .filter-actions{display:flex;gap:8px;margin-top:10px;flex-wrap:wrap;}
  .search-help{font-size:11px;color:var(--muted);margin-top:8px;line-height:1.5;}
  .search-help b{color:var(--gold-light);}

  .global-badge{display:none;align-items:center;gap:8px;margin-bottom:12px;padding:10px 16px;border:1px dashed var(--gold);border-radius:10px;background:rgba(255,215,0,.06);font-size:13px;color:var(--gold-light);}
  .global-badge.show{display:flex;flex-wrap:wrap;}
  .global-badge b{color:var(--gold);}
  .global-badge .btn{margin-left:auto;}

  .table-block{background:var(--bg);border:1px solid var(--gold);border-radius:14px;padding:20px;margin-bottom:16px;position:relative;}
  .block-title{color:var(--gold);font-size:12px;font-weight:800;letter-spacing:2px;text-align:center;margin-bottom:16px;padding-bottom:12px;border-bottom:1px solid var(--border);text-transform:uppercase;text-shadow:0 0 12px rgba(255,215,0,.6);}
  .table-wrap{overflow:auto;max-height:60vh;border-radius:8px;border:1px solid var(--gold);}
  table{width:100%;table-layout:auto;border-collapse:collapse;background:var(--bg);font-size:13px;}
  th,td{padding:11px 10px;text-align:left;border-bottom:1px solid rgba(212,175,55,.2);vertical-align:middle;color:var(--gold);background:transparent;white-space:nowrap;}
  th{position:sticky;top:0;z-index:2;background:var(--bg);color:var(--gold);font-weight:800;text-transform:uppercase;font-size:10px;letter-spacing:1px;border-bottom:1px solid var(--gold);cursor:pointer;user-select:none;}
  th:hover{background:#1a1408;}
  th.sortable::after{content:' ⇅';opacity:.5;margin-left:4px;font-size:9px;}
  th.asc::after{content:' ▲';opacity:1;color:var(--gold-light);}
  th.desc::after{content:' ▼';opacity:1;color:var(--gold-light);}
  th.num,td.num{text-align:right;font-variant-numeric:tabular-nums;}
  th.col-num,td.col-num{width:38px;text-align:center;}
  th.col-star,td.col-star{width:44px;text-align:center;padding:8px 6px;}
  th.col-qty,td.col-qty{width:80px;text-align:center;padding:8px 6px;}
  th.col-star{position:sticky;top:0;background:linear-gradient(180deg,#1a1408,#0a0a0a) !important;}
  th.col-star::before{content:'▼';position:absolute;top:100%;left:50%;transform:translateX(-50%);color:var(--gold);font-size:20px;line-height:1;text-shadow:0 0 12px rgba(255,215,0,1),0 0 24px rgba(255,199,0,.8);animation:arrowBounce 1s ease-in-out infinite;pointer-events:none;}
  @keyframes arrowBounce{0%,100%{transform:translateX(-50%) translateY(0);opacity:1;}50%{transform:translateX(-50%) translateY(6px);opacity:.7;}}
  .select-hint{position:absolute;top:-14px;left:0;background:linear-gradient(135deg,#FFD700,#FF8C00);color:#0a0a0a;font-size:11px;font-weight:900;letter-spacing:1.5px;padding:6px 18px;border-radius:999px;box-shadow:0 0 20px rgba(255,215,0,.7);text-transform:uppercase;animation:hintPulse 1.5s ease-in-out infinite;z-index:5;white-space:nowrap;}
  @keyframes hintPulse{0%,100%{box-shadow:0 0 20px rgba(255,215,0,.7);transform:scale(1);}50%{box-shadow:0 0 35px rgba(255,215,0,1),0 0 60px rgba(255,140,0,.6);transform:scale(1.05);}}
  tbody tr{transition:background .15s;}
  tbody tr:hover{background:#1a1408;box-shadow:inset 3px 0 0 var(--gold-light),inset -3px 0 0 var(--gold-light);}
  tbody tr.picked{background:linear-gradient(90deg,rgba(255,215,0,.15),rgba(255,215,0,.04));box-shadow:inset 4px 0 0 var(--gold);}
  tbody tr.discount-active{background:linear-gradient(90deg,rgba(125,255,125,.15),rgba(255,215,0,.04));box-shadow:inset 4px 0 0 var(--green);}
  td.price{font-weight:800;color:var(--gold-light);font-size:14px;}
  td.price.discount{color:var(--green);text-shadow:0 0 10px rgba(125,255,125,.5);}
  td.price.request{color:var(--muted);font-style:italic;font-weight:600;}
  td.article{font-family:'Courier New',monospace;font-size:12px;color:var(--gold-light);}
  td.dims{font-weight:700;color:var(--gold-light);font-size:13px;letter-spacing:.3px;}
  td b{color:#fff;}
  td.col-qty input.qty{width:70px;padding:6px 8px;border:1px solid var(--border);border-radius:6px;background:#0a0a0a;color:var(--gold-light);font-size:14px;font-weight:800;text-align:center;font-family:inherit;outline:none;font-variant-numeric:tabular-nums;transition:.2s;}
  td.col-qty input.qty:focus{border-color:var(--gold);box-shadow:0 0 0 3px rgba(255,215,0,.2);}
  td.col-qty input.qty:disabled{opacity:.25;cursor:not-allowed;}
  tbody tr.picked td.col-qty input.qty{border-color:var(--gold);color:var(--gold-light);box-shadow:0 0 8px rgba(255,215,0,.4);}
  .badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:800;text-transform:uppercase;background:rgba(212,175,55,.15);color:var(--gold-light);border:1px solid rgba(212,175,55,.5);letter-spacing:.3px;white-space:nowrap;}
  .badge.many{background:rgba(57,255,20,.08);color:var(--ok);border-color:rgba(57,255,20,.3);}
  .badge.zero{background:rgba(255,107,107,.12);color:var(--bad);border-color:rgba(255,107,107,.4);}
  .badge.req{background:rgba(255,215,0,.1);color:var(--gold-light);border-color:rgba(255,215,0,.4);}
  .star{cursor:pointer;font-size:22px;color:rgba(212,175,55,.35);transition:all .2s;user-select:none;text-align:center;display:inline-block;}
  .star:hover{color:var(--gold);transform:scale(1.3);}
  .star.on{color:var(--gold-light);text-shadow:0 0 12px var(--gold-light),0 0 24px rgba(255,215,0,.5);}
  .footnote{display:flex;flex-wrap:wrap;gap:20px;margin-top:14px;padding-top:12px;border-top:1px solid var(--gold);}
  .fn{color:var(--gold);font-size:12px;position:relative;padding-left:14px;opacity:.9;}
  .fn::before{content:"◆";position:absolute;left:0;color:var(--gold);font-size:8px;top:4px;}

  mark.hl{background:linear-gradient(135deg,#FFD700,#FF8C00);color:#0a0a0a;border-radius:3px;padding:0 2px;font-weight:800;}

  .cta{text-align:center;background:var(--bg);border:1px solid var(--gold);border-radius:14px;padding:28px 20px;margin-top:16px;}
  .cta-text{font-size:16px;font-weight:600;color:var(--gold);margin-bottom:16px;}
  .cta-btn{display:inline-block;background:var(--gold);color:#0a0a0a;text-decoration:none;padding:16px 40px;font-size:20px;font-weight:800;letter-spacing:1px;border-radius:999px;transition:.25s;margin:0 6px;}
  .cta-btn:hover{background:var(--gold-light);transform:scale(1.03);}
  .cta-mail{display:inline-block;color:var(--gold);text-decoration:none;padding:16px 30px;font-size:16px;font-weight:700;border:1px solid var(--gold);border-radius:999px;transition:.25s;margin:0 6px;}
  .cta-mail:hover{background:var(--gold);color:#0a0a0a;}
  .manager{margin-top:16px;font-size:13px;color:var(--muted);}
  .seo{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0;}

  .sticky-bar{position:fixed;left:0;right:0;bottom:0;background:linear-gradient(180deg,rgba(10,10,10,.95),#0a0a0a);border-top:3px solid var(--gold);box-shadow:0 -10px 40px rgba(255,215,0,.25),0 -4px 15px rgba(0,0,0,.8);padding:14px 20px;z-index:1000;transform:translateY(110%);transition:transform .35s cubic-bezier(.34,1.56,.64,1);backdrop-filter:blur(8px);}
  .sticky-bar.show{transform:translateY(0);}
  .sticky-bar.discount-active{border-top-color:var(--green);box-shadow:0 -10px 40px rgba(125,255,125,.4),0 -4px 15px rgba(0,0,0,.8);}
  .sticky-bar::before{content:'';position:absolute;top:-3px;left:0;right:0;height:3px;background:linear-gradient(90deg,transparent,var(--gold),var(--accent),var(--gold),transparent);background-size:200% 100%;animation:barShine 3s linear infinite;}
  .sticky-bar.discount-active::before{background:linear-gradient(90deg,transparent,var(--green),#3aa03a,var(--green),transparent);background-size:200% 100%;}
  @keyframes barShine{0%{background-position:200% 0;}100%{background-position:-200% 0;}}
  .sticky-inner{max-width:1600px;margin:0 auto;display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
  .sticky-info{display:flex;gap:16px;align-items:center;flex-wrap:wrap;flex:1;}
  .sticky-stat{display:flex;flex-direction:column;gap:2px;padding:6px 14px;border-left:2px solid var(--gold);}
  .sticky-stat:first-child{border-left:none;padding-left:0;}
  .sticky-stat .lbl{font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:1.2px;color:var(--gold);opacity:.7;margin:0;}
  .sticky-stat .val{font-size:18px;font-weight:900;color:var(--gold-light);line-height:1;font-variant-numeric:tabular-nums;}
  .sticky-stat .val.big{font-size:26px;color:var(--gold);text-shadow:0 0 15px rgba(255,215,0,.7);animation:totalPulse 1.5s ease-in-out infinite;}
  @keyframes totalPulse{0%,100%{text-shadow:0 0 15px rgba(255,215,0,.7);}50%{text-shadow:0 0 25px rgba(255,215,0,1),0 0 40px rgba(255,140,0,.6);}}
  .sticky-bar.discount-active .sticky-stat{border-color:var(--green);}
  .sticky-bar.discount-active .sticky-stat .lbl{color:var(--green);}
  .sticky-bar.discount-active .sticky-stat .val{color:#c8ffb8;}
  .sticky-bar.discount-active .sticky-stat .val.big{color:var(--green);text-shadow:0 0 15px rgba(125,255,125,.8);animation:totalPulseGreen 1.5s ease-in-out infinite;}
  @keyframes totalPulseGreen{0%,100%{text-shadow:0 0 15px rgba(125,255,125,.8);}50%{text-shadow:0 0 25px rgba(125,255,125,1),0 0 40px rgba(58,160,58,.8);}}
  .sticky-actions{display:flex;gap:10px;flex-wrap:wrap;}
  .sticky-btn{display:inline-flex;align-items:center;gap:6px;padding:12px 22px;border-radius:999px;border:2px solid var(--gold);background:transparent;color:var(--gold);font-size:14px;font-weight:900;cursor:pointer;transition:.2s;font-family:inherit;letter-spacing:.5px;text-transform:uppercase;white-space:nowrap;}
  .sticky-btn:hover{background:var(--gold);color:#0a0a0a;transform:scale(1.03);}
  .sticky-btn.primary{background:linear-gradient(135deg,#FFD700,#FF8C00);color:#0a0a0a;border-color:#FFD700;box-shadow:0 0 20px rgba(255,215,0,.5);}
  .sticky-btn.primary:hover{transform:scale(1.05);box-shadow:0 0 30px rgba(255,215,0,.8);}
  .sticky-bar.discount-active .sticky-btn.primary{background:linear-gradient(135deg,#7dff7d,#3aa03a);color:#0a0a0a;border-color:#7dff7d;box-shadow:0 0 25px rgba(125,255,125,.7);}
  .sticky-btn.clear{border-color:rgba(255,138,122,.5);color:var(--bad);}
  .sticky-btn.clear:hover{background:var(--bad);color:#0a0a0a;border-color:var(--bad);}

  @media(max-width:900px){
    .sticky-inner{flex-direction:column;gap:10px;}
    .sticky-info{justify-content:center;width:100%;}
    .sticky-actions{width:100%;justify-content:center;}
    .sticky-stat{padding:4px 10px;}
    .sticky-stat .val{font-size:15px;}
    .sticky-stat .val.big{font-size:20px;}
    .sticky-btn{padding:10px 16px;font-size:12px;}
  }
  @media(max-width:500px){
    body{padding-bottom:220px;}
    .sticky-info{gap:8px;}
    .sticky-stat{padding:2px 8px;}
    .sticky-stat .val{font-size:13px;}
    .sticky-stat .val.big{font-size:17px;}
    .sticky-stat .lbl{font-size:8px;}
  }

  .wrap ::-webkit-scrollbar{width:14px;height:14px;}
  .wrap ::-webkit-scrollbar-track{background:#050505;border:1px solid #2a2210;border-radius:9px;}
  .wrap ::-webkit-scrollbar-thumb{background:linear-gradient(180deg,#FFE55C,#FFD700,#FF8C00);border-radius:9px;border:1px solid #FFD700;box-shadow:0 0 10px rgba(255,215,0,.9);}

  @media print{
    body{background:#fff;color:#000;padding:0;}
    .header{background:#000 !important;color:#FFD700 !important;-webkit-print-color-adjust:exact;print-color-adjust:exact;}
    .header h1{color:#FFD700 !important;text-shadow:none !important;animation:none !important;}
    .tag{background:#FFD700 !important;color:#000 !important;}
    .line{background:#FFD700 !important;}
    .stats,.table-block,.cta,.cta-block,.discount-banner{background:#fff !important;border-color:#666 !important;box-shadow:none !important;}
    .toolbar,.filter,.select-hint,th.col-star::before,.banner,.ticker,.ad-strip,.sticky-bar,.tabs,.global-badge,.subcats{display:none !important;}
    .block-title{color:#000 !important;border-color:#666 !important;text-shadow:none !important;}
    .val{color:#000 !important;}
    .cta-block h2,.cta-block p,.discount-banner h3,.discount-banner p{color:#000 !important;}
    .cta-counter{background:#fff !important;color:#000 !important;border-color:#666 !important;}
    th{background:#000 !important;color:#FFD700 !important;-webkit-print-color-adjust:exact;print-color-adjust:exact;}
    td{color:#000 !important;border-color:#ccc !important;}
    td.price,td.dims{color:#000 !important;}
    .cta-text{color:#000 !important;}
    .cta-btn{background:#000 !important;color:#fff !important;}
    td.col-qty input.qty{background:#fff !important;color:#000 !important;border-color:#ccc !important;}
    .progress-fill{background:#3aa03a !important;-webkit-print-color-adjust:exact;print-color-adjust:exact;}
    mark.hl{background:#FFD700 !important;color:#000 !important;-webkit-print-color-adjust:exact;print-color-adjust:exact;}
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="wrap" id="app"&gt;&lt;/div&gt;

&lt;div class="sticky-bar" id="stickyBar"&gt;
  &lt;div class="sticky-inner"&gt;
    &lt;div class="sticky-info"&gt;
      &lt;div class="sticky-stat"&gt;
        &lt;div class="lbl"&gt;Позиций&lt;/div&gt;
        &lt;div class="val" id="barCount"&gt;0&lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="sticky-stat"&gt;
        &lt;div class="lbl"&gt;Всего шт&lt;/div&gt;
        &lt;div class="val" id="barQty"&gt;0&lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="sticky-stat"&gt;
        &lt;div class="lbl"&gt;Сумма без скидки&lt;/div&gt;
        &lt;div class="val" id="barBase"&gt;0 ₽&lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="sticky-stat"&gt;
        &lt;div class="lbl" id="barDiscountLabel"&gt;Скидка&lt;/div&gt;
        &lt;div class="val" id="barDiscount"&gt;0 ₽&lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="sticky-stat"&gt;
        &lt;div class="lbl"&gt;Итого с НДС 22%&lt;/div&gt;
        &lt;div class="val big" id="barTotal"&gt;0 ₽&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="sticky-actions"&gt;
      &lt;button class="sticky-btn primary" onclick="downloadRequest()"&gt;⬇ Скачать запрос КП&lt;/button&gt;
      &lt;button class="sticky-btn" onclick="sendByEmail()"&gt;✉ На e-mail&lt;/button&gt;
      &lt;button class="sticky-btn clear" onclick="clearPicked()"&gt;✕ Очистить&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;script&gt;
/* ============================================================
   АРСЕНАЛ-ДЕТАЛЬ · Полный каталог
   - Стропы, крюки, КЧ ХЛ, канаты, колёса, ЗКЗ, барабаны
   - Сквозной поиск по всем разделам
   - Скидка от суммы ≥ 50 000 ₽ → 10%
   ============================================================ */

var PROJECT = {
  id: 'arsenal-full',
  title: 'Каталог продукции',
  subtitle: 'Стропы · Крюки · Канаты · Колёса · Фланцы · Барабаны',
  vat: 22,
  discountThreshold: 50000,
  discountPercent: 10,

  banner: {
    tag: 'РЕКЛАМНЫЕ ПЛОЩАДИ',
    title: 'ЗДЕСЬ МОЖЕТ БЫТЬ&lt;br&gt;ВАША РЕКЛАМА',
    phone: '8 902 873-36-90 · МАКС',
    note: 'Позвоните, а лучше пишите в МАКС'
  },

  ads: [
    {tag:'Акция', text:'Скидка от 50 000 ₽ · по всем разделам', cta:'Перейти →', href:'#'},
    {tag:'Склад', text:'Стропы · Крюки · Канаты · Колёса', cta:'Перейти →', href:'#'}
  ],

  sections: {
    stroPs: {
      label: 'Стропы канатные',
      icon: '?',
      title: 'Стропы канатные',
      subtitle: 'УСК1 · УСК2 · 1СК · 2СК · 4СК · ГОСТ 25573-82',
      tag: 'ПРАЙС-ЛИСТ · 8 ПОЗИЦИЙ',
      columns: [
        {key:'num',    label:'№',              type:'num',  cls:'col-num'},
        {key:'name',   label:'Марка',          type:'text'},
        {key:'type',   label:'Тип',            type:'text'},
        {key:'capacity', label:'Г/п, т',       type:'num',  sortable:true},
        {key:'length', label:'Длина, м',       type:'num',  sortable:true},
        {key:'construction', label:'Конструкция', type:'text'},
        {key:'diam',   label:'Ø каната, мм',   type:'num',  sortable:true},
        {key:'weight', label:'Масса, кг',      type:'num',  sortable:true},
        {key:'stock',  label:'Наличие, шт',    type:'badge',sortable:true},
        {key:'price',  label:'Цена с НДС, ₽',  type:'price'},
        {key:'term',   label:'Сроки',          type:'text'}
      ],
      quickFilters: [
        {label:'Со склада', field:'term', value:'Со склада'},
        {label:'Под заказ', field:'term', value:'Под заказ'},
        {label:'УСК1',     field:'type', value:'УСК1'},
        {label:'УСК2',     field:'type', value:'УСК2'},
        {label:'1СК',      field:'type', value:'1СК'}
      ],
      data: [
        {num:1, name:'Строп УСК1 (СКП) 1,0т', type:'УСК1', capacity:1.0, length:2.0, construction:'Заплетка', diam:11, weight:1.8, stock:25, price:890, term:'Со склада'},
        {num:2, name:'Строп УСК1 (СКП) 2,0т', type:'УСК1', capacity:2.0, length:2.0, construction:'Опрессовка', diam:15, weight:3.2, stock:18, price:1450, term:'Со склада'},
        {num:3, name:'Строп УСК2 (СКК) 2,0т', type:'УСК2', capacity:2.0, length:2.5, construction:'Заплетка', diam:11.5, weight:4.2, stock:12, price:2720, term:'Со склада'},
        {num:4, name:'Строп УСК2 (СКК) 4,0т', type:'УСК2', capacity:4.0, length:3.0, construction:'Опрессовка', diam:15, weight:7.8, stock:8, price:4600, term:'Под заказ'},
        {num:5, name:'Строп 1СК 2,5т', type:'1СК', capacity:2.5, length:3.0, construction:'Заплетка', diam:16.5, weight:5.5, stock:15, price:2100, term:'Со склада'},
        {num:6, name:'Строп 1СК 5,0т', type:'1СК', capacity:5.0, length:4.0, construction:'Опрессовка', diam:24, weight:12.3, stock:6, price:5400, term:'Под заказ'},
        {num:7, name:'Строп 2СК 3,2т', type:'2СК', capacity:3.2, length:3.0, construction:'Заплетка', diam:16.5, weight:10.8, stock:5, price:7840, term:'Под заказ'},
        {num:8, name:'Строп 4СК 8,0т', type:'4СК', capacity:8.0, length:3.5, construction:'Опрессовка', diam:19.5, weight:43.0, stock:3, price:22286, term:'Под заказ'}
      ]
    },

    hooks: {
      label: 'Крюки крановые',
      icon: '?',
      title: 'Крюки крановые',
      subtitle: 'ГОСТ 6627-74 · исполнение А и Б',
      tag: 'ПРАЙС-ЛИСТ · 29 ПОЗИЦИЙ',
      columns: [
        {key:'num',    label:'№',              type:'num',  cls:'col-num'},
        {key:'name',   label:'Марка',          type:'text'},
        {key:'capacity', label:'Г/п, т',       type:'num',  sortable:true},
        {key:'exec',   label:'Исполнение',     type:'text'},
        {key:'shank',  label:'Хвостовик',      type:'text'},
        {key:'gost',   label:'ГОСТ',           type:'text'},
        {key:'stock',  label:'Наличие, шт',    type:'badge',sortable:true},
        {key:'price',  label:'Цена с НДС, ₽',  type:'price'},
        {key:'term',   label:'Сроки',          type:'text'}
      ],
      quickFilters: [
        {label:'Со склада', field:'term', value:'Со склада'},
        {label:'Под заказ', field:'term', value:'Под заказ'},
        {label:'Исп. А',   field:'exec', value:'А'},
        {label:'Исп. Б',   field:'exec', value:'Б'},
        {label:'до 5 т',   field:'capMax', value:5},
        {label:'от 10 т',  field:'capMin', value:10}
      ],
      data: [
        {num:1,  name:'Крюк крановый 0,2 т 3А',  capacity:0.2,  exec:'А', shank:'М14',   gost:'6627-74', stock:0, price:5528,   term:'Под заказ'},
        {num:2,  name:'Крюк крановый 0,4 т 3Б',  capacity:0.4,  exec:'Б', shank:'М14',   gost:'6627-74', stock:0, price:5528,   term:'Под заказ'},
        {num:3,  name:'Крюк крановый 0,6 т 4А',  capacity:0.6,  exec:'А', shank:'М16',   gost:'6627-74', stock:0, price:5528,   term:'Под заказ'},
        {num:4,  name:'Крюк крановый 0,8 т 4Б',  capacity:0.8,  exec:'Б', shank:'М16',   gost:'6627-74', stock:0, price:5528,   term:'Под заказ'},
        {num:5,  name:'Крюк крановый 0,8 т 5А',  capacity:0.8,  exec:'А', shank:'М16',   gost:'6627-74', stock:0, price:5528,   term:'Под заказ'},
        {num:6,  name:'Крюк крановый 1,0 т 7А',  capacity:1.0,  exec:'А', shank:'М20',   gost:'6627-74', stock:0, price:5677,   term:'Под заказ'},
        {num:7,  name:'Крюк крановый 1,0 т 7Б',  capacity:1.0,  exec:'Б', shank:'М20',   gost:'6627-74', stock:0, price:5677,   term:'Под заказ'},
        {num:8,  name:'Крюк крановый 1,25 т 8А', capacity:1.25, exec:'А', shank:'М16',   gost:'6627-74', stock:0, price:4332,   term:'Под заказ'},
        {num:9,  name:'Крюк крановый 1,5 т 9А',  capacity:1.5,  exec:'А', shank:'М20',   gost:'6627-74', stock:0, price:4332,   term:'Под заказ'},
        {num:10, name:'Крюк крановый 1,5 т 9Б',  capacity:1.5,  exec:'Б', shank:'М20',   gost:'6627-74', stock:0, price:4332,   term:'Под заказ'},
        {num:11, name:'Крюк крановый 10,0 т 16А',capacity:10.0, exec:'А', shank:'М56',   gost:'6627-74', stock:0, price:18226,  term:'Под заказ'},
        {num:12, name:'Крюк крановый 10,0 т 17А',capacity:10.0, exec:'А', shank:'М64',   gost:'6627-74', stock:0, price:18226,  term:'Под заказ'},
        {num:13, name:'Крюк крановый 10,0 т 17Б',capacity:10.0, exec:'Б', shank:'М64',   gost:'6627-74', stock:0, price:20617,  term:'Под заказ'},
        {num:14, name:'Крюк крановый 12,5 т 18А',capacity:12.5, exec:'А', shank:'70×10', gost:'6627-74', stock:0, price:22409,  term:'Под заказ'},
        {num:15, name:'Крюк крановый 15,0 т 19А',capacity:15.0, exec:'А', shank:'80×10', gost:'6627-74', stock:0, price:25398,  term:'Под заказ'},
        {num:16, name:'Крюк крановый 15,0 т 19Б',capacity:15.0, exec:'Б', shank:'80×10', gost:'6627-74', stock:0, price:2988,   term:'Под заказ'},
        {num:17, name:'Крюк крановый 2,0 т 10А', capacity:2.0,  exec:'А', shank:'М30',   gost:'6627-74', stock:0, price:4481,   term:'Под заказ'},
        {num:18, name:'Крюк крановый 2,0 т 10Б', capacity:2.0,  exec:'Б', shank:'М30',   gost:'6627-74', stock:0, price:4481,   term:'Под заказ'},
        {num:19, name:'Крюк крановый 2,0 т 11А', capacity:2.0,  exec:'А', shank:'М33',   gost:'6627-74', stock:0, price:6872,   term:'Под заказ'},
        {num:20, name:'Крюк крановый 25,0 т 20А',capacity:25.0, exec:'А', shank:'90×12', gost:'6627-74', stock:0, price:32121,  term:'Под заказ'},
        {num:21, name:'Крюк крановый 25,0 т 20Б',capacity:25.0, exec:'Б', shank:'90×12', gost:'6627-74', stock:0, price:34362,  term:'Под заказ'},
        {num:22, name:'Крюк крановый 3,0 т 12А', capacity:3.0,  exec:'А', shank:'М36',   gost:'6627-74', stock:0, price:6872,   term:'Под заказ'},
        {num:23, name:'Крюк крановый 3,0 т 12Б', capacity:3.0,  exec:'Б', shank:'М36',   gost:'6627-74', stock:0, price:6872,   term:'Под заказ'},
        {num:24, name:'Крюк крановый 40,0 т 22А',capacity:40.0, exec:'А', shank:'110×12',gost:'6627-74', stock:0, price:71712,  term:'Под заказ'},
        {num:25, name:'Крюк крановый 40,0 т 22Б',capacity:40.0, exec:'Б', shank:'110×12',gost:'6627-74', stock:0, price:71712,  term:'Под заказ'},
        {num:26, name:'Крюк крановый 40,0 т 24А',capacity:40.0, exec:'А', shank:'110×12',gost:'6627-74', stock:0, price:146411, term:'Под заказ'},
        {num:27, name:'Крюк крановый 5,0 т 13А', capacity:5.0,  exec:'А', shank:'М42',   gost:'6627-74', stock:0, price:11952,  term:'Под заказ'},
        {num:28, name:'Крюк крановый 5,0 т 14А', capacity:5.0,  exec:'А', shank:'М48',   gost:'6627-74', stock:0, price:11952,  term:'Под заказ'},
        {num:29, name:'Крюк крановый 5,0 т 14Б', capacity:5.0,  exec:'Б', shank:'М48',   gost:'6627-74', stock:0, price:14043,  term:'Под заказ'}
      ]
    },

    hooksCh: {
      label: 'Крюки КЧ ХЛ',
      icon: '⚓',
      title: 'Крюки для канатных строп КЧ ХЛ',
      subtitle: 'Крюк чалочный холодноштампованный · для строп УСК/СКП/СКК',
      tag: 'ПРАЙС-ЛИСТ · 11 ПОЗИЦИЙ',
      columns: [
        {key:'num',    label:'№',              type:'num',  cls:'col-num'},
        {key:'name',   label:'Марка',          type:'text'},
        {key:'capacity', label:'Г/п, т',       type:'num',  sortable:true},
        {key:'type',   label:'Тип',            type:'text'},
        {key:'stock',  label:'Наличие, шт',    type:'badge',sortable:true},
        {key:'price',  label:'Цена с НДС, ₽',  type:'price'},
        {key:'term',   label:'Сроки',          type:'text'}
      ],
      quickFilters: [
        {label:'Со склада', field:'term', value:'Со склада'},
        {label:'Под заказ', field:'term', value:'Под заказ'},
        {label:'до 2,5 т', field:'capMax', value:2.5},
        {label:'от 5 т',   field:'capMin', value:5}
      ],
      data: [
        {num:1,  name:'Крюк КЧ ХЛ 1,0т',  capacity:1.0,  type:'КЧ ХЛ', stock:12, price:720,  term:'Со склада'},
        {num:2,  name:'Крюк КЧ ХЛ 1,6т',  capacity:1.6,  type:'КЧ ХЛ', stock:10, price:890,  term:'Со склада'},
        {num:3,  name:'Крюк КЧ ХЛ 2,0т',  capacity:2.0,  type:'КЧ ХЛ', stock:8,  price:1050, term:'Со склада'},
        {num:4,  name:'Крюк КЧ ХЛ 2,5т',  capacity:2.5,  type:'КЧ ХЛ', stock:6,  price:1290, term:'Со склада'},
        {num:5,  name:'Крюк КЧ ХЛ 3,2т',  capacity:3.2,  type:'КЧ ХЛ', stock:5,  price:1590, term:'Под заказ'},
        {num:6,  name:'Крюк КЧ ХЛ 4,0т',  capacity:4.0,  type:'КЧ ХЛ', stock:4,  price:1980, term:'Под заказ'},
        {num:7,  name:'Крюк КЧ ХЛ 5,0т',  capacity:5.0,  type:'КЧ ХЛ', stock:3,  price:2450, term:'Под заказ'},
        {num:8,  name:'Крюк КЧ ХЛ 6,3т',  capacity:6.3,  type:'КЧ ХЛ', stock:2,  price:3120, term:'Под заказ'},
        {num:9,  name:'Крюк КЧ ХЛ 8,0т',  capacity:8.0,  type:'КЧ ХЛ', stock:2,  price:4380, term:'Под заказ'},
        {num:10, name:'Крюк КЧ ХЛ 10,0т', capacity:10.0, type:'КЧ ХЛ', stock:1,  price:5790, term:'Под заказ'},
        {num:11, name:'Крюк КЧ ХЛ 12,5т', capacity:12.5, type:'КЧ ХЛ', stock:1,  price:7450, term:'Под заказ'}
      ]
    },

    cables: {
      label: 'Канаты стальные',
      icon: '?',
      title: 'Канаты стальные ГОСТ 2688-80',
      subtitle: 'Двойной свивки · тип ЛК-Р · Ø 4,1…39,5 мм',
      tag: 'ПРАЙС-ЛИСТ · 28 ПОЗИЦИЙ',
      columns: [
        {key:'num',    label:'№',              type:'num',  cls:'col-num'},
        {key:'name',   label:'Марка',          type:'text'},
        {key:'diam',   label:'Ø, мм',          type:'num',  sortable:true},
        {key:'force',  label:'Разрывное усилие, Н', type:'num', sortable:true},
        {key:'gost',   label:'ГОСТ',           type:'text'},
        {key:'stock',  label:'Наличие, м',     type:'badge',sortable:true},
        {key:'price',  label:'Цена с НДС, ₽/м',type:'price'},
        {key:'term',   label:'Сроки',          type:'text'}
      ],
      quickFilters: [
        {label:'Со склада', field:'term', value:'Со склада'},
        {label:'Под заказ', field:'term', value:'Под заказ'},
        {label:'до 10 мм',  field:'diamMax', value:10},
        {label:'от 20 мм',  field:'diamMin', value:20}
      ],
      data: [
        {num:1,  name:'Канат стальной 4,1мм',  diam:4.1,  force:11550,  gost:'2688-80', stock:500, price:38,   term:'Со склада'},
        {num:2,  name:'Канат стальной 4,8мм',  diam:4.8,  force:15200,  gost:'2688-80', stock:500, price:52,   term:'Со склада'},
        {num:3,  name:'Канат стальной 5,1мм',  diam:5.1,  force:17200,  gost:'2688-80', stock:400, price:59,   term:'Со склада'},
        {num:4,  name:'Канат стальной 5,6мм',  diam:5.6,  force:20950,  gost:'2688-80', stock:400, price:71,   term:'Со склада'},
        {num:5,  name:'Канат стальной 6,2мм',  diam:6.2,  force:25500,  gost:'2688-80', stock:350, price:86,   term:'Со склада'},
        {num:6,  name:'Канат стальной 6,9мм',  diam:6.9,  force:31800,  gost:'2688-80', stock:350, price:106,  term:'Со склада'},
        {num:7,  name:'Канат стальной 7,6мм',  diam:7.6,  force:38000,  gost:'2688-80', stock:300, price:129,  term:'Со склада'},
        {num:8,  name:'Канат стальной 8,3мм',  diam:8.3,  force:46100,  gost:'2688-80', stock:300, price:154,  term:'Со склада'},
        {num:9,  name:'Канат стальной 9,1мм',  diam:9.1,  force:55000,  gost:'2688-80', stock:250, price:185,  term:'Со склада'},
        {num:10, name:'Канат стальной 9,6мм',  diam:9.6,  force:64650,  gost:'2688-80', stock:250, price:206,  term:'Со склада'},
        {num:11, name:'Канат стальной 11,0мм', diam:11.0, force:83200,  gost:'2688-80', stock:200, price:270,  term:'Со склада'},
        {num:12, name:'Канат стальной 12,0мм', diam:12.0, force:95000,  gost:'2688-80', stock:200, price:321,  term:'Со склада'},
        {num:13, name:'Канат стальной 13,0мм', diam:13.0, force:107500, gost:'2688-80', stock:180, price:377,  term:'Под заказ'},
        {num:14, name:'Канат стальной 14,0мм', diam:14.0, force:131000, gost:'2688-80', stock:150, price:437,  term:'Под заказ'},
        {num:15, name:'Канат стальной 15,0мм', diam:15.0, force:152000, gost:'2688-80', stock:150, price:502,  term:'Под заказ'},
        {num:16, name:'Канат стальной 16,5мм', diam:16.5, force:184500, gost:'2688-80', stock:120, price:607,  term:'Под заказ'},
        {num:17, name:'Канат стальной 18,0мм', diam:18.0, force:220000, gost:'2688-80', stock:100, price:723,  term:'Под заказ'},
        {num:18, name:'Канат стальной 19,5мм', diam:19.5, force:253000, gost:'2688-80', stock:80,  price:848,  term:'Под заказ'},
        {num:19, name:'Канат стальной 21,0мм', diam:21.0, force:294500, gost:'2688-80', stock:80,  price:983,  term:'Под заказ'},
        {num:20, name:'Канат стальной 22,5мм', diam:22.5, force:333000, gost:'2688-80', stock:60,  price:1129, term:'Под заказ'},
        {num:21, name:'Канат стальной 24,0мм', diam:24.0, force:380000, gost:'2688-80', stock:60,  price:1285, term:'Под заказ'},
        {num:22, name:'Канат стальной 25,5мм', diam:25.5, force:430000, gost:'2688-80', stock:50,  price:1450, term:'Под заказ'},
        {num:23, name:'Канат стальной 27,0мм', diam:27.0, force:483500, gost:'2688-80', stock:40,  price:1627, term:'Под заказ'},
        {num:24, name:'Канат стальной 28,0мм', diam:28.0, force:525000, gost:'2688-80', stock:40,  price:1750, term:'Под заказ'},
        {num:25, name:'Канат стальной 30,5мм', diam:30.5, force:629000, gost:'2688-80', stock:30,  price:2077, term:'Под заказ'},
        {num:26, name:'Канат стальной 32,0мм', diam:32.0, force:693000, gost:'2688-80', stock:30,  price:2285, term:'Под заказ'},
        {num:27, name:'Канат стальной 33,5мм', diam:33.5, force:760500, gost:'2688-80', stock:20,  price:2504, term:'Под заказ'},
        {num:28, name:'Канат стальной 39,5мм', diam:39.5, force:1030000,gost:'2688-80', stock:15,  price:3482, term:'Под заказ'}
      ]
    },

    wheels: {
      label: 'Колёса крановые',
      icon: '⚙️',
      title: 'Колёса крановые К2Р',
      subtitle: 'ГОСТ 28648-90 · D 200…1000 мм',
      tag: 'ПРАЙС-ЛИСТ · 22 ПОЗИЦИИ',
      columns: [
        {key:'num',    label:'№',              type:'num',  cls:'col-num'},
        {key:'name',   label:'Марка',          type:'text'},
        {key:'D',      label:'D, мм',          type:'num',  sortable:true},
        {key:'D1',     label:'D1, мм',         type:'num',  sortable:true},
        {key:'B',      label:'B, мм',          type:'num',  sortable:true},
        {key:'B1',     label:'B1, мм',         type:'num',  sortable:true},
        {key:'L',      label:'L, мм',          type:'text', sortable:false},
        {key:'weight', label:'Вес, кг',        type:'num',  sortable:true},
        {key:'stock',  label:'Наличие, шт',    type:'badge',sortable:true},
        {key:'price',  label:'Цена с НДС, ₽',  type:'price'},
        {key:'term',   label:'Сроки',          type:'text'}
      ],
      quickFilters: [
        {label:'Со склада', field:'term', value:'Со склада'},
        {label:'Под заказ', field:'term', value:'Под заказ'},
        {label:'D до 500',  field:'dMax', value:500},
        {label:'D от 710',  field:'dMin', value:710}
      ],
      data: [
        {num:1,  name:'Колесо крановое К2Р-200х60',  D:200,  D1:230,  B:60,  B1:90,  L:'80',     weight:15,  stock:6, price:13500,  term:'Со склада'},
        {num:2,  name:'Колесо крановое К2Р-250х70',  D:250,  D1:290,  B:70,  B1:110, L:'110',    weight:30,  stock:5, price:22000,  term:'Со склада'},
        {num:3,  name:'Колесо крановое К2Р-320х70',  D:320,  D1:360,  B:70,  B1:110, L:'120',    weight:45,  stock:4, price:31500,  term:'Со склада'},
        {num:4,  name:'Колесо крановое К2Р-320х80',  D:320,  D1:360,  B:80,  B1:120, L:'120',    weight:50,  stock:4, price:31500,  term:'Со склада'},
        {num:5,  name:'Колесо крановое К2Р-400х80',  D:400,  D1:450,  B:80,  B1:130, L:'120',    weight:80,  stock:3, price:42000,  term:'Со склада'},
        {num:6,  name:'Колесо крановое К2Р-400х90',  D:400,  D1:450,  B:90,  B1:140, L:'120',    weight:80,  stock:3, price:42000,  term:'Со склада'},
        {num:7,  name:'Колесо крановое К2Р-400х100', D:400,  D1:450,  B:100, B1:150, L:'130',    weight:90,  stock:2, price:42000,  term:'Со склада'},
        {num:8,  name:'Колесо крановое К2Р-500х90',  D:500,  D1:550,  B:90,  B1:150, L:'135',    weight:145, stock:2, price:62000,  term:'Под заказ'},
        {num:9,  name:'Колесо крановое К2Р-500х100', D:500,  D1:550,  B:100, B1:150, L:'150',    weight:145, stock:2, price:62000,  term:'Под заказ'},
        {num:10, name:'Колесо крановое К2Р-630х90',  D:630,  D1:680,  B:90,  B1:140, L:'150',    weight:220, stock:1, price:130000, term:'Под заказ'},
        {num:11, name:'Колесо крановое К2Р-630х100', D:630,  D1:680,  B:100, B1:150, L:'150',    weight:250, stock:1, price:130000, term:'Под заказ'},
        {num:12, name:'Колесо крановое К2Р-710х100', D:710,  D1:770,  B:100, B1:150, L:'150–160',weight:300, stock:1, price:128000, term:'Под заказ'},
        {num:13, name:'Колесо крановое К2Р-710х130', D:710,  D1:770,  B:130, B1:180, L:'160–190',weight:380, stock:1, price:148000, term:'Под заказ'},
        {num:14, name:'Колесо крановое К2Р-710х150', D:710,  D1:770,  B:150, B1:200, L:'200',    weight:410, stock:1, price:190000, term:'Под заказ'},
        {num:15, name:'Колесо крановое К2Р-800х110', D:800,  D1:880,  B:110, B1:170, L:'150–170',weight:330, stock:0, price:210000, term:'Под заказ'},
        {num:16, name:'Колесо крановое К2Р-800х130', D:800,  D1:880,  B:130, B1:190, L:'160–170',weight:360, stock:0, price:210000, term:'Под заказ'},
        {num:17, name:'Колесо крановое К2Р-800х150', D:800,  D1:880,  B:150, B1:210, L:'170–200',weight:410, stock:0, price:210000, term:'Под заказ'},
        {num:18, name:'Колесо крановое К2Р-800х170', D:800,  D1:880,  B:170, B1:250, L:'200–230',weight:640, stock:0, price:320000, term:'Под заказ'},
        {num:19, name:'Колесо крановое К2Р-900х130', D:900,  D1:980,  B:130, B1:190, L:'170',    weight:460, stock:0, price:270000, term:'Под заказ'},
        {num:20, name:'Колесо крановое К2Р-900х150', D:900,  D1:980,  B:150, B1:210, L:'180',    weight:530, stock:0, price:310000, term:'Под заказ'},
        {num:21, name:'Колесо крановое К2Р-900х170', D:900,  D1:980,  B:150, B1:250, L:'190',    weight:630, stock:0, price:310000, term:'Под заказ'},
        {num:22, name:'Колесо крановое К2Р-1000х170',D:1000, D1:1080, B:170, B1:250, L:'230',    weight:890, stock:0, price:550000, term:'Под заказ'}
      ]
    },

    drums: {
      label: 'Барабаны БК',
      icon: '?',
      title: 'Барабаны крановые грузовые БК',
      subtitle: 'БК 260 · 310 · 400 · 410 · 510 · 815 · в наличии',
      tag: 'ПРАЙС-ЛИСТ · 6 ПОЗИЦИЙ',
      columns: [
        {key:'num',    label:'№',              type:'num',  cls:'col-num'},
        {key:'name',   label:'Наименование',   type:'text'},
        {key:'model',  label:'Модель',         type:'text'},
        {key:'stock',  label:'Наличие',        type:'badge',sortable:false},
        {key:'price',  label:'Цена с НДС, ₽',  type:'price'},
        {key:'term',   label:'Сроки',          type:'text'}
      ],
      quickFilters: [
        {label:'В наличии', field:'term', value:'В наличии'},
        {label:'БК 260',   field:'model', value:'БК 260'},
        {label:'БК 400',   field:'model', value:'БК 400'},
        {label:'БК 510',   field:'model', value:'БК 510'}
      ],
      data: [
        {num:1, name:'Крановый грузовой барабан БК 260', model:'БК 260', stock:1, price:79000,  term:'В наличии'},
        {num:2, name:'Крановый грузовой барабан БК 310', model:'БК 310', stock:1, price:85000,  term:'В наличии'},
        {num:3, name:'Крановый грузовой барабан БК 400', model:'БК 400', stock:1, price:162000, term:'В наличии'},
        {num:4, name:'Крановый грузовой барабан БК 410', model:'БК 410', stock:1, price:180000, term:'В наличии'},
        {num:5, name:'Крановый грузовой барабан БК 510', model:'БК 510', stock:1, price:261000, term:'В наличии'},
        {num:6, name:'Крановый грузовой барабан БК 815', model:'БК 815', stock:1, price:450000, term:'В наличии'}
      ]
    },

    zkz: {
      label: 'ЗКЗ · Фланцы и детали',
      icon: '?',
      title: 'Фланцы, заглушки, прокладки, заготовки (ЗКЗ)',
      subtitle: 'ГОСТ 33259-2015 · 28759 · ASME B16.5/16.47/16.48 · DIN EN 1092-1',
      tag: 'КАТАЛОГ · 30 ГРУПП',
      columns: [
        {key:'num',     label:'№',              type:'num',  cls:'col-num'},
        {key:'name',    label:'Наименование',   type:'text'},
        {key:'std',     label:'Стандарт',       type:'text'},
        {key:'du',      label:'Dу, мм',         type:'text', sortable:false},
        {key:'pu',      label:'Ру, МПа / Class',type:'text'},
        {key:'height',  label:'Высота, мм',     type:'text'},
        {key:'steel',   label:'Марки стали',    type:'text'},
        {key:'stock',   label:'Наличие',        type:'badge',sortable:false},
        {key:'price',   label:'Цена с НДС',     type:'price'},
        {key:'term',    label:'Сроки',          type:'text'}
      ],
      quickFilters: [
        {label:'Фланцы',        field:'cat', value:'Фланцы'},
        {label:'Заглушки',      field:'cat', value:'Заглушки'},
        {label:'Прокладки',     field:'cat', value:'Прокладки'},
        {label:'Краны шаровые', field:'cat', value:'Краны шаровые'},
        {label:'Спец. изделия', field:'cat', value:'Спец. изделия'},
        {label:'Заготовки',     field:'cat', value:'Заготовки'},
        {label:'12Х18Н10Т',     field:'steel', value:'12Х18Н10Т'}
      ],
      data: [
        /* ФЛАНЦЫ */
        {num:1, cat:'Фланцы', name:'Фланец стальной плоский тип 01', std:'ГОСТ 33259-2015', du:'400–1600', pu:'0,6–2,5 МПа', height:'—', steel:'ст.20, 09Г2С, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:2, cat:'Фланцы', name:'Фланец стальной приварной встык тип 11', std:'ГОСТ 33259-2015', du:'50–1400', pu:'0,6–25,0 МПа', height:'—', steel:'ст.20, 09Г2С, 15Х5М, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:3, cat:'Фланцы', name:'Фланец стальной type 01 / type 11', std:'DIN EN 1092-1', du:'50–1200', pu:'2,5–10,0 МПа', height:'—', steel:'P245GH, 16Mo3, 14404', stock:0, price:0, term:'Под заказ'},
        {num:4, cat:'Фланцы', name:'Фланец стальной плоский приварной сосудов и аппаратов', std:'ГОСТ 28759.2-90', du:'400–2000', pu:'0,3–1,6 МПа', height:'—', steel:'ст.20, 09Г2С, 15Х5М, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:5, cat:'Фланцы', name:'Фланец стальной приварной встык сосудов и аппаратов', std:'ГОСТ 28759.3-90', du:'400–2000', pu:'1,0–6,3 МПа', height:'—', steel:'ст.20, 09Г2С, 15Х5М, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:6, cat:'Фланцы', name:'Фланец стальной приварной встык сосудов и аппаратов', std:'ГОСТ 28759.4-90', du:'400–1200', pu:'6,3–16,0 МПа', height:'—', steel:'ст.20, 09Г2С, 15Х5М, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:7, cat:'Фланцы', name:'Фланец стальной для труб', std:'ASME B16.5', du:'50–1400', pu:'Class 150–2500', height:'—', steel:'A105, A182GrF5, A350GrLF2, A182GrF304, A182GrF316L', stock:0, price:0, term:'Под заказ'},
        {num:8, cat:'Фланцы', name:'Фланец стальной для труб', std:'ASME B16.47', du:'50–1400', pu:'Class 150–600', height:'—', steel:'A105, A182GrF5, A350GrLF2, A182GrF304, A182GrF316L', stock:0, price:0, term:'Под заказ'},
        {num:9, cat:'Фланцы', name:'Заготовка фланца стальная', std:'ГОСТ 33259 / 28759 / ASME / DIN', du:'50–2000', pu:'0,6–25,0 МПа', height:'—', steel:'ст.20, 09Г2С, 15Х5М, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},

        /* ЗАГЛУШКИ */
        {num:10, cat:'Заглушки', name:'Заглушка фланцевая стальная', std:'АТК 24.200.02-90', du:'150–700', pu:'1,6–16,0 МПа', height:'—', steel:'ст.20, 09Г2С, 15Х5М, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:11, cat:'Заглушки', name:'Заглушка поворотная стальная', std:'ASME B16.48', du:'150–700', pu:'1,6–16,0 МПа', height:'—', steel:'ст.20, 09Г2С, 15Х5М, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:12, cat:'Заглушки', name:'Заглушка поворотная стальная', std:'АТК 26-18-5-93', du:'150–700', pu:'1,6–16,0 МПа', height:'—', steel:'ст.20, 09Г2С, 15Х5М, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},

        /* ПРОКЛАДКИ */
        {num:13, cat:'Прокладки', name:'Прокладка металлическая восьмиугольного сечения', std:'ГОСТ 28759.8-90', du:'400–1600', pu:'6,3–16,0 МПа', height:'—', steel:'08Х13, 09Г2С, 08Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:14, cat:'Прокладки', name:'Прокладка овального и восьмиугольного сечения стальная для фланцев арматуры', std:'ГОСТ Р 53561-2009', du:'150–400', pu:'6,3–16,0 МПа', height:'—', steel:'ст.20, 10895, 09Г2С, 08Х13, 15Х5М, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:15, cat:'Прокладки', name:'Прокладка овального и восьмиугольного сечения стальная для фланцев арматуры', std:'ГОСТ 26.260.461-99', du:'150–400', pu:'6,3–16,0 МПа', height:'—', steel:'08Х13, 09Г2С, 08Х18Н10Т', stock:0, price:0, term:'Под заказ'},

        /* КРАНЫ ШАРОВЫЕ */
        {num:16, cat:'Краны шаровые', name:'Седло крана шарового', std:'—', du:'350–1800', pu:'0,6–25,0 МПа', height:'70–400', steel:'09Г2С, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:17, cat:'Краны шаровые', name:'Патрубок фланцевый или приварной', std:'—', du:'240–700', pu:'0,6–25,0 МПа', height:'70–500', steel:'09Г2С, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:18, cat:'Краны шаровые', name:'Корпус крана шарового', std:'—', du:'240–700', pu:'0,6–25,0 МПа', height:'70–500', steel:'09Г2С, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:19, cat:'Краны шаровые', name:'Пробка крана шарового', std:'—', du:'240–700', pu:'0,6–25,0 МПа', height:'70–500', steel:'09Г2С, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},

        /* СПЕЦ. ИЗДЕЛИЯ */
        {num:20, cat:'Спец. изделия', name:'Фланец по чертежам заказчика', std:'—', du:'240–2350', pu:'0,6–25,0 МПа', height:'70–500', steel:'09Г2С, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:21, cat:'Спец. изделия', name:'Монтажная катушка', std:'—', du:'240–1500', pu:'0,6–25,0 МПа', height:'150–500', steel:'09Г2С, 13ХФА, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:22, cat:'Спец. изделия', name:'Полумуфта', std:'—', du:'240–500', pu:'4,0–36,0 МПа', height:'100–400', steel:'09Г2С, 20ГЛ, 40ХЛ', stock:0, price:0, term:'Под заказ'},
        {num:23, cat:'Спец. изделия', name:'Полукольцо', std:'—', du:'240–2400', pu:'1,6–25,0 МПа', height:'100–400', steel:'09Г2С, 20ГЛ, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:24, cat:'Спец. изделия', name:'Крышка для задвижки', std:'—', du:'240–480', pu:'1,6–25,0 МПа', height:'100–350', steel:'09Г2С, 13ХФА, 20ГЛ, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:25, cat:'Спец. изделия', name:'Корпус колонной обвязки ОКО', std:'—', du:'240–425', pu:'25,0–32,0 МПа', height:'200–325', steel:'40Х, 30ХГСА, 09Г2С', stock:0, price:0, term:'Под заказ'},

        /* ЗАГОТОВКИ */
        {num:26, cat:'Заготовки', name:'Металлургическая заготовка (слиток)', std:'ГОСТ 8479-70 / 25054-81 / 20072-74', du:'180–500', pu:'—', height:'100–300', steel:'09Г2С, 16ГС, 12Х18Н10Т', stock:0, price:0, term:'Под заказ'},
        {num:27, cat:'Заготовки', name:'Кольцевая заготовка (ЦЭШЛ)', std:'ГОСТ 8479-70 / 25054-81 / 20072-74', du:'180–2350', pu:'—', height:'50–500', steel:'20, 09Г2С, 13ХФА, 15Х5М, 12Х18Н10Т, 10Х17Н13М2Т', stock:0, price:0, term:'Под заказ'},
        {num:28, cat:'Заготовки', name:'Кованая заготовка (поковка, раскатное кольцо)', std:'ГОСТ 8479-70 / 25054-81 / 20072-74', du:'180–2500', pu:'—', height:'50–800', steel:'20, 09Г2С, 15Х5М, 12Х18Н10Т, 10Х17Н13М2Т', stock:0, price:0, term:'Под заказ'}
      ]
    }
  },

  phone: '8 (902) 873-36-90',
  phoneHref: '+79028733690',
  email: 'arsenal-detal@list.ru',
  manager: 'Менеджер: Ольга · ООО «Арсенал Деталь»'
};

/* ==================== ДВИЖОК ==================== */
var state = {search:'', sort:{key:null,dir:1}, filters:{}, quickFilter:null, section:'stroPs', subcat:'Все'};
var picked = {};

function keyOf(section,num){ return section+':'+num; }
function currentSection(){ return PROJECT.sections[state.section]; }
function fmt(n){ return Math.round(n).toLocaleString('ru-RU'); }

/* ==================== ПОИСК ==================== */
function norm(s){
  return String(s==null?'':s)
    .toLowerCase()
    .replace(/ё/g,'е')
    .replace(/,/g,'.')
    .replace(/[×xх*]/g,'x')
    .replace(/\b(мм|см|м|т|шт|руб|р|₽|кг|г|н|мпа|class)\b/g,' ')
    .replace(/[^\wа-я0-9.x\s-]+/gi,' ')
    .replace(/\s+/g,' ')
    .trim();
}

function buildIndex(r){
  var parts = [
    r.num, r.name, r.type, r.construction, r.term, r.cat, r.model,
    r.exec, r.shank, r.gost, r.std, r.du, r.pu, r.height, r.steel,
    r.capacity, r.length, r.diam, r.weight, r.force,
    r.D, r.D1, r.B, r.B1, r.L
  ];
  var base = norm(parts.join(' '));
  var extra = '';
  [r.capacity, r.length, r.diam, r.weight, r.force, r.D, r.D1, r.B, r.B1].forEach(function(v){
    if (v==null || v==='') return;
    var n = parseFloat(String(v).replace(',','.'));
    if (isNaN(n)) return;
    extra += ' ' + n + ' ' + n.toFixed(1) + ' ' + (n*1000) + ' ';
  });
  return (base + ' ' + norm(extra)).replace(/\s+/g,' ').trim();
}

function tokenize(q){ return norm(q).split(' ').filter(function(t){return t.length&gt;0;}); }

function tokenMatches(tok, idx){
  if (idx.indexOf(tok) !== -1) return true;
  var n = parseFloat(tok);
  if (!isNaN(n) &amp;&amp; /^\d+(\.\d+)?$/.test(tok)){
    var variants = [String(n), n.toFixed(1), n.toFixed(2), ('0'+n).slice(-2), String(n*1000)];
    for (var i=0;i&lt;variants.length;i++){
      if (idx.indexOf(variants[i]) !== -1) return true;
    }
  }
  return false;
}

function rowMatches(r, tokens){
  if (!tokens.length) return true;
  var idx = buildIndex(r);
  for (var i=0;i&lt;tokens.length;i++){
    if (!tokenMatches(tokens[i], idx)) return false;
  }
  return true;
}

function highlight(text, tokens){
  if (!tokens.length) return text;
  var out = String(text);
  tokens.forEach(function(t){
    if (t.length &lt; 2) return;
    var re = new RegExp('('+t.replace(/[.*+?^${}()|[\]\\]/g,'\\$&amp;')+')','gi');
    out = out.replace(re, '&lt;mark class="hl"&gt;$1&lt;/mark&gt;');
  });
  return out;
}

/* ---------- СУММЫ ---------- */
function calcBaseSum(){
  var total = 0;
  Object.keys(picked).forEach(function(k){
    var parts = k.split(':');
    var sec = PROJECT.sections[parts[0]];
    if (!sec) return;
    var r = sec.data.find(function(x){return x.num===parseInt(parts[1],10);});
    if (!r) return;
    total += (r.price||0) * (picked[k]||1);
  });
  return total;
}
function getDiscount(sum){
  if (sum &gt;= PROJECT.discountThreshold) return sum * (PROJECT.discountPercent/100);
  return 0;
}
function isDiscountActive(sum){ return sum &gt;= PROJECT.discountThreshold; }

/* ---------- РЕНДЕР ---------- */
function renderApp(){
  var p = PROJECT;
  var html = '';

  html += '&lt;div class="banner"&gt;'+
    '&lt;div class="banner-tag"&gt;'+p.banner.tag+'&lt;/div&gt;'+
    '&lt;div class="banner-title"&gt;'+p.banner.title+'&lt;/div&gt;'+
    '&lt;div class="banner-phone"&gt;'+p.banner.phone+'&lt;/div&gt;'+
    '&lt;div class="banner-note"&gt;'+p.banner.note+'&lt;/div&gt;'+
  '&lt;/div&gt;';

  var tickerItems = '';
  Object.keys(p.sections).forEach(function(sk){
    var s = p.sections[sk];
    s.data.slice(0,3).forEach(function(r){
      var price = r.price&gt;0 ? fmt(r.price)+' ₽' : 'по запросу';
      tickerItems += '&lt;span class="ticker-item"&gt;'+r.name+' — &lt;b&gt;'+price+'&lt;/b&gt;&lt;/span&gt;&lt;span class="ticker-dot"&gt;◆&lt;/span&gt;';
    });
  });
  html += '&lt;div class="ticker"&gt;'+
    '&lt;div class="ticker-label"&gt;ЦЕНЫ&lt;/div&gt;'+
    '&lt;div class="ticker-vp"&gt;&lt;div class="ticker-track"&gt;'+tickerItems+tickerItems+'&lt;/div&gt;&lt;/div&gt;'+
  '&lt;/div&gt;';

  html += '&lt;div class="ad-strip"&gt;'+p.ads.map(function(a){
    return '&lt;a class="ad-item" href="'+(a.href||'#')+'" target="_blank" rel="noopener"&gt;'+
      '&lt;span class="ad-tag"&gt;'+a.tag+'&lt;/span&gt;'+
      '&lt;span class="ad-text"&gt;'+a.text+'&lt;/span&gt;'+
      '&lt;span class="ad-cta"&gt;'+a.cta+'&lt;/span&gt;'+
    '&lt;/a&gt;';
  }).join('')+'&lt;/div&gt;';

  html += '&lt;div class="header"&gt;'+
    '&lt;div class="tag"&gt;'+p.title.toUpperCase()+'&lt;/div&gt;'+
    '&lt;h1&gt;'+p.title+'&lt;/h1&gt;'+
    '&lt;div class="line"&gt;&lt;/div&gt;'+
    '&lt;p&gt;'+p.subtitle+'&lt;/p&gt;'+
  '&lt;/div&gt;';

  /* ВКЛАДКИ */
  html += '&lt;div class="tabs" id="tabsBlock"&gt;';
  Object.keys(p.sections).forEach(function(sk){
    var s = p.sections[sk];
    html += '&lt;button class="tab'+(state.section===sk?' active':'')+'" onclick="switchSection(\''+sk+'\')"&gt;'+
      s.icon+' '+s.label+' &lt;span class="cnt"&gt;'+s.data.length+'&lt;/span&gt;&lt;/button&gt;';
  });
  html += '&lt;/div&gt;';

  /* ПОДКАТЕГОРИИ (только для ЗКЗ) */
  var sec = currentSection();
  if (state.section==='zkz'){
    var cats = ['Все','Фланцы','Заглушки','Прокладки','Краны шаровые','Спец. изделия','Заготовки'];
    html += '&lt;div class="subcats"&gt;';
    cats.forEach(function(c){
      html += '&lt;button class="subcat'+(state.subcat===c?' active':'')+'" onclick="setSubcat(\''+c+'\')"&gt;'+c+'&lt;/button&gt;';
    });
    html += '&lt;/div&gt;';
  }

  /* Блок скидки */
  html += '&lt;div class="discount-banner" id="discountBanner"&gt;'+
    '&lt;h3&gt;★ Скидка от суммы ★&lt;/h3&gt;'+
    '&lt;p&gt;Закажите на сумму от &lt;b&gt;50 000 ₽&lt;/b&gt; — получите &lt;b style="color:#7dff7d"&gt;скидку 10%&lt;/b&gt;.&lt;br&gt;'+
    'Скидка применяется автоматически ко всей сумме по всем разделам.&lt;/p&gt;'+
    '&lt;div class="progress-wrap"&gt;'+
      '&lt;div class="progress-fill" id="progressFill" style="width:0%"&gt;&lt;/div&gt;'+
      '&lt;div class="progress-label" id="progressLabel"&gt;Отметьте позиции — узнаете скидку&lt;/div&gt;'+
    '&lt;/div&gt;'+
    '&lt;div class="discount-stats"&gt;'+
      '&lt;div class="discount-stat"&gt;&lt;div class="lbl"&gt;Набрано&lt;/div&gt;&lt;div class="val" id="discBase"&gt;0 ₽&lt;/div&gt;&lt;/div&gt;'+
      '&lt;div class="discount-stat"&gt;&lt;div class="lbl"&gt;До скидки осталось&lt;/div&gt;&lt;div class="val" id="discRemain"&gt;50 000 ₽&lt;/div&gt;&lt;/div&gt;'+
      '&lt;div class="discount-stat"&gt;&lt;div class="lbl"&gt;Ваша скидка&lt;/div&gt;&lt;div class="val" id="discRate"&gt;0 ₽&lt;/div&gt;&lt;/div&gt;'+
    '&lt;/div&gt;'+
  '&lt;/div&gt;';

  html += '&lt;div class="cta-block"&gt;'+
    '&lt;h2&gt;'+sec.title+'&lt;/h2&gt;'+
    '&lt;p&gt;Кликните &lt;b&gt;★&lt;/b&gt;, укажите количество — сумма появится внизу экрана.&lt;br&gt;'+
    'При сумме от &lt;b&gt;50 000 ₽&lt;/b&gt; скидка 10% применится автоматически.&lt;/p&gt;'+
    '&lt;div class="cta-counter"&gt;Выбрано: &lt;b id="selectedCount"&gt;0&lt;/b&gt; из '+sec.data.length+'&lt;/div&gt;'+
    '&lt;div class="cta-buttons"&gt;'+
      '&lt;button class="btn-big primary" onclick="downloadRequest()"&gt;⬇ Скачать запрос КП&lt;/button&gt;'+
      '&lt;button class="btn-big" onclick="sendByEmail()"&gt;✉ Отправить на e-mail&lt;/button&gt;'+
      '&lt;button class="btn-big" onclick="scrollToTable()"&gt;↓ К каталогу&lt;/button&gt;'+
    '&lt;/div&gt;'+
  '&lt;/div&gt;';

  html += '&lt;div class="stats"&gt;'+
    '&lt;div class="stat"&gt;&lt;div class="lbl"&gt;Всего позиций&lt;/div&gt;&lt;div class="val" id="statTotal"&gt;—&lt;/div&gt;&lt;/div&gt;'+
    '&lt;div class="stat"&gt;&lt;div class="lbl"&gt;Всего на складе&lt;/div&gt;&lt;div class="val" id="statStock"&gt;—&lt;/div&gt;&lt;/div&gt;'+
    '&lt;div class="stat"&gt;&lt;div class="lbl"&gt;Диапазон&lt;/div&gt;&lt;div class="val sm" id="statCap"&gt;—&lt;/div&gt;&lt;/div&gt;'+
    '&lt;div class="stat"&gt;&lt;div class="lbl"&gt;Цена от&lt;/div&gt;&lt;div class="val sm" id="statPrice"&gt;—&lt;/div&gt;&lt;/div&gt;'+
  '&lt;/div&gt;';

  html += '&lt;div class="toolbar"&gt;'+
    '&lt;button class="btn" onclick="resetFilters()"&gt;✕ Очистить фильтры&lt;/button&gt;'+
    '&lt;button class="btn" onclick="window.print()"&gt;? Печать каталога&lt;/button&gt;'+
  '&lt;/div&gt;';

  html += '&lt;div class="filter"&gt;'+
    '&lt;div class="filter-row"&gt;'+
      '&lt;input class="search" type="text" id="search" placeholder="? Сквозной поиск: БК, фланец, 33259, 12Х18Н10Т, К2Р…"&gt;'+
      '&lt;div class="counter" id="counter"&gt;Найдено: 0&lt;/div&gt;'+
    '&lt;/div&gt;'+
    '&lt;div class="search-help"&gt;Поиск &lt;b&gt;сразу по всем разделам&lt;/b&gt;: стропы, крюки, КЧ ХЛ, канаты, колёса, барабаны, фланцы ЗКЗ. Ищите по аббревиатуре (КЧ, УСК, К2Р, БК), стандарту (33259, 2688, ASME), марке стали (09Г2С, 12Х18Н10Т), размеру (710, 2000). Несколько слов — &lt;b&gt;все должны найтись&lt;/b&gt;.&lt;/div&gt;'+
    '&lt;div class="filter-grid" style="margin-top:12px"&gt;'+
      '&lt;div class="fld"&gt;&lt;label&gt;Размер / г/п&lt;/label&gt;&lt;input type="number" id="fCapacity" placeholder="напр. 710"&gt;&lt;/div&gt;'+
      '&lt;div class="fld"&gt;&lt;label&gt;Длина, м&lt;/label&gt;&lt;input type="number" id="fLength" placeholder="напр. 2.5"&gt;&lt;/div&gt;'+
      '&lt;div class="fld"&gt;&lt;label&gt;Тип / исполнение&lt;/label&gt;&lt;input type="text" id="fType" placeholder="КЧ ХЛ, А, УСК1"&gt;&lt;/div&gt;'+
      '&lt;div class="fld"&gt;&lt;label&gt;Наличие&lt;/label&gt;&lt;select id="fStock"&gt;&lt;option value="all"&gt;Все&lt;/option&gt;&lt;option value="in"&gt;Есть на складе&lt;/option&gt;&lt;option value="out"&gt;Под заказ&lt;/option&gt;&lt;/select&gt;&lt;/div&gt;'+
      '&lt;div class="fld"&gt;&lt;label&gt;Сроки&lt;/label&gt;&lt;select id="fTerm"&gt;&lt;option value="all"&gt;Все&lt;/option&gt;&lt;option value="Со склада"&gt;Со склада&lt;/option&gt;&lt;option value="Под заказ"&gt;Под заказ&lt;/option&gt;&lt;option value="В наличии"&gt;В наличии&lt;/option&gt;&lt;/select&gt;&lt;/div&gt;'+
    '&lt;/div&gt;'+
    '&lt;div class="filter-actions"&gt;'+
      sec.quickFilters.map(function(q,i){
        return '&lt;button class="btn" onclick="applyQuick('+i+')"&gt;'+q.label+'&lt;/button&gt;';
      }).join('')+
    '&lt;/div&gt;'+
  '&lt;/div&gt;';

  html += '&lt;div class="table-block" id="catalog"&gt;'+
    '&lt;div class="select-hint"&gt;→ ВЫБЕРИ ПОЗИЦИИ →&lt;/div&gt;'+
    '&lt;div class="global-badge" id="globalBadge"&gt;&lt;/div&gt;'+
    '&lt;div class="block-title" id="blockTitle"&gt;'+sec.title+' · прайс-лист&lt;/div&gt;'+
    '&lt;div class="table-wrap"&gt;&lt;table id="tbl"&gt;&lt;thead id="thead"&gt;&lt;/thead&gt;&lt;tbody id="tbody"&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;'+
    '&lt;div class="footnote"&gt;'+
      '&lt;div class="fn"&gt;Отметьте &lt;b&gt;★&lt;/b&gt;, укажите &lt;b&gt;количество&lt;/b&gt; — попадёт в запрос&lt;/div&gt;'+
      '&lt;div class="fn"&gt;Все цены указаны &lt;b&gt;с НДС '+p.vat+'%&lt;/b&gt;&lt;/div&gt;'+
      '&lt;div class="fn"&gt;При сумме &lt;b&gt;от 50 000 ₽&lt;/b&gt; — скидка 10% (автоматически)&lt;/div&gt;'+
      '&lt;div class="fn"&gt;Позиции ЗКЗ — &lt;b&gt;по запросу&lt;/b&gt; (цена по чертежу)&lt;/div&gt;'+
      '&lt;div class="fn"&gt;Возможно изготовление по чертежу заказчика&lt;/div&gt;'+
    '&lt;/div&gt;'+
  '&lt;/div&gt;';

  html += '&lt;div class="cta"&gt;'+
    '&lt;p class="cta-text"&gt;Отметили позиции? Нажмите «Скачать запрос КП»&lt;/p&gt;'+
    '&lt;button class="btn-big primary" onclick="downloadRequest()"&gt;⬇ Скачать запрос КП&lt;/button&gt;'+
    '&lt;div style="margin-top:20px"&gt;'+
      '&lt;a href="tel:'+p.phoneHref+'" class="cta-btn"&gt;'+p.phone+'&lt;/a&gt;'+
      '&lt;a href="mailto:'+p.email+'?subject=Запрос%20КП%20на%20'+encodeURIComponent(p.title)+'" class="cta-mail"&gt;✉ '+p.email+'&lt;/a&gt;'+
    '&lt;/div&gt;'+
    '&lt;p class="manager"&gt;'+p.manager+'&lt;/p&gt;'+
  '&lt;/div&gt;';

  html += '&lt;div class="seo"&gt;&lt;p&gt;'+p.title+'. Скидка от 50 000 ₽. ООО «Арсенал Деталь».&lt;/p&gt;&lt;/div&gt;';

  document.getElementById('app').innerHTML = html;
}

function switchSection(sk){
  state.section = sk;
  state.search=''; state.filters={}; state.quickFilter=null; state.sort={key:null,dir:1}; state.subcat='Все';
  renderApp();
  updateStats();
  render();
}

function setSubcat(c){
  state.subcat = c;
  renderApp();
  updateStats();
  render();
}

/* ---------- СБОР СТРОК ПО ВСЕМ РАЗДЕЛАМ ---------- */
function collectAllRows(){
  var out = [];
  Object.keys(PROJECT.sections).forEach(function(sk){
    PROJECT.sections[sk].data.forEach(function(r){
      out.push({section:sk, sectionLabel:PROJECT.sections[sk].label, row:r});
    });
  });
  return out;
}

/* ---------- ФИЛЬТРАЦИЯ ---------- */
function getFiltered(){
  var tokens = tokenize(state.search);
  var isGlobal = tokens.length &gt; 0;

  var items;
  if (isGlobal){
    items = collectAllRows().filter(function(it){ return rowMatches(it.row, tokens); });
  } else {
    var sec = currentSection();
    items = sec.data.map(function(r){ return {section:state.section, sectionLabel:sec.label, row:r}; });
    if (state.section==='zkz' &amp;&amp; state.subcat &amp;&amp; state.subcat!=='Все'){
      items = items.filter(function(it){ return it.row.cat===state.subcat; });
    }
  }

  if (!isGlobal){
    if (state.filters.capacity){ var c=parseFloat(state.filters.capacity); if(!isNaN(c)) items=items.filter(function(it){return it.row.capacity===c || it.row.diam===c || it.row.D===c || it.row.weight===c;}); }
    if (state.filters.length){ var l=parseFloat(state.filters.length); if(!isNaN(l)) items=items.filter(function(it){return it.row.length===l;}); }
    if (state.filters.stock==='in')  items=items.filter(function(it){return it.row.stock&gt;0;});
    if (state.filters.stock==='out') items=items.filter(function(it){return it.row.stock===0;});
    if (state.filters.term &amp;&amp; state.filters.term!=='all') items=items.filter(function(it){return it.row.term===state.filters.term;});
    if (state.filters.type){
      var ft = norm(state.filters.type);
      if (ft) items=items.filter(function(it){
        var r=it.row;
        return norm(r.type||'').indexOf(ft)!==-1 || norm(r.exec||'')===ft || norm(r.name||'').indexOf(ft)!==-1;
      });
    }
    if (state.quickFilter){
      var qf = state.quickFilter;
      items = items.filter(function(it){
        var r = it.row;
        if (qf.field==='term') return r.term===qf.value;
        if (qf.field==='type') return norm(r.type||'').indexOf(norm(qf.value))!==-1;
        if (qf.field==='exec') return r.exec===qf.value;
        if (qf.field==='capMax') return r.capacity&lt;=qf.value;
        if (qf.field==='capMin') return r.capacity&gt;=qf.value;
        if (qf.field==='diamMax') return r.diam&lt;=qf.value;
        if (qf.field==='diamMin') return r.diam&gt;=qf.value;
        if (qf.field==='dMax') return r.D&lt;=qf.value;
        if (qf.field==='dMin') return r.D&gt;=qf.value;
        if (qf.field==='cat') return r.cat===qf.value;
        if (qf.field==='steel') return norm(r.steel||'').indexOf(norm(qf.value))!==-1;
        if (qf.field==='model') return norm(r.model||'').indexOf(norm(qf.value))!==-1;
        return true;
      });
    }
  }

  if (state.sort.key &amp;&amp; !isGlobal){
    var k=state.sort.key, d=state.sort.dir;
    items.sort(function(a,b){
      var va=a.row[k], vb=b.row[k];
      if (typeof va==='number' &amp;&amp; typeof vb==='number') return (va-vb)*d;
      return String(va).localeCompare(String(vb),'ru')*d;
    });
  }

  return {items:items, tokens:tokens, isGlobal:isGlobal};
}

/* ---------- УНИВЕРСАЛЬНЫЕ ХАРАКТЕРИСТИКИ ---------- */
function rowChars(section, r){
  if (section==='stroPs') return r.type+' · '+r.length+' м · '+r.construction+' · Ø'+r.diam+' мм';
  if (section==='hooks')  return 'исп. '+r.exec+' · хвостовик '+r.shank+' · ГОСТ '+r.gost;
  if (section==='hooksCh') return r.type;
  if (section==='cables') return 'Ø'+r.diam+' мм · усилие '+fmt(r.force)+' Н · ГОСТ '+r.gost;
  if (section==='wheels') return 'D'+r.D+'×B'+r.B+' · D1 '+r.D1+' · вес '+r.weight+' кг';
  if (section==='drums')  return 'Грузовой · модель '+r.model+' · в наличии';
  if (section==='zkz'){
    var parts = [];
    if (r.std) parts.push(r.std);
    if (r.du) parts.push('Dу '+r.du);
    if (r.pu) parts.push('Ру '+r.pu);
    if (r.height &amp;&amp; r.height!=='—') parts.push('H '+r.height);
    return parts.join(' · ');
  }
  return '';
}

/* ---------- РЕНДЕР ТАБЛИЦЫ ---------- */
function render(){
  var res = getFiltered();
  var items = res.items, tokens = res.tokens, isGlobal = res.isGlobal;
  var tbody = document.getElementById('tbody');
  var thead = document.getElementById('thead');
  if (!tbody || !thead) return;
  tbody.innerHTML = '';
  thead.innerHTML = '';

  var baseSum = calcBaseSum();
  var discountActive = isDiscountActive(baseSum);

  var globalBadge = document.getElementById('globalBadge');
  var blockTitle = document.getElementById('blockTitle');
  var tabsBlock = document.getElementById('tabsBlock');

  if (isGlobal){
    if (tabsBlock) tabsBlock.style.display = 'none';
    if (globalBadge){
      globalBadge.classList.add('show');
      var secCounts = {};
      items.forEach(function(it){ secCounts[it.section] = (secCounts[it.section]||0)+1; });
      var parts = Object.keys(secCounts).map(function(sk){
        return PROJECT.sections[sk].label+': '+secCounts[sk];
      });
      globalBadge.innerHTML = '&lt;span&gt;? &lt;b&gt;Сквозной поиск&lt;/b&gt; «'+state.search+'» — найдено &lt;b&gt;'+items.length+'&lt;/b&gt; поз. по всем разделам&lt;/span&gt;'+
        '&lt;span style="opacity:.8"&gt;'+parts.join(' · ')+'&lt;/span&gt;'+
        '&lt;button class="btn" onclick="exitGlobalSearch()"&gt;✕ Выйти из сквозного поиска&lt;/button&gt;';
    }
    if (blockTitle) blockTitle.textContent = 'Результаты поиска по всем разделам';
  } else {
    if (tabsBlock) tabsBlock.style.display = '';
    if (globalBadge) globalBadge.classList.remove('show');
    if (blockTitle) blockTitle.textContent = currentSection().title+' · прайс-лист';
  }

  if (isGlobal){
    thead.innerHTML = '&lt;tr&gt;'+
      '&lt;th class="col-star"&gt;★&lt;/th&gt;'+
      '&lt;th class="col-qty"&gt;Кол-во&lt;/th&gt;'+
      '&lt;th&gt;Раздел&lt;/th&gt;'+
      '&lt;th&gt;№&lt;/th&gt;'+
      '&lt;th&gt;Марка&lt;/th&gt;'+
      '&lt;th class="num"&gt;Г/п, т / Ø&lt;/th&gt;'+
      '&lt;th&gt;Характеристики&lt;/th&gt;'+
      '&lt;th class="num"&gt;Наличие&lt;/th&gt;'+
      '&lt;th class="num"&gt;Цена с НДС, ₽&lt;/th&gt;'+
      '&lt;th&gt;Сроки&lt;/th&gt;'+
    '&lt;/tr&gt;';
  } else {
    var sec = currentSection();
    var thHtml = '&lt;tr&gt;'+
      '&lt;th class="col-star" title="Отметь позиции"&gt;★&lt;/th&gt;'+
      '&lt;th class="col-qty"&gt;Кол-во&lt;/th&gt;';
    sec.columns.forEach(function(c){
      var cls = (c.type==='num'?'num ':'') + (c.cls||'');
      if (c.sortable) cls += ' sortable';
      thHtml += '&lt;th class="'+cls+'" '+(c.sortable?'data-key="'+c.key+'"':'')+'&gt;'+c.label+'&lt;/th&gt;';
    });
    thHtml += '&lt;/tr&gt;';
    thead.innerHTML = thHtml;
  }

  if (!items.length){
    var colCount = isGlobal ? 10 : (currentSection().columns.length+2);
    tbody.innerHTML = '&lt;tr&gt;&lt;td colspan="'+colCount+'" style="text-align:center;padding:40px;opacity:.6"&gt;Ничего не найдено. Попробуйте другой запрос — например, «БК», «фланец», «33259», «710», «К2Р».&lt;/td&gt;&lt;/tr&gt;';
    document.getElementById('counter').textContent = 'Найдено: 0';
    updateStickyBar();
    updateDiscountBanner();
    bindSortHeaders();
    return;
  }

  items.forEach(function(it){
    var r = it.row;
    var k = keyOf(it.section, r.num);
    var isPicked = picked[k]!==undefined;
    var qty = isPicked ? picked[k] : 1;
    var hasPrice = (r.price||0) &gt; 0;
    var finalPrice = discountActive &amp;&amp; hasPrice ? Math.round(r.price * (1 - PROJECT.discountPercent/100)) : r.price;
    var tr = document.createElement('tr');
    if (isPicked) tr.className = discountActive &amp;&amp; hasPrice ? 'picked discount-active' : 'picked';

    var cells =
      '&lt;td class="col-star"&gt;&lt;span class="star'+(isPicked?' on':'')+'" data-sec="'+it.section+'" data-num="'+r.num+'"&gt;'+(isPicked?'★':'☆')+'&lt;/span&gt;&lt;/td&gt;'+
      '&lt;td class="col-qty"&gt;&lt;input type="number" class="qty" data-sec="'+it.section+'" data-num="'+r.num+'" value="'+qty+'" min="1" max="9999"'+(isPicked?'':' disabled')+'&gt;&lt;/td&gt;';

    if (isGlobal){
      var gp = r.capacity!=null ? r.capacity+' т' : (r.diam!=null ? 'Ø'+r.diam+' мм' : (r.D!=null ? 'D'+r.D+' мм' : (r.du ? 'Dу '+r.du : (r.model ? r.model : '—'))));
      var nameHl = tokens.length ? highlight(r.name, tokens) : r.name;
      var priceCell = hasPrice
        ? '&lt;td class="num price'+(discountActive&amp;&amp;isPicked?' discount':'')+'"&gt;'+fmt(finalPrice)+' ₽&lt;/td&gt;'
        : '&lt;td class="num price request"&gt;по запросу&lt;/td&gt;';
      cells +=
        '&lt;td&gt;'+it.sectionLabel+'&lt;/td&gt;'+
        '&lt;td class="num"&gt;'+r.num+'&lt;/td&gt;'+
        '&lt;td&gt;'+nameHl+'&lt;/td&gt;'+
        '&lt;td class="num"&gt;'+gp+'&lt;/td&gt;'+
        '&lt;td&gt;'+rowChars(it.section, r)+'&lt;/td&gt;'+
        '&lt;td class="num"&gt;&lt;span class="'+(r.stock&gt;=10?'badge many':r.stock===0?'badge zero':'badge')+'"&gt;'+(r.stock&gt;0?r.stock:'под заказ')+'&lt;/span&gt;&lt;/td&gt;'+
        priceCell+
        '&lt;td&gt;'+r.term+'&lt;/td&gt;';
    } else {
      var sec = currentSection();
      sec.columns.forEach(function(c){
        var v = r[c.key];
        if (c.type==='num') cells += '&lt;td class="num '+(c.cls||'')+'"&gt;'+v+'&lt;/td&gt;';
        else if (c.type==='price'){
          if (v&gt;0){
            cells += discountActive&amp;&amp;isPicked
              ? '&lt;td class="num price discount"&gt;'+fmt(finalPrice)+' ₽&lt;/td&gt;'
              : '&lt;td class="num price"&gt;'+fmt(v)+' ₽&lt;/td&gt;';
          } else {
            cells += '&lt;td class="num price request"&gt;по запросу&lt;/td&gt;';
          }
        }
        else if (c.type==='badge'){
          var cls = v&gt;=10 ? 'badge many' : v===0 ? 'badge zero' : 'badge';
          var txt = v&gt;0 ? v : 'под заказ';
          cells += '&lt;td class="num"&gt;&lt;span class="'+cls+'"&gt;'+txt+'&lt;/span&gt;&lt;/td&gt;';
        }
        else {
          var txt = (c.key==='num') ? '&lt;b&gt;'+v+'&lt;/b&gt;' : v;
          if (c.key==='name' &amp;&amp; tokens.length) txt = highlight(v, tokens);
          cells += '&lt;td class="'+(c.cls||'')+'"&gt;'+txt+'&lt;/td&gt;';
        }
      });
    }
    tr.innerHTML = cells;
    tbody.appendChild(tr);
  });
  document.getElementById('counter').textContent = 'Найдено: '+items.length;
  updateSort();
  bindStars();
  bindQty();
  updateStickyBar();
  updateDiscountBanner();
  bindSortHeaders();
}

function updateSort(){
  document.querySelectorAll('#tbl th.sortable').forEach(function(th){
    th.classList.remove('asc','desc');
    if (th.dataset.key===state.sort.key) th.classList.add(state.sort.dir===1?'asc':'desc');
  });
}

function bindSortHeaders(){
  document.querySelectorAll('#tbl th.sortable').forEach(function(th){
    th.addEventListener('click',function(){
      var k = th.dataset.key;
      if (state.sort.key===k) state.sort.dir *= -1;
      else state.sort = {key:k, dir:1};
      render();
    });
  });
}

function bindStars(){
  document.querySelectorAll('.star').forEach(function(el){
    el.addEventListener('click',function(){
      var s = this.dataset.sec, n = parseInt(this.dataset.num,10);
      var k = keyOf(s,n);
      if (picked[k]!==undefined) delete picked[k];
      else picked[k] = 1;
      render();
    });
  });
}

function bindQty(){
  document.querySelectorAll('input.qty').forEach(function(inp){
    inp.addEventListener('input',function(){
      var s = this.dataset.sec, n = parseInt(this.dataset.num,10);
      var k = keyOf(s,n);
      if (picked[k]===undefined) return;
      var v = Math.max(1, parseInt(this.value,10)||1);
      picked[k] = v;
      render();
    });
  });
}

function exitGlobalSearch(){
  state.search='';
  var s = document.getElementById('search');
  if (s) s.value='';
  renderApp(); updateStats(); render();
}

/* ---------- БЛОК СКИДКИ ---------- */
function updateDiscountBanner(){
  var baseSum = calcBaseSum();
  var discountActive = isDiscountActive(baseSum);
  var remaining = Math.max(0, PROJECT.discountThreshold - baseSum);
  var progressPct = Math.min(100, (baseSum / PROJECT.discountThreshold) * 100);

  var banner = document.getElementById('discountBanner');
  if (banner){ if (discountActive) banner.classList.add('active'); else banner.classList.remove('active'); }
  var fill = document.getElementById('progressFill');
  if (fill) fill.style.width = progressPct.toFixed(1)+'%';
  var lbl = document.getElementById('progressLabel');
  if (lbl){
    if (baseSum === 0) lbl.innerHTML = 'Отметьте позиции — узнаете скидку';
    else if (discountActive) lbl.innerHTML = '✓ &lt;b&gt;СКИДКА АКТИВНА!&lt;/b&gt; −10%';
    else lbl.innerHTML = 'Набрано: &lt;b&gt;'+fmt(baseSum)+' ₽&lt;/b&gt; из '+fmt(PROJECT.discountThreshold)+' ₽';
  }
  var b = document.getElementById('discBase');
  if (b) b.textContent = fmt(baseSum)+' ₽';
  var r = document.getElementById('discRemain');
  if (r) r.textContent = discountActive ? '✓ Достигнуто' : fmt(remaining)+' ₽';
  var rate = document.getElementById('discRate');
  if (rate){
    if (discountActive){ rate.innerHTML = '−'+fmt(getDiscount(baseSum))+' ₽'; rate.style.color = '#7dff7d'; }
    else { rate.textContent = '0 ₽'; rate.style.color = ''; }
  }
}

/* ---------- STICKY-БАР ---------- */
function updateStickyBar(){
  var keys = Object.keys(picked);
  var count = keys.length;
  var totalQty = 0;
  var baseSum = 0;
  keys.forEach(function(k){
    var parts = k.split(':');
    var sec = PROJECT.sections[parts[0]];
    if (!sec) return;
    var r = sec.data.find(function(x){return x.num===parseInt(parts[1],10);});
    if (!r) return;
    var q = picked[k]||1;
    totalQty += q;
    baseSum += (r.price||0) * q;
  });
  var discountActive = isDiscountActive(baseSum);
  var discountAmount = getDiscount(baseSum);
  var totalSum = baseSum - discountAmount;

  document.getElementById('barCount').textContent = count;
  document.getElementById('barQty').textContent = totalQty;
  document.getElementById('barBase').textContent = fmt(baseSum)+' ₽';
  document.getElementById('barDiscount').textContent = discountActive ? '−'+fmt(discountAmount)+' ₽' : '0 ₽';
  document.getElementById('barDiscountLabel').textContent = discountActive ? '✓ Скидка 10%' : 'Скидка';
  document.getElementById('barTotal').textContent = fmt(totalSum)+' ₽';

  var bar = document.getElementById('stickyBar');
  if (count &gt; 0) bar.classList.add('show');
  else bar.classList.remove('show');
  if (discountActive) bar.classList.add('discount-active');
  else bar.classList.remove('discount-active');

  var sel = document.getElementById('selectedCount');
  if (sel) sel.textContent = count;
}

function clearPicked(){
  if (!Object.keys(picked).length) return;
  if (!confirm('Очистить все отмеченные позиции?')) return;
  picked = {};
  render();
}

/* ---------- СТАТИСТИКА ---------- */
function updateStats(){
  var sec = currentSection();
  var d = sec.data;
  document.getElementById('statTotal').textContent = d.length;
  document.getElementById('statStock').textContent = d.reduce(function(s,r){return s+(r.stock||0);},0)+' шт';
  var vals = d.map(function(r){return r.capacity!=null?r.capacity:(r.diam!=null?r.diam:r.D);}).filter(function(v){return v!=null;});
  if (vals.length){
    var unit = (state.section==='cables'||state.section==='wheels')?' мм':(state.section==='zkz'?'':' т');
    document.getElementById('statCap').textContent = Math.min.apply(null,vals)+'–'+Math.max.apply(null,vals)+unit;
  } else {
    document.getElementById('statCap').textContent = '—';
  }
  var prices = d.map(function(r){return r.price;}).filter(function(p){return p&gt;0;});
  document.getElementById('statPrice').textContent = prices.length ? fmt(Math.min.apply(null,prices))+' ₽' : 'по запросу';
}

/* ---------- КНОПКИ ---------- */
function scrollToTable(){ document.getElementById('catalog').scrollIntoView({behavior:'smooth',block:'start'}); }
function resetFilters(){
  state.search=''; state.filters={}; state.quickFilter=null; state.subcat='Все';
  renderApp(); updateStats(); render();
}
function applyQuick(i){
  resetFilters();
  state.quickFilter = currentSection().quickFilters[i];
  render();
}

/* ---------- СБОР ВЫБРАННОГО ---------- */
function collectPicked(){
  var out = [];
  Object.keys(picked).forEach(function(k){
    var parts = k.split(':');
    var sec = PROJECT.sections[parts[0]];
    if (!sec) return;
    var r = sec.data.find(function(x){return x.num===parseInt(parts[1],10);});
    if (!r) return;
    out.push({section:parts[0], sectionLabel:sec.label, row:r, qty:picked[k]||1});
  });
  return out;
}

/* ---------- СКАЧАТЬ ЗАПРОС ---------- */
function downloadRequest(){
  var items = collectPicked();
  if (!items.length){
    alert('Сначала отметьте нужные позиции звёздочкой ★ и укажите количество.');
    scrollToTable();
    return;
  }
  var baseSum = calcBaseSum();
  var discountActive = isDiscountActive(baseSum);
  var discountAmount = getDiscount(baseSum);

  var header = ['Раздел','№','Марка','Г/п или Ø','Характеристики','Цена с НДС, ₽','Кол-во, шт','Сумма, ₽','Сроки'];
  var body = items.map(function(it){
    var r = it.row;
    var hasPrice = (r.price||0)&gt;0;
    var finalPrice = discountActive &amp;&amp; hasPrice ? Math.round(r.price * (1 - PROJECT.discountPercent/100)) : r.price;
    var gp = r.capacity!=null ? r.capacity+' т' : (r.diam!=null ? 'Ø'+r.diam+' мм' : (r.D!=null ? 'D'+r.D+' мм' : (r.du ? 'Dу '+r.du : (r.model ? r.model : '—'))));
    var priceTxt = hasPrice ? finalPrice : 'по запросу';
    var sumTxt = hasPrice ? Math.round(finalPrice*it.qty) : 'по запросу';
    return [it.sectionLabel, r.num, r.name, gp, rowChars(it.section, r), priceTxt, it.qty, sumTxt, r.term];
  });
  body.push([]);
  body.push(['','','','','ИТОГО:', '', '', Math.round(baseSum - discountAmount), discountActive?'Скидка 10%':'']);

  var esc = function(v){return '"'+String(v==null?'':v).replace(/"/g,'""')+'"';};
  var csv = [header].concat(body).map(function(r){return r.map(esc).join(';');}).join('\r\n');
  var blob = new Blob(['\uFEFF'+csv],{type:'text/csv;charset=utf-8;'});
  var url = URL.createObjectURL(blob);
  var a = document.createElement('a');
  a.href = url;
  a.download = 'Запрос_КП_Арсенал_'+today()+'.csv';
  document.body.appendChild(a); a.click(); a.remove();
  setTimeout(function(){URL.revokeObjectURL(url);},500);
}

/* ---------- ОТПРАВИТЬ НА E-MAIL ---------- */
function sendByEmail(){
  var items = collectPicked();
  if (!items.length){
    alert('Сначала отметьте нужные позиции звёздочкой ★.');
    scrollToTable();
    return;
  }
  var baseSum = calcBaseSum();
  var discountActive = isDiscountActive(baseSum);
  var discountAmount = getDiscount(baseSum);
  var totalQty = 0;
  var lines = ['Здравствуйте!','','Прошу подготовить коммерческое предложение:',''];
  items.forEach(function(it){
    var r = it.row;
    totalQty += it.qty;
    var hasPrice = (r.price||0)&gt;0;
    var finalPrice = discountActive &amp;&amp; hasPrice ? Math.round(r.price * (1 - PROJECT.discountPercent/100)) : r.price;
    var priceTxt = hasPrice ? finalPrice+' ₽ × '+it.qty+' шт = '+fmt(finalPrice*it.qty)+' ₽' : 'по запросу × '+it.qty+' шт';
    lines.push('['+it.sectionLabel+'] №'+r.num+' · '+r.name+' · '+priceTxt);
  });
  lines.push('');
  lines.push('Всего позиций: '+items.length);
  lines.push('Всего штук: '+totalQty);
  lines.push('Сумма без скидки: '+fmt(baseSum)+' ₽');
  if (discountActive) lines.push('Скидка 10%: −'+fmt(discountAmount)+' ₽');
  lines.push('ИТОГО с НДС 22%: '+fmt(baseSum - discountAmount)+' ₽');
  lines.push('');
  lines.push('Прошу указать сроки изготовления и условия отгрузки.');
  lines.push('');
  lines.push('С уважением,');
  var subject = encodeURIComponent('Запрос КП — '+items.length+' поз.');
  var body = encodeURIComponent(lines.join('\n'));
  window.location.href = 'mailto:'+PROJECT.email+'?subject='+subject+'&amp;body='+body;
}

/* ---------- УТИЛИТЫ ---------- */
function today(){
  var d=new Date(), p=function(n){return String(n).padStart(2,'0');};
  return d.getFullYear()+'-'+p(d.getMonth()+1)+'-'+p(d.getDate());
}

/* ---------- СОБЫТИЯ ---------- */
document.addEventListener('DOMContentLoaded', function(){
  renderApp();
  updateStats();
  render();

  function bindFilters(){
    var s = document.getElementById('search');
    if (s) s.addEventListener('input',function(e){ state.search=e.target.value; render(); });
    var cap = document.getElementById('fCapacity');
    if (cap) cap.addEventListener('input',function(e){state.filters.capacity=e.target.value;render();});
    var len = document.getElementById('fLength');
    if (len) len.addEventListener('input',function(e){state.filters.length=e.target.value;render();});
    var st = document.getElementById('fStock');
    if (st) st.addEventListener('change',function(e){state.filters.stock=e.target.value;render();});
    var tm = document.getElementById('fTerm');
    if (tm) tm.addEventListener('change',function(e){state.filters.term=e.target.value;render();});
    var ty = document.getElementById('fType');
    if (ty) ty.addEventListener('input',function(e){state.filters.type=e.target.value;render();});
  }

  var _origSwitch = window.switchSection;
  window.switchSection = function(sk){
    _origSwitch(sk);
    bindFilters();
  };
  var _origSub = window.setSubcat;
  window.setSubcat = function(c){
    _origSub(c);
    bindFilters();
  };

  bindFilters();
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</subtitle>
  <updated>2026-11-01T09:35:14Z</updated>
  <logo>https://pandoraburo.ru/ssl/u/pic/07/26436cc3c611f19d9efcd8c4a10874/-/0c723f71762611f1b3964aaba1665535.jpg</logo>
  <author>
    <name>1592962</name>
    <uri>https://www.pandoraburo.ru/</uri>
  </author>
</feed>
