<?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/polusfery-stalnye-i-nerzhaveyuschie</id>
  <link href="https://www.pandoraburo.ru/polusfery-stalnye-i-nerzhaveyuschie.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;Полусферы стальные и нержавеющие Ø 500–1500 — Арсенал-Деталь&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}

  .min-order-banner{
    background:linear-gradient(135deg,rgba(255,140,0,.15),rgba(10,10,10,.9));
    border:2px dashed var(--accent);border-radius:12px;
    padding:12px 18px;margin-bottom:16px;text-align:center;
    color:var(--gold-light);font-size:14px;font-weight:600;
  }
  .min-order-banner b{color:var(--accent);font-size:15px;}

  .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;}

  .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;
  }

  #minOrderInfo{margin-top:12px;font-size:13px;font-weight:700;text-align:center;}

  .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);}

  .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,.min-order-banner{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;
/* ============================================================
   АРСЕНАЛ-ДЕТАЛЬ · Полусферы
   - Ø 500–1500 мм
   - Толщина выбирается в строке таблицы → пересчёт
   - Поиск по размеру / толщине / материалу / поверхности
   - Скидка от суммы ≥ 50 000 ₽ → 10%
   - Минимальный заказ 150 000 ₽
   ============================================================ */

var PROJECT = {
  id: 'arsenal-hemispheres',
  title: 'Полусферы стальные и нержавеющие',
  subtitle: 'Ø 500–1500 мм · сталь до 12 мм · нерж. до 10 мм · ротационная вытяжка',
  vat: 22,
  discountThreshold: 50000,
  discountPercent: 10,
  minOrder: 150000,

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

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

  /* Расчётные параметры цены */
  hemiPricing: {
    materialRate: {
      'Ст3': 85,
      '09Г2С': 110,
      'AISI304': 420,
      'AISI316': 620,
      '12Х18Н10Т': 480,
      'АМГ5': 380,
      'Медь': 950,
      'Латунь': 780
    },
    thicknessFactor: { 1.5: 1.0, 2: 1.0, 3: 1.15, 5: 1.45, 8: 1.9, 10: 2.3, 12: 2.8 },
    laborPerPiece: 4500,
    surfaceFactor: { 'Без обработки': 1.0, 'Шлифовка': 1.2, 'Полировка': 1.45, 'Окраска': 1.15 },
    /* базовый вес при толщине 1 мм для полусферы, кг/мм */
    weightPerMm: {
      500: 6.0,
      600: 8.5,
      700: 11.7,
      800: 15.5,
      900: 19.5,
      1000: 24.0,
      1100: 29.0,
      1200: 34.5,
      1300: 40.5,
      1400: 47.0,
      1500: 54.0
    }
  },

  sections: {
    hemispheres: {
      label: 'Полусферы',
      icon: '●',
      title: 'Полусферы стальные и нержавеющие',
      subtitle: 'Ø 500–1500 мм · сталь до 12 мм · нерж. до 10 мм · ротационная вытяжка',
      tag: 'КАТАЛОГ · ПОД ЗАКАЗ · Ø 500–1500',
      /* Толщины: для стали — 1.5–12, для нержи — 1.5–10 */
      thicknessSteel: [1.5, 2, 3, 5, 8, 10, 12],
      thicknessSteelShort: [1.5, 2, 3, 5, 8, 10, 12],
      thicknessSteelFull: [1.5, 2, 3, 5, 8, 10, 12],
      thicknessStainless: [1.5, 2, 3, 5, 8, 10],
      columns: [
        {key:'num',           label:'№',              type:'num',  cls:'col-num'},
        {key:'name',          label:'Наименование',   type:'text'},
        {key:'material',      label:'Материал',       type:'text'},
        {key:'diam',          label:'Ø, мм',          type:'num',  sortable:true},
        {key:'thickness',     label:'Толщина, мм',    type:'select'},
        {key:'process',       label:'Технология',     type:'text'},
        {key:'surface',       label:'Обработка',      type:'text'},
        {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:'Ø до 700',      field:'diamMax',       value:700},
        {label:'Ø от 1000',     field:'diamMin',       value:1000},
        {label:'Нержавейка',    field:'materialGroup', value:'Нержавеющая'},
        {label:'Чёрная сталь',  field:'materialGroup', value:'Чёрная'},
        {label:'Толщина до 3',  field:'thMax',         value:3}
      ],
      data: [
        /* ===== Ст3 ===== */
        {num:1,  name:'Полусфера Ø 500',  material:'Ст3',     material_group:'Чёрная',      diam:500,  thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:12,  stock:0, price:0, term:'Под заказ'},
        {num:2,  name:'Полусфера Ø 600',  material:'Ст3',     material_group:'Чёрная',      diam:600,  thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:17,  stock:0, price:0, term:'Под заказ'},
        {num:3,  name:'Полусфера Ø 700',  material:'Ст3',     material_group:'Чёрная',      diam:700,  thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:24,  stock:0, price:0, term:'Под заказ'},
        {num:4,  name:'Полусфера Ø 800',  material:'Ст3',     material_group:'Чёрная',      diam:800,  thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:31,  stock:0, price:0, term:'Под заказ'},
        {num:5,  name:'Полусфера Ø 900',  material:'Ст3',     material_group:'Чёрная',      diam:900,  thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:39,  stock:0, price:0, term:'Под заказ'},
        {num:6,  name:'Полусфера Ø 1000', material:'Ст3',     material_group:'Чёрная',      diam:1000, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:48,  stock:0, price:0, term:'Под заказ'},
        {num:7,  name:'Полусфера Ø 1100', material:'Ст3',     material_group:'Чёрная',      diam:1100, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:58,  stock:0, price:0, term:'Под заказ'},
        {num:8,  name:'Полусфера Ø 1200', material:'Ст3',     material_group:'Чёрная',      diam:1200, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:70,  stock:0, price:0, term:'Под заказ'},
        {num:9,  name:'Полусфера Ø 1300', material:'Ст3',     material_group:'Чёрная',      diam:1300, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:82,  stock:0, price:0, term:'Под заказ'},
        {num:10, name:'Полусфера Ø 1400', material:'Ст3',     material_group:'Чёрная',      diam:1400, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:95,  stock:0, price:0, term:'Под заказ'},
        {num:11, name:'Полусфера Ø 1500', material:'Ст3',     material_group:'Чёрная',      diam:1500, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:109, stock:0, price:0, term:'Под заказ'},
        {num:12, name:'Полусфера Ø 500',  material:'Ст3',     material_group:'Чёрная',      diam:500,  thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:18,  stock:0, price:0, term:'Под заказ'},
        {num:13, name:'Полусфера Ø 600',  material:'Ст3',     material_group:'Чёрная',      diam:600,  thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:26,  stock:0, price:0, term:'Под заказ'},
        {num:14, name:'Полусфера Ø 700',  material:'Ст3',     material_group:'Чёрная',      diam:700,  thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:35,  stock:0, price:0, term:'Под заказ'},
        {num:15, name:'Полусфера Ø 800',  material:'Ст3',     material_group:'Чёрная',      diam:800,  thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:46,  stock:0, price:0, term:'Под заказ'},
        {num:16, name:'Полусфера Ø 900',  material:'Ст3',     material_group:'Чёрная',      diam:900,  thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:58,  stock:0, price:0, term:'Под заказ'},
        {num:17, name:'Полусфера Ø 1000', material:'Ст3',     material_group:'Чёрная',      diam:1000, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:72,  stock:0, price:0, term:'Под заказ'},
        {num:18, name:'Полусфера Ø 1100', material:'Ст3',     material_group:'Чёрная',      diam:1100, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:87,  stock:0, price:0, term:'Под заказ'},
        {num:19, name:'Полусфера Ø 1200', material:'Ст3',     material_group:'Чёрная',      diam:1200, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:104, stock:0, price:0, term:'Под заказ'},
        {num:20, name:'Полусфера Ø 1300', material:'Ст3',     material_group:'Чёрная',      diam:1300, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:122, stock:0, price:0, term:'Под заказ'},
        {num:21, name:'Полусфера Ø 1400', material:'Ст3',     material_group:'Чёрная',      diam:1400, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:142, stock:0, price:0, term:'Под заказ'},
        {num:22, name:'Полусфера Ø 1500', material:'Ст3',     material_group:'Чёрная',      diam:1500, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:163, stock:0, price:0, term:'Под заказ'},

        /* ===== 09Г2С ===== */
        {num:23, name:'Полусфера Ø 500',  material:'09Г2С',   material_group:'Чёрная',      diam:500,  thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:18,  stock:0, price:0, term:'Под заказ'},
        {num:24, name:'Полусфера Ø 600',  material:'09Г2С',   material_group:'Чёрная',      diam:600,  thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:26,  stock:0, price:0, term:'Под заказ'},
        {num:25, name:'Полусфера Ø 700',  material:'09Г2С',   material_group:'Чёрная',      diam:700,  thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:35,  stock:0, price:0, term:'Под заказ'},
        {num:26, name:'Полусфера Ø 800',  material:'09Г2С',   material_group:'Чёрная',      diam:800,  thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:46,  stock:0, price:0, term:'Под заказ'},
        {num:27, name:'Полусфера Ø 900',  material:'09Г2С',   material_group:'Чёрная',      diam:900,  thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:58,  stock:0, price:0, term:'Под заказ'},
        {num:28, name:'Полусфера Ø 1000', material:'09Г2С',   material_group:'Чёрная',      diam:1000, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:72,  stock:0, price:0, term:'Под заказ'},
        {num:29, name:'Полусфера Ø 1100', material:'09Г2С',   material_group:'Чёрная',      diam:1100, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:87,  stock:0, price:0, term:'Под заказ'},
        {num:30, name:'Полусфера Ø 1200', material:'09Г2С',   material_group:'Чёрная',      diam:1200, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:104, stock:0, price:0, term:'Под заказ'},
        {num:31, name:'Полусфера Ø 1300', material:'09Г2С',   material_group:'Чёрная',      diam:1300, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:122, stock:0, price:0, term:'Под заказ'},
        {num:32, name:'Полусфера Ø 1400', material:'09Г2С',   material_group:'Чёрная',      diam:1400, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:142, stock:0, price:0, term:'Под заказ'},
        {num:33, name:'Полусфера Ø 1500', material:'09Г2С',   material_group:'Чёрная',      diam:1500, thickness:3, process:'Ротационная вытяжка', surface:'Без обработки', weight:163, stock:0, price:0, term:'Под заказ'},
        {num:34, name:'Полусфера Ø 500',  material:'09Г2С',   material_group:'Чёрная',      diam:500,  thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:12,  stock:0, price:0, term:'Под заказ'},
        {num:35, name:'Полусфера Ø 600',  material:'09Г2С',   material_group:'Чёрная',      diam:600,  thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:17,  stock:0, price:0, term:'Под заказ'},
        {num:36, name:'Полусфера Ø 700',  material:'09Г2С',   material_group:'Чёрная',      diam:700,  thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:24,  stock:0, price:0, term:'Под заказ'},
        {num:37, name:'Полусфера Ø 800',  material:'09Г2С',   material_group:'Чёрная',      diam:800,  thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:31,  stock:0, price:0, term:'Под заказ'},
        {num:38, name:'Полусфера Ø 900',  material:'09Г2С',   material_group:'Чёрная',      diam:900,  thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:39,  stock:0, price:0, term:'Под заказ'},
        {num:39, name:'Полусфера Ø 1000', material:'09Г2С',   material_group:'Чёрная',      diam:1000, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:48,  stock:0, price:0, term:'Под заказ'},
        {num:40, name:'Полусфера Ø 1100', material:'09Г2С',   material_group:'Чёрная',      diam:1100, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:58,  stock:0, price:0, term:'Под заказ'},
        {num:41, name:'Полусфера Ø 1200', material:'09Г2С',   material_group:'Чёрная',      diam:1200, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:70,  stock:0, price:0, term:'Под заказ'},
        {num:42, name:'Полусфера Ø 1300', material:'09Г2С',   material_group:'Чёрная',      diam:1300, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:82,  stock:0, price:0, term:'Под заказ'},
        {num:43, name:'Полусфера Ø 1400', material:'09Г2С',   material_group:'Чёрная',      diam:1400, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:95,  stock:0, price:0, term:'Под заказ'},
        {num:44, name:'Полусфера Ø 1500', material:'09Г2С',   material_group:'Чёрная',      diam:1500, thickness:2, process:'Ротационная вытяжка', surface:'Без обработки', weight:109, stock:0, price:0, term:'Под заказ'},

        /* ===== AISI304 ===== */
        {num:45, name:'Полусфера Ø 500',  material:'AISI304', material_group:'Нержавеющая', diam:500,  thickness:2, process:'Ротационная вытяжка', surface:'Шлифовка', weight:12,  stock:0, price:0, term:'Под заказ'},
        {num:46, name:'Полусфера Ø 600',  material:'AISI304', material_group:'Нержавеющая', diam:600,  thickness:2, process:'Ротационная вытяжка', surface:'Шлифовка', weight:17,  stock:0, price:0, term:'Под заказ'},
        {num:47, name:'Полусфера Ø 700',  material:'AISI304', material_group:'Нержавеющая', diam:700,  thickness:2, process:'Ротационная вытяжка', surface:'Шлифовка', weight:24,  stock:0, price:0, term:'Под заказ'},
        {num:48, name:'Полусфера Ø 800',  material:'AISI304', material_group:'Нержавеющая', diam:800,  thickness:2, process:'Ротационная вытяжка', surface:'Шлифовка', weight:31,  stock:0, price:0, term:'Под заказ'},
        {num:49, name:'Полусфера Ø 900',  material:'AISI304', material_group:'Нержавеющая', diam:900,  thickness:2, process:'Ротационная вытяжка', surface:'Шлифовка', weight:39,  stock:0, price:0, term:'Под заказ'},
        {num:50, name:'Полусфера Ø 1000', material:'AISI304', material_group:'Нержавеющая', diam:1000, thickness:2, process:'Ротационная вытяжка', surface:'Шлифовка', weight:48,  stock:0, price:0, term:'Под заказ'},
        {num:51, name:'Полусфера Ø 1100', material:'AISI304', material_group:'Нержавеющая', diam:1100, thickness:2, process:'Ротационная вытяжка', surface:'Шлифовка', weight:58,  stock:0, price:0, term:'Под заказ'},
        {num:52, name:'Полусфера Ø 1200', material:'AISI304', material_group:'Нержавеющая', diam:1200, thickness:2, process:'Ротационная вытяжка', surface:'Шлифовка', weight:70,  stock:0, price:0, term:'Под заказ'},
        {num:53, name:'Полусфера Ø 1300', material:'AISI304', material_group:'Нержавеющая', diam:1300, thickness:2, process:'Ротационная вытяжка', surface:'Шлифовка', weight:82,  stock:0, price:0, term:'Под заказ'},
        {num:54, name:'Полусфера Ø 1400', material:'AISI304', material_group:'Нержавеющая', diam:1400, thickness:2, process:'Ротационная вытяжка', surface:'Шлифовка', weight:95,  stock:0, price:0, term:'Под заказ'},
        {num:55, name:'Полусфера Ø 1500', material:'AISI304', material_group:'Нержавеющая', diam:1500, thickness:2, process:'Ротационная вытяжка', surface:'Шлифовка', weight:109, stock:0, price:0, term:'Под заказ'},
        {num:56, name:'Полусфера Ø 500',  material:'AISI304', material_group:'Нержавеющая', diam:500,  thickness:3, process:'Ротационная вытяжка', surface:'Шлифовка', weight:18,  stock:0, price:0, term:'Под заказ'},
        {num:57, name:'Полусфера Ø 600',  material:'AISI304', material_group:'Нержавеющая', diam:600,  thickness:3, process:'Ротационная вытяжка', surface:'Шлифовка', weight:26,  stock:0, price:0, term:'Под заказ'},
        {num:58, name:'Полусфера Ø 700',  material:'AISI304', material_group:'Нержавеющая', diam:700,  thickness:3, process:'Ротационная вытяжка', surface:'Шлифовка', weight:35,  stock:0, price:0, term:'Под заказ'},
        {num:59, name:'Полусфера Ø 800',  material:'AISI304', material_group:'Нержавеющая', diam:800,  thickness:3, process:'Ротационная вытяжка', surface:'Шлифовка', weight:46,  stock:0, price:0, term:'Под заказ'},
        {num:60, name:'Полусфера Ø 900',  material:'AISI304', material_group:'Нержавеющая', diam:900,  thickness:3, process:'Ротационная вытяжка', surface:'Шлифовка', weight:58,  stock:0, price:0, term:'Под заказ'},
        {num:61, name:'Полусфера Ø 1000', material:'AISI304', material_group:'Нержавеющая', diam:1000, thickness:3, process:'Ротационная вытяжка', surface:'Шлифовка', weight:72,  stock:0, price:0, term:'Под заказ'},
        {num:62, name:'Полусфера Ø 1100', material:'AISI304', material_group:'Нержавеющая', diam:1100, thickness:3, process:'Ротационная вытяжка', surface:'Шлифовка', weight:87,  stock:0, price:0, term:'Под заказ'},
        {num:63, name:'Полусфера Ø 1200', material:'AISI304', material_group:'Нержавеющая', diam:1200, thickness:3, process:'Ротационная вытяжка', surface:'Шлифовка', weight:104, stock:0, price:0, term:'Под заказ'},
        {num:64, name:'Полусфера Ø 1300', material:'AISI304', material_group:'Нержавеющая', diam:1300, thickness:3, process:'Ротационная вытяжка', surface:'Шлифовка', weight:122, stock:0, price:0, term:'Под заказ'},
        {num:65, name:'Полусфера Ø 1400', material:'AISI304', material_group:'Нержавеющая', diam:1400, thickness:3, process:'Ротационная вытяжка', surface:'Шлифовка', weight:142, stock:0, price:0, term:'Под заказ'},
        {num:66, name:'Полусфера Ø 1500', material:'AISI304', material_group:'Нержавеющая', diam:1500, thickness:3, process:'Ротационная вытяжка', surface:'Шлифовка', weight:163, 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:'hemispheres'};
var picked = {};

/* Толщина и материал, выбранные пользователем по каждой позиции */
var userThickness = {};   // { num: thickness }
var userMaterial  = {};   // { num: material }

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 calcWeight(r, thickness){
  var pr = PROJECT.hemiPricing;
  var base = pr.weightPerMm[r.diam];
  if (!base) return r.weight || 0;
  return Math.round(base * thickness * 100) / 100;
}

function calcHemiPrice(r, thickness, material, surface){
  var pr = PROJECT.hemiPricing;
  thickness = thickness || r.thickness;
  material  = material  || r.material;
  surface   = surface   || r.surface;
  var rate = pr.materialRate[material] || 0;
  if (!rate) return 0;
  var w = calcWeight(r, thickness);
  var tf = pr.thicknessFactor[thickness] || 1;
  var sf = pr.surfaceFactor[surface] || 1;
  var base = w * rate * tf * sf + pr.laborPerPiece;
  return Math.round(base / 100) * 100;
}

function getRowThickness(r){ return userThickness[r.num] || r.thickness; }
function getRowMaterial(r){ return userMaterial[r.num] || r.material; }
function getRowSurface(r){ return r.surface; }

/* ---------- ПОИСК ---------- */
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.material, r.material_group, r.diam,
    getRowThickness(r), r.process, r.surface, calcWeight(r, getRowThickness(r)), r.term
  ];
  var base = norm(parts.join(' '));
  var extra = '';
  [r.diam, getRowThickness(r), calcWeight(r, getRowThickness(r))].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;
    var th = getRowThickness(r);
    var mat = getRowMaterial(r);
    var price = calcHemiPrice(r, th, mat);
    total += price * (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 = '';
  p.sections.hemispheres.data.slice(0,6).forEach(function(r){
    var price = calcHemiPrice(r, getRowThickness(r), getRowMaterial(r));
    tickerItems += '&lt;span class="ticker-item"&gt;'+r.name+' · '+r.material+' · '+getRowThickness(r)+' мм — &lt;b&gt;'+fmt(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;КАТАЛОГ · ПОЛУСФЕРЫ&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="min-order-banner"&gt;⚠ Минимальная сумма заказа — &lt;b&gt;150 000 ₽&lt;/b&gt;. Меньшие суммы — по согласованию с менеджером.&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;'+p.sections.hemispheres.title+'&lt;/h2&gt;'+
    '&lt;p&gt;Кликните &lt;b&gt;★&lt;/b&gt;, укажите количество — сумма появится внизу экрана.&lt;br&gt;'+
    'Толщину можно изменить прямо в строке — цена и масса пересчитаются.&lt;/p&gt;'+
    '&lt;div class="cta-counter"&gt;Выбрано: &lt;b id="selectedCount"&gt;0&lt;/b&gt; из '+p.sections.hemispheres.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="requestCustom()"&gt;✎ Запросить нестандарт&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="? Поиск: 1000, 700, 3, AISI304, 09Г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; (1000, 700), &lt;b&gt;толщине&lt;/b&gt; (2, 3, 5), &lt;b&gt;марке стали&lt;/b&gt; (09Г2С, AISI304, 12Х18Н10Т), &lt;b&gt;поверхности&lt;/b&gt; (шлифовка, полировка). Несколько слов — &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="fDiam" placeholder="напр. 1000"&gt;&lt;/div&gt;'+
      '&lt;div class="fld"&gt;&lt;label&gt;Толщина, мм&lt;/label&gt;&lt;input type="number" id="fThickness" placeholder="напр. 3"&gt;&lt;/div&gt;'+
      '&lt;div class="fld"&gt;&lt;label&gt;Материал&lt;/label&gt;&lt;input type="text" id="fMaterial" placeholder="09Г2С, AISI304…"&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;/select&gt;&lt;/div&gt;'+
    '&lt;/div&gt;'+
    '&lt;div class="filter-actions"&gt;'+
      p.sections.hemispheres.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="block-title" id="blockTitle"&gt;'+p.sections.hemispheres.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;/div&gt;'+
      '&lt;div class="fn"&gt;Минимальный заказ — &lt;b&gt;150 000 ₽&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полусферы" 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 ₽. Минимальный заказ 150 000 ₽. ООО «Арсенал Деталь».&lt;/p&gt;&lt;/div&gt;';

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

/* ---------- ФИЛЬТРАЦИЯ ---------- */
function getFiltered(){
  var tokens = tokenize(state.search);
  var sec = currentSection();
  var items = sec.data.map(function(r){ return {section:state.section, sectionLabel:sec.label, row:r}; });
  if (tokens.length) {
    items = items.filter(function(it){ return rowMatches(it.row, tokens); });
  }
  if (state.filters.diam){
    var d = parseFloat(state.filters.diam); if(!isNaN(d)) items=items.filter(function(it){return it.row.diam===d;});
  }
  if (state.filters.thickness){
    var t = parseFloat(state.filters.thickness); if(!isNaN(t)) items=items.filter(function(it){return getRowThickness(it.row)===t;});
  }
  if (state.filters.material){
    var m = norm(state.filters.material); if(m) items=items.filter(function(it){return norm(getRowMaterial(it.row)).indexOf(m)!==-1;});
  }
  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.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==='diamMax') return r.diam&lt;=qf.value;
      if (qf.field==='diamMin') return r.diam&gt;=qf.value;
      if (qf.field==='materialGroup') return r.material_group===qf.value;
      if (qf.field==='thMax') return getRowThickness(r)&lt;=qf.value;
      return true;
    });
  }
  if (state.sort.key){
    var k=state.sort.key, d=state.sort.dir;
    items.sort(function(a,b){
      var va = (k==='thickness') ? getRowThickness(a.row) : (k==='weight' ? calcWeight(a.row, getRowThickness(a.row)) : a.row[k]);
      var vb = (k==='thickness') ? getRowThickness(b.row) : (k==='weight' ? calcWeight(b.row, getRowThickness(b.row)) : 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};
}

/* ---------- РЕНДЕР ТАБЛИЦЫ ---------- */
function render(){
  var res = getFiltered();
  var items = res.items, tokens = res.tokens;
  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 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){
    tbody.innerHTML = '&lt;tr&gt;&lt;td colspan="'+(sec.columns.length+2)+'" style="text-align:center;padding:40px;opacity:.6"&gt;Ничего не найдено. Попробуйте другой запрос — например, «1000», «700 3», «AISI304», «09Г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 th = getRowThickness(r);
    var mat = getRowMaterial(r);
    var w = calcWeight(r, th);
    var calcPrice = calcHemiPrice(r, th, mat);
    var finalPrice = discountActive ? Math.round(calcPrice * (1 - PROJECT.discountPercent/100)) : calcPrice;
    var tr = document.createElement('tr');
    if (isPicked) tr.className = discountActive ? 'picked discount-active' : 'picked';

    /* Опции толщины */
    var thList = r.material_group==='Нержавеющая'
      ? sec.thicknessStainless
      : sec.thicknessSteel;
    var thOptions = thList.map(function(t){
      return '&lt;option value="'+t+'"'+(t===th?' selected':'')+'&gt;'+t+'&lt;/option&gt;';
    }).join('');

    var cells =
      '&lt;td class="col-star"&gt;&lt;span class="star'+(isPicked?' on':'')+'" 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-num="'+r.num+'" value="'+qty+'" min="1" max="9999"'+(isPicked?'':' disabled')+'&gt;&lt;/td&gt;';

    sec.columns.forEach(function(c){
      if (c.type==='select'){
        cells += '&lt;td class="num"&gt;&lt;select class="th-select" data-num="'+r.num+'"&gt;'+thOptions+'&lt;/select&gt;&lt;/td&gt;';
      } else if (c.type==='num') {
        var v = c.key==='weight' ? w : r[c.key];
        cells += '&lt;td class="num '+(c.cls||'')+'"&gt;'+v+'&lt;/td&gt;';
      } else if (c.type==='price'){
        if (discountActive &amp;&amp; isPicked) {
          cells += '&lt;td class="num price discount" title="Расчётная цена"&gt;'+fmt(finalPrice)+' ₽&lt;/td&gt;';
        } else {
          cells += '&lt;td class="num price" title="Расчётная цена"&gt;'+fmt(finalPrice)+' ₽&lt;/td&gt;';
        }
      } else if (c.type==='badge'){
        var cls = r.stock&gt;=10 ? 'badge many' : r.stock===0 ? 'badge zero' : 'badge';
        var txt = r.stock&gt;0 ? r.stock : 'под заказ';
        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;'+r.num+'&lt;/b&gt;' : r[c.key];
        if (c.key==='name' &amp;&amp; tokens.length) txt = highlight(r.name, 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();
  bindThickness();
  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 n = parseInt(this.dataset.num,10);
      var k = keyOf('hemispheres', 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 n = parseInt(this.dataset.num,10);
      var k = keyOf('hemispheres', n);
      if (picked[k]===undefined) return;
      var v = Math.max(1, parseInt(this.value,10)||1);
      picked[k] = v;
      render();
    });
  });
}

function bindThickness(){
  document.querySelectorAll('.th-select').forEach(function(sel){
    sel.addEventListener('change',function(){
      var n = parseInt(this.dataset.num,10);
      var v = parseFloat(this.value);
      userThickness[n] = v;
      render();
    });
  });
}

/* ---------- БЛОК СКИДКИ ---------- */
function updateDiscountBanner(){
  var baseSum = calcBaseSum();
  var discountActive = isDiscountActive(baseSum);
  var minOrder = PROJECT.minOrder || 0;
  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 = ''; }
  }

  var mo = document.getElementById('minOrderInfo');
  if (!mo){
    mo = document.createElement('div');
    mo.id = 'minOrderInfo';
    var bannerEl = document.getElementById('discountBanner');
    if (bannerEl) bannerEl.appendChild(mo);
  }
  if (baseSum === 0){
    mo.textContent = 'Минимальный заказ: '+fmt(minOrder)+' ₽';
    mo.style.color = 'var(--muted)';
  } else if (baseSum &lt; minOrder){
    mo.innerHTML = '⚠ До минимального заказа: &lt;b style="color:#ff8c00"&gt;'+fmt(minOrder - baseSum)+' ₽&lt;/b&gt;';
    mo.style.color = '#ff9a9a';
  } else {
    mo.innerHTML = '✓ Минимальный заказ достигнут';
    mo.style.color = '#7dff7d';
  }
}

/* ---------- 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;
    var price = calcHemiPrice(r, getRowThickness(r), getRowMaterial(r));
    baseSum += price * 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.diam;}).filter(function(v){return v!=null;});
  document.getElementById('statCap').textContent = Math.min.apply(null,vals)+'–'+Math.max.apply(null,vals)+' мм';
  var calcPrices = d.map(function(r){return calcHemiPrice(r, getRowThickness(r), getRowMaterial(r));}).filter(function(p){return p&gt;0;});
  document.getElementById('statPrice').textContent = calcPrices.length ? 'от '+fmt(Math.min.apply(null,calcPrices))+' ₽' : 'по запросу';
}

/* ---------- КНОПКИ ---------- */
function scrollToTable(){ document.getElementById('catalog').scrollIntoView({behavior:'smooth',block:'start'}); }
function resetFilters(){
  state.search=''; state.filters={}; state.quickFilter=null;
  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,
      thickness:getRowThickness(r),
      material:getRowMaterial(r),
      weight:calcWeight(r, getRowThickness(r)),
      price:calcHemiPrice(r, getRowThickness(r), getRowMaterial(r))
    });
  });
  return out;
}

/* ---------- ПРЕДОХРАНИТЕЛЬ МИН. ЗАКАЗА ---------- */
function checkMinOrder(baseSum){
  var minOrder = PROJECT.minOrder || 0;
  if (baseSum &gt; 0 &amp;&amp; baseSum &lt; minOrder){
    return confirm('Сумма заказа '+fmt(baseSum)+' ₽ меньше минимальной ('+fmt(minOrder)+' ₽).\nВсё равно сформировать запрос?');
  }
  return true;
}

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

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

  var header = ['Раздел','№','Марка','Материал','Ø, мм','Толщина, мм','Технология','Обработка','Масса, кг','Цена с НДС, ₽','Кол-во, шт','Сумма, ₽','Сроки'];
  var body = items.map(function(it){
    var finalPrice = discountActive ? Math.round(it.price * (1 - PROJECT.discountPercent/100)) : it.price;
    return [it.sectionLabel, it.row.num, it.row.name, it.material, it.row.diam, it.thickness, it.row.process, it.row.surface, it.weight, finalPrice, it.qty, Math.round(finalPrice*it.qty), it.row.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 baseSumCheck = calcBaseSum();
  if (!checkMinOrder(baseSumCheck)) return;

  var baseSum = calcBaseSum();
  var discountActive = isDiscountActive(baseSum);
  var discountAmount = getDiscount(baseSum);
  var totalQty = 0;
  var lines = ['Здравствуйте!','','Прошу подготовить коммерческое предложение по полусферам:',''];
  items.forEach(function(it){
    totalQty += it.qty;
    var finalPrice = discountActive ? Math.round(it.price * (1 - PROJECT.discountPercent/100)) : it.price;
    lines.push('№'+it.row.num+' · '+it.row.name+' · '+it.material+' · Ø'+it.row.diam+' · '+it.thickness+' мм · '+finalPrice+' ₽ × '+it.qty+' шт = '+fmt(finalPrice*it.qty)+' ₽');
  });
  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 requestCustom(){
  var lines = [
    'Здравствуйте!',
    '',
    'Прошу рассчитать нестандартную полусферу:',
    '',
    '— Диаметр: ______ мм (вне матрицы 500–1500)',
    '— Материал: ______ (Ст3 / 09Г2С / AISI304 / AISI316 / 12Х18Н10Т / АМГ5 / медь / латунь)',
    '— Толщина стенки: ______ мм',
    '— Тип: полусфера / полый шар / сферическое днище',
    '— Технология: ротационная вытяжка / штамповка / сварная',
    '— Обработка поверхности: без обработки / шлифовка / полировка / окраска',
    '— Количество: ______ шт',
    '— Назначение: ______',
    '',
    'Прошу указать цену с НДС, срок изготовления и минимально возможную толщину.',
    '',
    'С уважением,'
  ];
  var subject = encodeURIComponent('Запрос нестандартной полусферы — Арсенал-Деталь');
  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 di = document.getElementById('fDiam');
    if (di) di.addEventListener('input',function(e){state.filters.diam=e.target.value;render();});
    var th = document.getElementById('fThickness');
    if (th) th.addEventListener('input',function(e){state.filters.thickness=e.target.value;render();});
    var mat = document.getElementById('fMaterial');
    if (mat) mat.addEventListener('input',function(e){state.filters.material=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();});
  }

  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>
