{"id":1863,"date":"2024-07-03T14:27:12","date_gmt":"2024-07-03T14:27:12","guid":{"rendered":"http:\/\/landing.anderskisling.dk\/?page_id=1863"},"modified":"2026-10-21T08:03:02","modified_gmt":"2026-10-21T08:03:02","slug":"audiowaveformexporter","status":"publish","type":"page","link":"https:\/\/landing.anderskisling.dk\/index.php\/audiowaveformexporter\/","title":{"rendered":"Audio Waveform Exporter"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"1863\" class=\"elementor elementor-1863\">\n\t\t\t\t<div class=\"elementor-element elementor-element-d701464 e-flex e-con-boxed e-con e-parent\" data-id=\"d701464\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-908f585 elementor-widget elementor-widget-heading\" data-id=\"908f585\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">wydgy<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-466c992 elementor-widget elementor-widget-html\" data-id=\"466c992\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"audio-editor-widget aew-blank\">\n<style data-no-optimize=\"1\" data-noptimize=\"1\" data-no-minify=\"1\">.audio-editor-widget{--bg:#14171d;--panel:#1a1e26;--line:#2a303b;--txt:#e6ecf5;--mut:#8794a8;--acc:#3aa9ff;--env:#ffc46b;--org:#ff7a1f;\n  box-sizing:border-box;width:100%;max-width:1400px;margin:0 auto;padding:24px;background:var(--bg);color:var(--txt);\n  border:1px solid var(--line);border-radius:16px;font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Inter,Roboto,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.45;text-align:left;position:relative}\n.audio-editor-widget *{box-sizing:border-box}\n.audio-editor-widget [hidden]{display:none!important}\n.audio-editor-widget h3,.audio-editor-widget h4,.audio-editor-widget p{margin:0;padding:0;color:var(--txt);text-transform:none;letter-spacing:0}\n.audio-editor-widget .aew-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:18px}\n.audio-editor-widget .aew-title{display:flex;align-items:center;gap:10px;font-size:16px;font-weight:600;line-height:1.2}\n.audio-editor-widget .aew-badge{font-size:11px;color:var(--acc);border:1px solid rgba(58,169,255,.35);padding:3px 9px;border-radius:99px;background:rgba(58,169,255,.06);white-space:nowrap}\n.audio-editor-widget .aew-drop{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;padding:26px 16px;border:1.5px dashed #2f3641;border-radius:12px;background:var(--panel);cursor:pointer;text-align:center;transition:border-color .2s,background .2s,box-shadow .2s}\n.audio-editor-widget .aew-drop:focus-within,.audio-editor-widget .aew-drop.aew-over{border-color:var(--acc);background:#14202f;box-shadow:0 0 0 4px rgba(58,169,255,.08)}\n@media(hover:hover){.audio-editor-widget .aew-drop:hover{border-color:var(--acc);background:#14202f;box-shadow:0 0 0 4px rgba(58,169,255,.08)}}\n.audio-editor-widget .aew-drop.aew-has{padding:12px 16px;flex-direction:row;gap:10px}\n.audio-editor-widget .aew-drop svg{width:26px;height:26px;stroke:var(--acc);fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex:none}\n.audio-editor-widget .aew-drop strong{font-weight:600;color:var(--txt)}\n.audio-editor-widget .aew-drop span{color:var(--mut);font-size:12.5px}\n.audio-editor-widget .aew-file{position:absolute;left:0;top:0;width:100%;height:100%;margin:0;padding:0;border:0;opacity:0;cursor:pointer;z-index:2;font-size:0}\n.audio-editor-widget .aew-work{margin-top:16px}\n.audio-editor-widget .aew-tools{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;margin-bottom:10px}\n.audio-editor-widget .aew-grp{display:flex;gap:6px;flex-wrap:wrap}\n.audio-editor-widget .aew-stage{border:1px solid var(--line);border-radius:4px;background:#0c1017;overflow:hidden}\n.audio-editor-widget .aew-wave{position:relative;height:500px;touch-action:none;user-select:none;-webkit-user-select:none;outline:none}\n.audio-editor-widget.aew-env .aew-wave{touch-action:none}\n.audio-editor-widget .aew-wave{border-radius:3px 3px 0 0}\n.audio-editor-widget .aew-wave:focus-visible{box-shadow:none}\n.audio-editor-widget .aew-wave:focus-visible::after{content:\"\";position:absolute;left:0;top:0;right:0;bottom:0;border-radius:inherit;box-shadow:inset 0 0 0 2px rgba(58,169,255,.45);pointer-events:none;z-index:9}\n.audio-editor-widget .aew-cv,.audio-editor-widget .aew-ov{position:absolute;left:0;top:0;width:100%;height:100%;display:block}\n.audio-editor-widget .aew-ov{pointer-events:none}\n.audio-editor-widget .aew-sh{position:absolute;top:0;bottom:0;background:rgba(6,7,10,.66);pointer-events:none;display:none}\n.audio-editor-widget .aew-shl{left:0;width:0}\n.audio-editor-widget .aew-shr{left:100%;width:0}\n.audio-editor-widget .aew-seln{position:absolute;top:22px;bottom:0;left:0;width:0;background:rgba(255,122,31,.17);pointer-events:none}\n.audio-editor-widget .aew-h{position:absolute;top:0;bottom:0;left:0;width:16px;pointer-events:none;display:none}\n.audio-editor-widget .aew-h:before{content:\"\";position:absolute;left:7px;top:0;bottom:0;width:2px;background:rgba(255,122,31,.9);box-shadow:0 0 8px rgba(255,122,31,.6)}\n.audio-editor-widget .aew-h:after{position:absolute;top:0;width:22px;height:24px;background:rgba(255,122,31,.95);color:#000;font:800 13px\/24px -apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Arial,sans-serif;text-align:center;letter-spacing:0;box-shadow:inset 0 0 0 1px #000}\n.audio-editor-widget .aew-hs:after{content:\"L\";left:-13px;border-radius:0 0 0 7px}\n.audio-editor-widget .aew-he:after{content:\"R\";left:7px;border-radius:0 0 7px 0}\n.audio-editor-widget .aew-hs.aew-in:after{left:7px;border-radius:0 0 7px 0}\n.audio-editor-widget .aew-he.aew-in:after{left:-13px;border-radius:0 0 0 7px}\n.audio-editor-widget .aew-ph{position:absolute;top:0;bottom:0;left:0;width:2px;background:#fff;box-shadow:0 0 6px rgba(255,255,255,.9),0 0 12px rgba(58,169,255,.8);pointer-events:none;display:none}\n.audio-editor-widget .aew-empty{position:absolute;left:0;top:0;right:0;bottom:0;display:none;align-items:center;justify-content:center;color:var(--mut);font-size:13px;pointer-events:none}\n.audio-editor-widget.aew-blank .aew-empty{display:flex}\n.audio-editor-widget .aew-scroll{display:block;margin:0;padding:0 12px 6px}\n.audio-editor-widget .aew-help{padding:8px 14px 10px;color:var(--mut);font-size:12px;border-top:1px solid var(--line)}\n.audio-editor-widget .aew-barw{container-type:inline-size;margin:12px 0}\n.audio-editor-widget .aew-bar{position:relative;display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0;padding:10px 14px;background:var(--panel);border:1px solid var(--line);border-radius:12px}\n.audio-editor-widget .aew-tgrp{display:flex;align-items:center;gap:6px;margin-left:30px}\n.audio-editor-widget .aew-bar .aew-tgrp button.aew-btn.aew-ico{width:36px}\n.audio-editor-widget .aew-tgrp .aew-pi{margin-left:8px}\n.audio-editor-widget .aew-bar button.aew-btn.aew-ico.aew-pi svg,.audio-editor-widget .aew-bar button.aew-btn.aew-ico.aew-po svg{width:30px;height:20px}\n.audio-editor-widget.aew-selon .aew-seln{background:rgba(255,122,31,.17)}\n.audio-editor-widget .aew-selr{display:none!important}\n@container (min-width:1290px){.audio-editor-widget .aew-tgrp{position:absolute;margin-left:0;left:calc(min(max(calc(50% + 100px),750px),calc(100% - 535px)) - 127px);top:50%;transform:translateY(-50%)}}\n.audio-editor-widget .aew-sp{flex:1 1 auto}\n.audio-editor-widget .aew-time{font-variant-numeric:tabular-nums;font-size:13px;white-space:nowrap;color:var(--txt)}\n.audio-editor-widget .aew-time span{color:var(--mut)}\n.audio-editor-widget .aew-time em{font-style:normal}\n.audio-editor-widget button.aew-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:32px;min-width:0;margin:0;padding:0 12px;border:1px solid #2f3641;border-radius:8px;background:#171a23;color:var(--txt);font-family:inherit;font-size:12.5px;font-weight:500;line-height:1;text-transform:none;letter-spacing:0;text-decoration:none;box-shadow:none;cursor:pointer;transition:border-color .15s,background .15s,transform .15s,box-shadow .2s}\n.audio-editor-widget button.aew-btn:focus,.audio-editor-widget button.aew-btn:active{background:#1d2230;color:var(--txt);border-color:var(--acc);box-shadow:none;outline:none}\n@media(hover:hover){.audio-editor-widget button.aew-btn:hover{background:#1d2230;color:var(--txt);border-color:var(--acc);box-shadow:none;outline:none}}\n.audio-editor-widget button.aew-btn:disabled{opacity:.4;cursor:not-allowed}\n.audio-editor-widget button.aew-btn.aew-on,.audio-editor-widget button.aew-btn.aew-on:focus{background:rgba(58,169,255,.14);border-color:var(--acc);color:var(--acc)}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-on:hover{background:rgba(58,169,255,.14);border-color:var(--acc);color:var(--acc)}}\n.audio-editor-widget button.aew-btn.aew-pri,.audio-editor-widget button.aew-btn.aew-pri:focus{background:var(--acc);border-color:var(--acc);color:#04101c;font-weight:600}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-pri:hover{background:var(--acc);border-color:var(--acc);color:#04101c;font-weight:600}}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-pri:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 6px 24px rgba(58,169,255,.35)}}\n.audio-editor-widget button.aew-btn.aew-big{height:42px;padding:0 22px;font-size:14px;border-radius:10px;width:100%}\n.audio-editor-widget button.aew-play{flex:none;width:58px;height:58px;min-width:0;margin:0;padding:0;border:0;border-radius:50%;background:var(--acc);color:#04101c;cursor:pointer;display:flex;align-items:center;justify-content:center;box-shadow:none;transition:transform .15s,box-shadow .2s}\n.audio-editor-widget button.aew-play:focus{background:var(--acc);color:#04101c;transform:scale(1.07);box-shadow:0 4px 18px rgba(58,169,255,.4);outline:none}\n@media(hover:hover){.audio-editor-widget button.aew-play:hover{background:var(--acc);color:#04101c;transform:scale(1.07);box-shadow:0 4px 18px rgba(58,169,255,.4);outline:none}}\n.audio-editor-widget button.aew-play svg{width:26px;height:26px;fill:currentColor;stroke:none}\n.audio-editor-widget button.aew-play .aew-ipa{display:none}\n.audio-editor-widget button.aew-play.aew-playing .aew-ip{display:none}\n.audio-editor-widget button.aew-play.aew-playing .aew-ipa{display:block}\n.audio-editor-widget .aew-trim{display:flex;align-items:center;gap:6px 20px;flex-wrap:wrap;margin-bottom:14px}\n.audio-editor-widget .aew-fld{display:flex;flex-direction:column;gap:6px;margin:0}\n.audio-editor-widget .aew-fld>span{font-size:12px;color:var(--mut);text-transform:uppercase;letter-spacing:.6px}\n.audio-editor-widget .aew-fld b{display:flex;align-items:center;height:34px;font-variant-numeric:tabular-nums;font-weight:600}\n.audio-editor-widget input.aew-ti{width:120px;height:34px;margin:0;padding:0 10px;border:1px solid #2f3641;border-radius:8px;background:#0d1016;color:var(--txt);font-family:inherit;font-size:14px;font-variant-numeric:tabular-nums;text-align:center;outline:none;box-shadow:none}\n.audio-editor-widget input.aew-ti:focus{border-color:var(--acc)}\n.audio-editor-widget .aew-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:16px}\n.audio-editor-widget .aew-card{display:flex;flex-direction:column;gap:14px;padding:14px 18px 18px;background:var(--panel);border:1px solid var(--line);border-radius:12px}\n.audio-editor-widget .aew-ecard{position:relative}\n.audio-editor-widget .aew-card h4{font-size:15px;font-weight:600;text-transform:uppercase;letter-spacing:.8px;color:var(--acc)}\n.audio-editor-widget .aew-ctl{display:flex;flex-direction:column;gap:8px;margin:0}\n.audio-editor-widget .aew-lab{display:flex;justify-content:space-between;font-size:12px;color:var(--mut);text-transform:uppercase;letter-spacing:.6px}\n.audio-editor-widget .aew-lab b{color:var(--txt);font-weight:600;text-transform:none;letter-spacing:0;font-variant-numeric:tabular-nums}\n.audio-editor-widget input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:18px;margin:0;padding:0;background:transparent;cursor:pointer;border:0;box-shadow:none}\n.audio-editor-widget input[type=range]::-webkit-slider-runnable-track{height:4px;border-radius:4px;background:linear-gradient(90deg,var(--acc) var(--p,50%),#262c36 var(--p,50%))}\n.audio-editor-widget input[type=range]::-moz-range-track{height:4px;border-radius:4px;background:#262c36}\n.audio-editor-widget input[type=range]::-moz-range-progress{height:4px;border-radius:4px;background:var(--acc)}\n.audio-editor-widget input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;margin-top:-6px;border-radius:50%;background:#fff;border:3px solid var(--acc);box-shadow:0 0 10px rgba(58,169,255,.5)}\n.audio-editor-widget input[type=range]::-moz-range-thumb{width:10px;height:10px;border-radius:50%;background:#fff;border:3px solid var(--acc)}\n.audio-editor-widget select{width:100%;height:36px;margin:0;padding:0 10px;border-radius:8px;border:1px solid #2f3641;background:#0d1016;color:var(--txt);font-family:inherit;font-size:14px;outline:none;cursor:pointer;box-shadow:none}\n.audio-editor-widget select:focus{border-color:var(--acc)}\n.audio-editor-widget .aew-sw{position:relative;display:flex;align-items:center;justify-content:space-between;gap:10px;min-height:30px;margin:0;cursor:pointer;color:var(--txt);font-size:13px}\n.audio-editor-widget .aew-sw.aew-inl{justify-content:flex-start}\n.audio-editor-widget .aew-sw input{position:absolute;opacity:0;width:0;height:0}\n.audio-editor-widget .aew-sw i{position:relative;width:42px;height:24px;border-radius:99px;background:#262c36;transition:background .2s;flex:none;order:2}\n.audio-editor-widget .aew-sw.aew-inl i{order:0}\n.audio-editor-widget .aew-sw i:after{content:\"\";position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:#fff;transition:transform .2s}\n.audio-editor-widget .aew-sw input:checked+i{background:var(--acc)}\n.audio-editor-widget .aew-sw input:checked+i:after{transform:translateX(18px)}\n.audio-editor-widget .aew-sw input:focus-visible+i{box-shadow:0 0 0 3px rgba(58,169,255,.3)}\n.audio-editor-widget .aew-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}\n.audio-editor-widget .aew-stats.aew-two{grid-template-columns:repeat(2,1fr)}\n.audio-editor-widget .aew-stat{padding:9px 10px;background:#0d1016;border:1px solid var(--line);border-radius:8px;min-width:0}\n.audio-editor-widget .aew-stat span{display:block;font-size:11px;color:var(--mut);text-transform:uppercase;letter-spacing:.6px}\n.audio-editor-widget .aew-stat b{display:block;font-size:13px;font-weight:600;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.audio-editor-widget .aew-note{font-size:12.5px;color:var(--mut)}\n.audio-editor-widget .aew-note.aew-sm{font-size:11.5px}\n.audio-editor-widget .aew-status{margin-top:10px;color:var(--mut);font-size:12.5px;min-height:18px}\n.audio-editor-widget .aew-status.aew-err{color:#ff8a5c}\n.audio-editor-widget .aew-dlg{overflow:auto;position:absolute;left:0;top:0;right:0;bottom:0;z-index:5;display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(11,12,16,.96);border-radius:12px}\n.audio-editor-widget .aew-dlgin{display:flex;flex-direction:column;gap:12px;width:100%}\n.audio-editor-widget .aew-nm{display:flex;align-items:center;gap:6px}\n.audio-editor-widget input.aew-ti.aew-fname{flex:1;width:100%;min-width:0;text-align:left}\n.audio-editor-widget .aew-nm b{height:auto;color:var(--mut);font-weight:500}\n.audio-editor-widget .aew-sw input:disabled+i{opacity:.35}\n.audio-editor-widget .aew-sw.aew-off{opacity:.45;cursor:not-allowed}\n.audio-editor-widget .aew-meter{margin:0 0 16px;padding:14px 18px 10px;background:var(--panel);border:1px solid var(--line);border-radius:12px}\n.audio-editor-widget .aew-mhead{display:flex;align-items:center;gap:8px 18px;flex-wrap:wrap;margin-bottom:8px}\n.audio-editor-widget .aew-mhead h4{font-size:15px;font-weight:600;text-transform:uppercase;letter-spacing:.8px;color:var(--acc)}\n.audio-editor-widget .aew-mread{display:flex;gap:4px 24px;flex-wrap:wrap;flex:1 1 auto;min-height:18px;font-size:12.5px;color:var(--txt);font-variant-numeric:tabular-nums}\n.audio-editor-widget .aew-mwrap{position:relative;width:100%}\n.audio-editor-widget .aew-mcv{display:block;width:100%;cursor:crosshair}\n.audio-editor-widget button.aew-btn.aew-ovl{height:22px;min-width:0;padding:0;margin-left:auto;font-size:10px;font-weight:700;letter-spacing:.4px;color:#8794a8;overflow:hidden;white-space:nowrap}\n.audio-editor-widget button.aew-btn.aew-ovl.aew-lit,.audio-editor-widget button.aew-btn.aew-ovl.aew-lit:focus{background:#ff3b30;border-color:#ff3b30;color:#fff;box-shadow:0 0 14px rgba(255,59,48,.8)}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-ovl.aew-lit:hover{background:#ff3b30;border-color:#ff3b30;color:#fff;box-shadow:0 0 14px rgba(255,59,48,.8)}}\n.audio-editor-widget button.aew-btn.aew-tgl{height:26px;padding:0 11px;font-size:11px;font-weight:700;letter-spacing:.9px}\n.audio-editor-widget button.aew-btn.aew-tgl.aew-on,.audio-editor-widget button.aew-btn.aew-tgl.aew-on:focus{box-shadow:inset 0 2px 5px rgba(0,0,0,.55);background:rgba(58,169,255,.2)}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-tgl.aew-on:hover{box-shadow:inset 0 2px 5px rgba(0,0,0,.55);background:rgba(58,169,255,.2)}}\n.audio-editor-widget .aew-fld.aew-tf{flex-direction:row;align-items:center;gap:6px;height:17px;cursor:text}\n.audio-editor-widget .aew-fld.aew-tf>span{font-size:10px;line-height:17px;letter-spacing:.7px}\n.audio-editor-widget .aew-fld.aew-tf b{height:17px;font-size:12px;font-weight:500;color:var(--txt)}\n.audio-editor-widget input.aew-ti.aew-tin{width:68px;height:17px;padding:0 1px;border:0;border-bottom:1px solid transparent;border-radius:0;background:transparent;box-shadow:none;font-size:12px;line-height:15px;text-align:left;color:var(--txt)}\n@media(hover:hover){.audio-editor-widget input.aew-ti.aew-tin:hover{border-bottom-color:#2f3641}}\n.audio-editor-widget input.aew-ti.aew-tin:focus{border-bottom-color:var(--acc)}\n.audio-editor-widget .aew-trim button.aew-btn{height:20px;padding:0 9px;font-size:11px;border-radius:6px}\n.audio-editor-widget button.aew-btn.aew-home svg{width:13px;height:13px;fill:currentColor;stroke:none;flex:none}\n.audio-editor-widget .aew-ucnt{display:inline-block;margin-left:1px;font-size:8.5px;line-height:1;opacity:.7;font-variant-numeric:tabular-nums;vertical-align:top}\n.audio-editor-widget .aew-status:empty{display:none}\n.audio-editor-widget{background:linear-gradient(180deg,#1a1e26 0%,#12151b 100%);border-color:#0a0c10;box-shadow:0 12px 40px rgba(0,0,0,.5),inset 0 1px 0 rgba(255,255,255,.05)}\n.audio-editor-widget .aew-stage{background:linear-gradient(180deg,#10141b,#0a0d12);border-color:#07090c;box-shadow:inset 0 2px 10px rgba(0,0,0,.65),0 1px 0 rgba(255,255,255,.04)}\n.audio-editor-widget .aew-card,.audio-editor-widget .aew-meter,.audio-editor-widget .aew-bar{background:linear-gradient(180deg,#1e232c,#171b22);border-color:#0a0c10;box-shadow:inset 0 1px 0 rgba(255,255,255,.05),0 2px 8px rgba(0,0,0,.35)}\n.audio-editor-widget .aew-drop{background:linear-gradient(180deg,#1c212a,#161a21);border-color:#323a47}\n.audio-editor-widget .aew-stat{background:#0c1016;border-color:#07090c;box-shadow:inset 0 1px 3px rgba(0,0,0,.6)}\n.audio-editor-widget select,.audio-editor-widget input.aew-ti{background:linear-gradient(180deg,#0f1218,#161a21);border-color:#07090c;box-shadow:inset 0 2px 4px rgba(0,0,0,.55)}\n.audio-editor-widget input.aew-ti.aew-tin{background:transparent;box-shadow:none;border-color:transparent}\n@media(hover:hover){.audio-editor-widget input.aew-ti.aew-tin:hover{border-bottom-color:#2f3641}}\n.audio-editor-widget input.aew-ti.aew-tin:focus{border-bottom-color:var(--acc)}\n.audio-editor-widget button.aew-btn{background:linear-gradient(180deg,#2e3440 0%,#1c2028 100%);border-color:#0a0c10;color:#d6dfec;box-shadow:inset 0 1px 0 rgba(255,255,255,.08),0 1px 2px rgba(0,0,0,.55)}\n.audio-editor-widget button.aew-btn:focus,.audio-editor-widget button.aew-btn:active{background:linear-gradient(180deg,#38404e,#232832);color:#fff;border-color:#0a0c10;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 0 10px rgba(58,169,255,.38)}\n@media(hover:hover){.audio-editor-widget button.aew-btn:hover{background:linear-gradient(180deg,#38404e,#232832);color:#fff;border-color:#0a0c10;box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 0 10px rgba(58,169,255,.38)}}\n.audio-editor-widget button.aew-btn.aew-on,.audio-editor-widget button.aew-btn.aew-on:focus,.audio-editor-widget button.aew-btn.aew-tgl.aew-on,.audio-editor-widget button.aew-btn.aew-tgl.aew-on:focus{background:linear-gradient(180deg,#1a130e,#2a1a0e);border-color:#7d3a0d;color:#ff9a4d;text-shadow:0 0 8px rgba(255,122,31,.9);box-shadow:inset 0 2px 5px rgba(0,0,0,.65),0 0 12px rgba(255,122,31,.45)}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-on:hover,.audio-editor-widget button.aew-btn.aew-tgl.aew-on:hover{background:linear-gradient(180deg,#1a130e,#2a1a0e);border-color:#7d3a0d;color:#ff9a4d;text-shadow:0 0 8px rgba(255,122,31,.9);box-shadow:inset 0 2px 5px rgba(0,0,0,.65),0 0 12px rgba(255,122,31,.45)}}\n.audio-editor-widget button.aew-btn.aew-pri,.audio-editor-widget button.aew-btn.aew-pri:focus{background:linear-gradient(180deg,#5bbaff,#2587e0);border-color:#0d4d92;color:#031220;text-shadow:0 1px 0 rgba(255,255,255,.28);box-shadow:inset 0 1px 0 rgba(255,255,255,.45),0 0 14px rgba(58,169,255,.45)}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-pri:hover{background:linear-gradient(180deg,#5bbaff,#2587e0);border-color:#0d4d92;color:#031220;text-shadow:0 1px 0 rgba(255,255,255,.28);box-shadow:inset 0 1px 0 rgba(255,255,255,.45),0 0 14px rgba(58,169,255,.45)}}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-pri:hover:not(:disabled){box-shadow:inset 0 1px 0 rgba(255,255,255,.5),0 6px 24px rgba(58,169,255,.55)}}\n.audio-editor-widget button.aew-play,.audio-editor-widget button.aew-play:focus{background:radial-gradient(circle at 50% 28%,#3d4553 0%,#1c2028 62%,#12151b 100%);color:#7ccbff;box-shadow:inset 0 2px 3px rgba(255,255,255,.1),inset 0 -5px 10px rgba(0,0,0,.55),0 0 0 2px #0a0c10,0 0 0 4px #3aa9ff,0 0 16px rgba(58,169,255,.6)}\n@media(hover:hover){.audio-editor-widget button.aew-play:hover{background:radial-gradient(circle at 50% 28%,#3d4553 0%,#1c2028 62%,#12151b 100%);color:#7ccbff;box-shadow:inset 0 2px 3px rgba(255,255,255,.1),inset 0 -5px 10px rgba(0,0,0,.55),0 0 0 2px #0a0c10,0 0 0 4px #3aa9ff,0 0 16px rgba(58,169,255,.6)}}\n@media(hover:hover){.audio-editor-widget button.aew-play:hover{color:#c4e6ff}}\n.audio-editor-widget button.aew-play.aew-playing,.audio-editor-widget button.aew-play.aew-playing:focus{color:#ff9a4d;box-shadow:inset 0 2px 3px rgba(255,255,255,.1),inset 0 -5px 10px rgba(0,0,0,.55),0 0 0 2px #0a0c10,0 0 0 4px #ff7a1f,0 0 18px rgba(255,122,31,.65)}\n@media(hover:hover){.audio-editor-widget button.aew-play.aew-playing:hover{color:#ff9a4d;box-shadow:inset 0 2px 3px rgba(255,255,255,.1),inset 0 -5px 10px rgba(0,0,0,.55),0 0 0 2px #0a0c10,0 0 0 4px #ff7a1f,0 0 18px rgba(255,122,31,.65)}}\n.audio-editor-widget input[type=range]::-webkit-slider-runnable-track{background:linear-gradient(90deg,#1d68bd,#4db3ff var(--p,50%),#222730 var(--p,50%));box-shadow:0 0 6px rgba(58,169,255,.3)}\n.audio-editor-widget input[type=range]::-moz-range-track{background:#222730}\n.audio-editor-widget input[type=range]::-moz-range-progress{background:#4db3ff}\n.audio-editor-widget input[type=range]::-webkit-slider-thumb{background:radial-gradient(circle at 50% 35%,#505968,#161a21);border-color:#3aa9ff;box-shadow:0 0 10px rgba(58,169,255,.65)}\n.audio-editor-widget input[type=range]::-moz-range-thumb{background:radial-gradient(circle at 50% 35%,#505968,#161a21);border-color:#3aa9ff}\n.audio-editor-widget .aew-sw i{box-shadow:inset 0 1px 3px rgba(0,0,0,.6)}\n.audio-editor-widget .aew-sw input:checked+i{background:linear-gradient(180deg,#ff9a4d,#ff6a10);box-shadow:0 0 10px rgba(255,122,31,.6)}\n.audio-editor-widget button.aew-btn.aew-tgl:active{background:linear-gradient(180deg,#1a130e,#2a1a0e);border-color:#7d3a0d;color:#ff9a4d;text-shadow:0 0 8px rgba(255,122,31,.9);box-shadow:inset 0 2px 5px rgba(0,0,0,.65),0 0 12px rgba(255,122,31,.45)}\n.audio-editor-widget .aew-nmod{position:absolute;left:0;top:0;right:0;bottom:0;z-index:30;display:flex;align-items:center;justify-content:center;padding:16px;background:rgba(8,10,14,.74);border-radius:16px}\n.audio-editor-widget .aew-nmbox{display:flex;flex-direction:column;gap:14px;width:100%;max-width:440px;padding:18px;background:linear-gradient(180deg,#1e232c,#171b22);border:1px solid #0a0c10;border-radius:12px;box-shadow:0 20px 50px rgba(0,0,0,.65),inset 0 1px 0 rgba(255,255,255,.05)}\n.audio-editor-widget .aew-nmbox h4{font-size:15px;font-weight:600;text-transform:uppercase;letter-spacing:.8px;color:var(--acc)}\n.audio-editor-widget .aew-nmr{display:flex;flex-direction:column;gap:6px;padding:10px 12px;background:#0c1016;border:1px solid #07090c;border-radius:8px;box-shadow:inset 0 1px 3px rgba(0,0,0,.6)}\n.audio-editor-widget .aew-nmrow{display:flex;justify-content:space-between;gap:12px;font-size:12.5px}\n.audio-editor-widget .aew-nmrow span{color:var(--mut);text-transform:uppercase;letter-spacing:.6px;font-size:11px}\n.audio-editor-widget .aew-nmrow b{font-weight:600;color:var(--txt);font-variant-numeric:tabular-nums;text-align:right}\n.audio-editor-widget .aew-nmbox .aew-grp{justify-content:flex-end}\n.audio-editor-widget .aew-rsg{display:flex;flex-wrap:wrap;gap:6px}\n.audio-editor-widget .aew-prow{display:flex;align-items:center;gap:12px}\n.audio-editor-widget .aew-prow input.aew-ps{flex:1;min-width:0}\n.audio-editor-widget input.aew-ps::-webkit-slider-runnable-track{background:linear-gradient(90deg,#222730 0,#222730 var(--a,50%),#4db3ff var(--a,50%),#4db3ff var(--b,50%),#222730 var(--b,50%),#222730 100%);box-shadow:0 0 6px rgba(58,169,255,.3)}\n.audio-editor-widget input.aew-ps::-moz-range-track{background:linear-gradient(90deg,#222730 0,#222730 var(--a,50%),#4db3ff var(--a,50%),#4db3ff var(--b,50%),#222730 var(--b,50%),#222730 100%)}\n.audio-editor-widget input.aew-ps::-moz-range-progress{background:transparent}\n.audio-editor-widget .aew-prow{align-items:flex-end}\n.audio-editor-widget .aew-pwrap{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}\n.audio-editor-widget .aew-pwrap input.aew-ps{flex:none;width:100%}\n.audio-editor-widget .aew-pscale{position:relative;height:24px}\n.audio-editor-widget .aew-pt{position:absolute;bottom:0;width:1px;margin-left:-.5px;background:#4b5565}\n.audio-editor-widget .aew-pt1{height:4px}\n.audio-editor-widget .aew-pt2{height:7px;background:#6d7a8f}\n.audio-editor-widget .aew-pt3{height:11px;background:#c2cde0}\n.audio-editor-widget .aew-ptl{position:absolute;top:0;transform:translateX(-50%);font-style:normal;font-size:9.5px;line-height:11px;font-weight:600;color:#8e9ab0;font-variant-numeric:tabular-nums;white-space:nowrap}\n.audio-editor-widget .aew-ptz{color:#ff9a4d}\n.audio-editor-widget .aew-ph:before{content:\"\";position:absolute;left:-5px;top:0;border-left:6px solid transparent;border-right:6px solid transparent;border-top:9px solid #fff;filter:drop-shadow(0 0 4px rgba(255,255,255,.8))}\n.audio-editor-widget .aew-lc{margin-top:4px}\n.audio-editor-widget .aew-lcrow{display:flex;align-items:center;gap:10px}\n.audio-editor-widget .aew-lcrow input.aew-lcs{flex:1;min-width:0}\n.audio-editor-widget .aew-lcrow button.aew-lcord{min-width:58px}\n.audio-editor-widget .aew-zh,.audio-editor-widget .aew-zv{position:absolute;z-index:6;display:flex;gap:6px}\n.audio-editor-widget .aew-zh{left:8px;bottom:8px;flex-direction:row}\n.audio-editor-widget .aew-zv{right:8px;bottom:8px;flex-direction:column}\n.audio-editor-widget button.aew-btn.aew-zb{width:26px;height:26px;min-width:0;padding:0;border-radius:50%;flex:none}\n.audio-editor-widget button.aew-btn.aew-zb svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:3;stroke-linecap:round;pointer-events:none}\n.audio-editor-widget button.aew-btn.aew-zb svg .aew-fl{fill:currentColor;stroke:none}\n\/* flade runde knapper: grundfarve = --bg (#14171d),ingen gradient; symbolerne i samme orange som resten (#ff7a1f) *\/\n.audio-editor-widget button.aew-btn.aew-zb,.audio-editor-widget button.aew-btn.aew-zb:focus,.audio-editor-widget button.aew-btn.aew-zb:active{background:#1f2530;background-image:none;color:rgba(255,255,255,.75);border:1px solid #38414f;box-shadow:none;text-shadow:none}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-zb:hover{background:#1f2530;background-image:none;color:rgba(255,255,255,.75);border:1px solid #38414f;box-shadow:none;text-shadow:none}}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-zb:hover{color:#3aa9ff;box-shadow:0 0 10px rgba(58,169,255,.38)}}\n.audio-editor-widget button.aew-btn.aew-zb:active{color:#ff7a1f;border-color:#7d3a0d;box-shadow:0 0 12px rgba(255,122,31,.45)}\n.audio-editor-widget .aew-row2{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n.audio-editor-widget .aew-row2 .aew-ctl{min-width:0}\n.audio-editor-widget button.aew-btn.aew-ico{width:36px;min-width:0;padding:0}\n.audio-editor-widget button.aew-btn.aew-ico svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;pointer-events:none;flex:none}\n.audio-editor-widget button.aew-btn.aew-ico svg .aew-fl{fill:currentColor;stroke:none}\n.audio-editor-widget .aew-radio{display:inline-block;position:relative;flex:none;width:12px;height:12px;margin-right:7px;border:2px solid currentColor;border-radius:50%;box-sizing:border-box}\n.audio-editor-widget .aew-radio:after{content:\"\";position:absolute;left:50%;top:50%;width:6px;height:6px;margin:-3px 0 0 -3px;border-radius:50%;background:#ff7a1f;transform:scale(0);transition:transform .12s}\n.audio-editor-widget button.aew-btn.aew-on .aew-radio:after{transform:scale(1);box-shadow:0 0 6px rgba(255,122,31,.9)}\n.audio-editor-widget .aew-ios{display:inline-block;position:relative;flex:none;width:30px;height:18px;margin-right:8px;border-radius:99px;background:#3a414f;box-shadow:inset 0 1px 3px rgba(0,0,0,.55);transition:background .15s}\n.audio-editor-widget .aew-ios i{position:absolute;left:2px;top:2px;width:14px;height:14px;border-radius:50%;background:#ffffff;box-shadow:0 1px 3px rgba(0,0,0,.55);transition:transform .15s}\n.audio-editor-widget button.aew-btn.aew-on .aew-ios{background:#ff7a1f}\n.audio-editor-widget button.aew-btn.aew-on .aew-ios i{transform:translateX(12px)}\n.audio-editor-widget button.aew-btn.aew-tgl.aew-toolenv,.audio-editor-widget button.aew-btn.aew-tgl.aew-toolenv:focus,.audio-editor-widget button.aew-btn.aew-tgl.aew-toolenv:active,.audio-editor-widget button.aew-btn.aew-tgl.aew-toolenv.aew-on,.audio-editor-widget button.aew-btn.aew-tgl.aew-toolenv.aew-on:focus{background:none;background-image:none;border:0;box-shadow:none;text-shadow:none;padding:0 6px;height:32px}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-tgl.aew-toolenv:hover,.audio-editor-widget button.aew-btn.aew-tgl.aew-toolenv.aew-on:hover{background:none;background-image:none;border:0;box-shadow:none;text-shadow:none;padding:0 6px;height:32px}}\n.audio-editor-widget button.aew-btn.aew-tgl.aew-toolenv{color:#d6dfec}\n.audio-editor-widget button.aew-btn.aew-tgl.aew-toolenv.aew-on{color:#ff9a4d}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-tgl.aew-toolenv.aew-on:hover{color:#ff9a4d}}\n.audio-editor-widget .aew-toolenv .aew-ios{width:46px;height:26px;margin-right:0;margin-left:9px}\n.audio-editor-widget .aew-toolenv .aew-ios i{left:3px;top:3px;width:20px;height:20px}\n.audio-editor-widget button.aew-btn.aew-on.aew-toolenv .aew-ios i{transform:translateX(20px)}\n.audio-editor-widget .aew-toolenv:focus-visible .aew-ios{box-shadow:0 0 0 3px rgba(58,169,255,.45)}\n.audio-editor-widget .aew-drop .aew-derr{margin-left:10px;color:#ff6b81;font-size:12.5px}\n.audio-editor-widget .aew-lcd{display:inline-flex;align-items:center;gap:10px;margin-right:10px;padding:0 2px;background:none;border:0;box-shadow:none;white-space:nowrap}\n.audio-editor-widget .aew-lcdf{position:relative;display:inline-block;width:9ch;text-align:right;font:700 26px\/1 ui-monospace,SFMono-Regular,Menlo,Consolas,\"Liberation Mono\",\"Courier New\",monospace;font-variant-numeric:tabular-nums}\n.audio-editor-widget .aew-lcdf i{position:absolute;right:0;top:0;font-style:normal;color:rgba(58,169,255,.09)}\n.audio-editor-widget .aew-lcdf b,.audio-editor-widget .aew-lcdf em{position:relative;font-style:normal;font-weight:700;color:#7ccbff;text-shadow:0 0 9px rgba(124,203,255,.55)}\n.audio-editor-widget .aew-lcdf.aew-dim b,.audio-editor-widget .aew-lcdf.aew-dim em{color:#7ccbff;text-shadow:0 0 9px rgba(124,203,255,.55)}\n.audio-editor-widget .aew-lcdsep{color:rgba(124,203,255,.45);font:700 22px\/1 ui-monospace,SFMono-Regular,Menlo,Consolas,\"Liberation Mono\",\"Courier New\",monospace}\n.audio-editor-widget button.aew-btn.aew-ico.aew-lps svg,.audio-editor-widget button.aew-btn.aew-ico.aew-lpe svg{width:22px;height:22px}\n.audio-editor-widget .aew-bar button.aew-btn.aew-ico{width:40px;height:32px}\n.audio-editor-widget .aew-bar button.aew-btn.aew-ico svg{width:20px;height:20px}\n.audio-editor-widget .aew-bar button.aew-btn.aew-loop svg{width:22px;height:22px}\n.audio-editor-widget .aew-bar button.aew-play{margin-right:10px}\n.audio-editor-widget .aew-bar button.aew-btn.aew-home{width:42px}\n.audio-editor-widget .aew-bar button.aew-btn.aew-home svg{width:22px;height:22px}\n.audio-editor-widget .aew-bar button.aew-btn.aew-lps,.audio-editor-widget .aew-bar button.aew-btn.aew-lpe{font-size:14px;font-weight:800;letter-spacing:0}\n.audio-editor-widget .aew-rsg{display:grid;grid-template-columns:1fr 1fr;gap:8px}\n.audio-editor-widget .aew-rsg button.aew-btn,.audio-editor-widget .aew-lcb button.aew-btn{width:100%;min-width:0;height:30px;padding:0;justify-content:center;text-align:center}\n.audio-editor-widget .aew-lcb{display:grid;grid-template-columns:1fr 1fr;gap:8px}\n.audio-editor-widget .aew-pwrap input.aew-lcs{flex:none;width:100%}\n.audio-editor-widget .aew-tools .aew-grp{align-items:center}\n.audio-editor-widget .aew-tools button.aew-btn{height:32px;box-sizing:border-box;margin:0}\n.audio-editor-widget .aew-tools button.aew-btn.aew-ico{width:36px;padding:0}\n.audio-editor-widget .aew-mkg{display:grid;grid-template-columns:repeat(6,1fr);gap:6px}\n.audio-editor-widget .aew-mknav{display:grid;grid-template-columns:1fr 1fr;gap:6px}\n.audio-editor-widget button.aew-btn.aew-mkb{width:100%;min-width:0;height:28px;padding:0;font-size:12px;font-weight:600;justify-content:center;color:#6d7a8f}\n.audio-editor-widget button.aew-btn.aew-mkb.aew-mkset,.audio-editor-widget button.aew-btn.aew-mkb.aew-mkset:focus{background:linear-gradient(180deg,#1a130e,#2a1a0e);border-color:#7d3a0d;color:#ff9a4d;text-shadow:0 0 8px rgba(255,122,31,.9);box-shadow:inset 0 2px 5px rgba(0,0,0,.65),0 0 12px rgba(255,122,31,.45)}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-mkb.aew-mkset:hover{background:linear-gradient(180deg,#1a130e,#2a1a0e);border-color:#7d3a0d;color:#ff9a4d;text-shadow:0 0 8px rgba(255,122,31,.9);box-shadow:inset 0 2px 5px rgba(0,0,0,.65),0 0 12px rgba(255,122,31,.45)}}\n.audio-editor-widget .aew-mknav button.aew-btn{width:100%;height:30px;padding:0}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-ico:hover:not(:disabled):not(.aew-on):not(:active),.audio-editor-widget button.aew-btn.aew-zb:hover:not(:disabled):not(:active){color:#3aa9ff}}\n.audio-editor-widget button.aew-btn.aew-ico:active:not(:disabled),.audio-editor-widget button.aew-btn.aew-zb:active:not(:disabled),.audio-editor-widget button.aew-btn.aew-ico.aew-on,.audio-editor-widget button.aew-btn.aew-ico.aew-on:focus{color:#ff7a1f}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-ico.aew-on:hover{color:#ff7a1f}}\n.audio-editor-widget .aew-pm{flex-wrap:nowrap}\n.audio-editor-widget .aew-pm{gap:4px}\n.audio-editor-widget .aew-pm button.aew-btn.aew-pmb{letter-spacing:.3px;font-weight:700;font-size:10.5px;padding:0 8px}\n.audio-editor-widget .aew-pm .aew-xfl{margin-left:4px}\n.audio-editor-widget .aew-tools .aew-tcol:first-child .aew-grp button.aew-btn{padding:0 10px;font-size:11px;font-weight:700;letter-spacing:.4px;text-transform:uppercase}\n.audio-editor-widget .aew-tcol{display:flex;flex-direction:column;align-items:stretch;gap:13px}\n.audio-editor-widget .aew-tlab{display:flex;align-items:center;justify-content:center;gap:9px;font-size:12.5px;font-weight:700;line-height:15px;letter-spacing:1px;text-transform:uppercase;color:var(--acc)}\n.audio-editor-widget .aew-tlab b{font-weight:700;margin-right:-1px;white-space:nowrap}\n.audio-editor-widget .aew-card h4.aew-tlab{font-size:12.5px;font-weight:700;letter-spacing:1px;line-height:15px}\n.audio-editor-widget .aew-tlab::before,.audio-editor-widget .aew-tlab::after{content:\"\";flex:1 1 0;min-width:6px;height:1px;border-radius:1px;background:rgba(58,169,255,.5)}\n.audio-editor-widget .aew-pm .aew-xfl.aew-off{opacity:.4}\n.audio-editor-widget .aew-fld.aew-tf>span.aew-unit{text-transform:none;letter-spacing:0;font-size:11px}\n.audio-editor-widget input.aew-ti.aew-tin.aew-xfms{width:30px;text-align:right}\n.audio-editor-widget input.aew-ti.aew-tin.aew-xfms:disabled{cursor:not-allowed}\n.audio-editor-widget .aew-mread span{display:inline-block;overflow:hidden;white-space:pre;vertical-align:top;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,\"Liberation Mono\",\"Courier New\",monospace;font-size:12px;line-height:18px;font-variant-numeric:tabular-nums}\n.audio-editor-widget .aew-mread .aew-m1,.audio-editor-widget .aew-mread .aew-m2{width:39ch}\n.audio-editor-widget .aew-mread .aew-m3{width:12ch}\n@container (max-width:1289px){.audio-editor-widget .aew-lcdf{font-size:26px}.audio-editor-widget .aew-lcdsep{font-size:22px}.audio-editor-widget .aew-tgrp{margin-left:20px}}\n@media(max-width:560px){.audio-editor-widget .aew-lcdf{font-size:24px}.audio-editor-widget .aew-lcdsep{font-size:20px}.audio-editor-widget{padding:14px}.audio-editor-widget .aew-wave{height:380px}.audio-editor-widget .aew-stats{grid-template-columns:1fr}.audio-editor-widget .aew-stats.aew-two{grid-template-columns:1fr 1fr}}\n.audio-editor-widget .aew-ttt{display:grid;grid-template-columns:repeat(3,1fr);gap:6px}\n.audio-editor-widget .aew-ttt button.aew-btn{width:100%;min-width:0;height:30px;padding:0 4px;font-size:11px;letter-spacing:.4px;font-weight:700}\n.audio-editor-widget .aew-m-tt .aew-fld{margin:0;min-width:0}\n.audio-editor-widget .aew-m-tt input.aew-ti{width:100%}\n.audio-editor-widget .aew-dis{opacity:.35;pointer-events:none}\n.audio-editor-widget .aew-ucnt:empty{display:none}\n.audio-editor-widget input.aew-ti.aew-tin.aew-xfms{width:36px;height:17px;padding:0 4px;border:1px solid rgba(150,160,176,.55);border-radius:3px;text-align:right}\n@media(hover:hover){.audio-editor-widget input.aew-ti.aew-tin.aew-xfms:hover{border-color:rgba(190,200,215,.8)}}\n.audio-editor-widget input.aew-ti.aew-tin.aew-xfms:focus{border-color:var(--acc)}\n.audio-editor-widget .aew-bar button.aew-btn.aew-rtn,.audio-editor-widget .aew-bar button.aew-btn.aew-last,.audio-editor-widget .aew-bar button.aew-btn.aew-link{width:46px;height:32px;padding:0;font-size:11px;font-weight:800;letter-spacing:.4px}\n.audio-editor-widget .aew-selr{position:absolute;top:0;bottom:0;left:0;width:0;background:rgba(255,122,31,.24);border-top:2px solid rgba(255,122,31,.7);pointer-events:none;display:none}\n.audio-editor-widget.aew-nolink .aew-seln,.audio-editor-widget.aew-nolink.aew-selon .aew-seln{background:none}\n.audio-editor-widget .aew-gin{position:absolute;z-index:12;width:94px;height:24px;margin:0;padding:0 6px;border:1px solid #3aa9ff;border-radius:4px;background:#0b0e13;color:#fff;font:600 12px ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;text-align:center;outline:none;box-shadow:0 4px 14px rgba(0,0,0,.6)}\n.audio-editor-widget .aew-gr{position:absolute;left:0;top:0;width:7px;height:21px;margin:-10.5px 0 0 -3.5px;border-radius:3px;background:rgba(235,244,255,.95);border:1px solid #0c1017;box-shadow:0 0 6px rgba(0,0,0,.7);pointer-events:none;display:none;box-sizing:border-box}\n.audio-editor-widget .aew-gr:before,.audio-editor-widget .aew-gr:after{content:\"\";position:absolute;top:5px;bottom:5px;width:1px;background:#1d4fb8;border-radius:1px}\n.audio-editor-widget .aew-gr:before{left:1.5px}\n.audio-editor-widget .aew-gr:after{right:1.5px}\n.audio-editor-widget .aew-gr.aew-hov{height:24px;margin-top:-12px;background:#f7fbff}\n.audio-editor-widget .aew-gr.aew-act{height:27px;margin-top:-13.5px;background:#ffffff;box-shadow:0 0 8px rgba(255,255,255,.55),0 0 6px rgba(0,0,0,.7)}\n.audio-editor-widget .aew-grl{position:absolute;left:0;top:0;display:none;padding:0 6px;height:18px;line-height:17px;border:1px solid #fff;background:rgba(11,12,16,.94);color:#fff;font:700 11px ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;pointer-events:none;white-space:nowrap}\n.audio-editor-widget button.aew-btn.aew-smb.aew-blocked{opacity:.45;cursor:not-allowed}\n.audio-editor-widget .aew-smg{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px}\n.audio-editor-widget .aew-smg button.aew-btn{width:100%;min-width:0;height:34px;padding:0;justify-content:center;font-size:12px;font-weight:700}\n.audio-editor-widget .aew-rsg2{display:grid;grid-template-columns:1fr 1fr;gap:8px}\n.audio-editor-widget .aew-rsg2 button.aew-btn{width:100%;min-width:0;height:34px;padding:0;justify-content:center;font-size:12px;font-weight:700}\n.audio-editor-widget button.aew-btn.aew-ico.aew-tcut.aew-on.aew-live,.audio-editor-widget button.aew-btn.aew-ico.aew-tcut.aew-on.aew-live:focus{background:linear-gradient(180deg,#0d1a12,#0e2a18);border-color:#1f7a45;color:#35e07a;text-shadow:0 0 8px rgba(53,224,122,.9);box-shadow:inset 0 2px 5px rgba(0,0,0,.65),0 0 12px rgba(53,224,122,.45)}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-ico.aew-tcut.aew-on.aew-live:hover{background:linear-gradient(180deg,#0d1a12,#0e2a18);border-color:#1f7a45;color:#35e07a;text-shadow:0 0 8px rgba(53,224,122,.9);box-shadow:inset 0 2px 5px rgba(0,0,0,.65),0 0 12px rgba(53,224,122,.45)}}\n.audio-editor-widget .aew-scroll.aew-off{opacity:.38;cursor:default}\n.audio-editor-widget .aew-unit{display:inline-flex;gap:6px}\n.audio-editor-widget button.aew-btn.aew-un{min-width:0;height:28px;padding:0 12px;font-size:11px;font-weight:700}\n.audio-editor-widget input.aew-ti.aew-tin{width:96px}\n.audio-editor-widget .aew-trim b.aew-len{display:inline-block;width:104px;text-align:left;font-variant-numeric:tabular-nums;white-space:nowrap}\n.audio-editor-widget input.aew-ti.aew-tin{font-variant-numeric:tabular-nums}\n.audio-editor-widget .aew-trim button.aew-btn.aew-reset{height:34px;min-width:96px;padding:0 22px;margin-left:34px;font-size:13px;font-weight:700;letter-spacing:.04em}\n.audio-editor-widget.aew-smp .aew-lcdf{font-size:23px}\n@media(max-width:560px){.audio-editor-widget.aew-smp .aew-lcdf{font-size:20px}}\n.audio-editor-widget .aew-drop .aew-mki{display:none;margin-top:4px;font-size:11px;line-height:14px;color:var(--mut);font-variant-numeric:tabular-nums;white-space:nowrap}\n.audio-editor-widget .aew-drop.aew-has .aew-mki{display:block;min-height:14px}\n.audio-editor-widget .aew-abbox{text-align:center;align-items:center}\n.audio-editor-widget .aew-abbox p{margin:0}\n.audio-editor-widget .aew-abbox p.aew-abver{margin:-6px 0 0;font-size:12.5px;color:var(--mut);letter-spacing:.04em}\n.audio-editor-widget .aew-abmade{font-size:15px;font-weight:600;color:var(--txt)}\n.audio-editor-widget .aew-abdon{font-size:13px;color:var(--mut)}\n.audio-editor-widget .aew-donate{color:var(--mut);text-decoration:none;cursor:default}\n.audio-editor-widget .aew-donate[href]{color:var(--acc);text-decoration:underline;cursor:pointer}\n.audio-editor-widget .aew-mkcard .aew-mkg{row-gap:8px}\n.audio-editor-widget .aew-mkcard button.aew-btn.aew-mkb{height:30px}\n.audio-editor-widget .aew-mkcard .aew-mknav{margin-top:-6px}\n.audio-editor-widget .aew-dmrow{display:flex;align-items:center;gap:10px;min-height:28px}\n.audio-editor-widget .aew-dmsum{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--mut);font-size:12.5px}\n.audio-editor-widget button.aew-btn.aew-dmbtn{height:28px;min-width:0;padding:0 14px;font-size:12px}\n.audio-editor-widget .aew-mtbox{max-width:640px;width:100%;max-height:100%;overflow:auto;gap:12px}\n.audio-editor-widget .aew-mtgrid{display:grid;grid-template-columns:1fr 1fr;gap:10px 14px}\n.audio-editor-widget .aew-mtf{display:flex;flex-direction:column;gap:4px;min-width:0}\n.audio-editor-widget .aew-mtf[hidden]{display:none}\n.audio-editor-widget .aew-mtf.aew-wide{grid-column:1\/-1}\n.audio-editor-widget .aew-mtf>span:first-child{font-size:11px;color:var(--mut);text-transform:uppercase;letter-spacing:.6px}\n.audio-editor-widget input.aew-mti{width:100%;height:32px;margin:0;padding:0 10px;border:1px solid #2f3641;border-radius:8px;box-sizing:border-box;background:linear-gradient(180deg,#0f1218,#161a21);border-color:#07090c;box-shadow:inset 0 2px 4px rgba(0,0,0,.55);color:var(--txt);font-family:inherit;font-size:13px;outline:none}\n.audio-editor-widget input.aew-mti:focus{border-color:var(--acc)}\n.audio-editor-widget .aew-mttr{display:flex;align-items:center;gap:8px}\n.audio-editor-widget .aew-mttr i{font-style:normal;color:var(--mut);font-size:12px;text-transform:none;letter-spacing:0}\n.audio-editor-widget .aew-mttr input.aew-mti{width:72px;text-align:center}\n.audio-editor-widget .aew-mtcov{display:flex;gap:16px;align-items:center}\n.audio-editor-widget .aew-mtcov[hidden]{display:none}\n.audio-editor-widget .aew-mtimg{width:112px;height:112px;flex:none;border:1px dashed #2f3641;border-radius:8px;background:#0d1016 center\/cover no-repeat}\n.audio-editor-widget .aew-mtcov.aew-dis{opacity:.5}\n.audio-editor-widget .aew-mtcb{display:flex;flex-direction:column;gap:8px;min-width:0}\n.audio-editor-widget .aew-mtct{font-size:12.5px;color:var(--txt);font-weight:600}\n.audio-editor-widget .aew-mtbtns{justify-content:flex-end}\n.audio-editor-widget .aew-mtcb .aew-grp{justify-content:flex-start}\n@media(max-width:560px){.audio-editor-widget .aew-mtgrid{grid-template-columns:1fr}.audio-editor-widget .aew-mtcov{flex-direction:column;align-items:flex-start}}\n.audio-editor-widget button.aew-btn.aew-pri,.audio-editor-widget button.aew-btn.aew-pri:focus{background:linear-gradient(180deg,#0e1620,#0d2237);border-color:#1c5b94;color:#3aa9ff;font-weight:700;text-shadow:0 0 8px rgba(58,169,255,.8);box-shadow:inset 0 2px 5px rgba(0,0,0,.65),0 0 12px rgba(58,169,255,.4)}\n@media(hover:hover){.audio-editor-widget button.aew-btn.aew-pri:hover:not(:disabled){background:linear-gradient(180deg,#112133,#12304c);border-color:#2475b8;color:#5bbaff;box-shadow:inset 0 2px 5px rgba(0,0,0,.65),0 0 16px rgba(58,169,255,.55)}}\n.audio-editor-widget button.aew-btn.aew-pri.aew-big{letter-spacing:.08em}\n.audio-editor-widget button.aew-btn .aew-pvi{width:13px;height:13px;margin-right:0;flex:none;fill:currentColor;stroke:none;pointer-events:none}\n.audio-editor-widget button.aew-btn:has(.aew-pvi){display:inline-flex;align-items:center;justify-content:center}\n.audio-editor-widget .aew-nvw{display:inline-flex;align-items:center;gap:6px}\n.audio-editor-widget .aew-nvw i{font-style:normal;color:var(--mut);font-size:12px}\n.audio-editor-widget input.aew-ti.aew-nin{width:84px;height:28px;padding:0 8px;text-align:right;font-size:13px;border-radius:7px}\n.audio-editor-widget .aew-nvw b{color:var(--mut);font-weight:600;font-size:12.5px;margin-left:4px}\n.audio-editor-widget .aew-ttlw{align-self:flex-start}\n.audio-editor-widget .aew-nmcu[hidden]{display:none}\n.audio-editor-widget .aew-ptp{position:absolute;z-index:11;display:flex;gap:8px;padding:8px 10px;background:rgba(11,12,16,.96);border:1px solid #3aa9ff;border-radius:8px;box-shadow:0 6px 18px rgba(0,0,0,.6)}\n.audio-editor-widget .aew-ptp[hidden]{display:none}\n.audio-editor-widget .aew-ptp label{display:flex;flex-direction:column;gap:3px;font-size:10.5px;color:var(--mut);text-transform:uppercase;letter-spacing:.6px}\n.audio-editor-widget .aew-ptp input.aew-ti.aew-nin{width:104px;text-align:center}\n.audio-editor-widget .aew-ptp label:last-child input.aew-ti.aew-nin{width:70px}\n.audio-editor-widget .aew-drop .aew-mki{pointer-events:none}\n.audio-editor-widget .aew-drop .aew-mki.aew-ed{pointer-events:auto;position:relative;z-index:3;cursor:text;text-decoration:underline dotted rgba(150,160,176,.6);text-underline-offset:3px}\n.audio-editor-widget .aew-mki input.aew-ti.aew-nin{height:20px;width:110px;margin-left:4px;font-size:11px;text-align:left}\n.audio-editor-widget select,.audio-editor-widget input.aew-mti[list]{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url(\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238b98ac' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'\/%3E%3C\/svg%3E\"),linear-gradient(180deg,#0f1218,#161a21);background-repeat:no-repeat,no-repeat;background-position:right 12px center,0 0;background-size:10px 6px,auto;padding-right:32px;text-overflow:ellipsis}\n.audio-editor-widget select:focus,.audio-editor-widget input.aew-mti[list]:focus{background-image:url(\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23c7d3e6' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'\/%3E%3C\/svg%3E\"),linear-gradient(180deg,#0f1218,#161a21)}\n@media(hover:hover){.audio-editor-widget select:hover:not(:disabled),.audio-editor-widget input.aew-mti[list]:hover{background-image:url(\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23c7d3e6' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'\/%3E%3C\/svg%3E\"),linear-gradient(180deg,#0f1218,#161a21)}}\n.audio-editor-widget select:disabled{opacity:.5;cursor:default}\n.audio-editor-widget input.aew-mti[list]::-webkit-calendar-picker-indicator{opacity:0;position:absolute;right:0;width:32px;height:100%;cursor:pointer}\n.audio-editor-widget .aew-drop .aew-demo{position:absolute;right:29px;top:50%;transform:translateY(-50%);z-index:3;margin:0;padding:4px 6px;border:0;border-radius:0;background:none;box-shadow:none;filter:none;text-shadow:none;-webkit-appearance:none;appearance:none;color:var(--mut);font-family:inherit;font-size:12px;font-weight:400;line-height:1.2;letter-spacing:0;text-transform:none;cursor:pointer;transition:none}\n.audio-editor-widget .aew-drop .aew-demo:active,.audio-editor-widget .aew-drop .aew-demo:focus,.audio-editor-widget .aew-drop .aew-demo:disabled{background:none;box-shadow:none;filter:none;text-shadow:none;color:var(--mut);transform:translateY(-50%);opacity:1}\n@media(hover:hover){.audio-editor-widget .aew-drop .aew-demo:hover{background:none;box-shadow:none;filter:none;text-shadow:none;color:var(--mut);transform:translateY(-50%);opacity:1}}\n.audio-editor-widget .aew-drop .aew-demo:disabled{cursor:default}\n.audio-editor-widget .aew-drop .aew-demo:focus-visible{outline:1px dotted var(--mut);outline-offset:1px}\n@media(max-width:560px){.audio-editor-widget .aew-drop .aew-demo,.audio-editor-widget .aew-drop .aew-demo:hover,.audio-editor-widget .aew-drop .aew-demo:active,.audio-editor-widget .aew-drop .aew-demo:focus,.audio-editor-widget .aew-drop .aew-demo:disabled{position:static;transform:none;margin-top:4px}}\n.audio-editor-widget .aew-drop .aew-tipb{position:absolute;left:29px;top:50%;transform:translateY(-50%);z-index:3;margin:0;padding:3px;border:0;border-radius:50%;background:none;box-shadow:none;filter:none;color:#3aa9ff;line-height:0;cursor:pointer;-webkit-appearance:none;appearance:none;transition:none}\n.audio-editor-widget .aew-drop .aew-tipb:active,.audio-editor-widget .aew-drop .aew-tipb:focus{background:none;box-shadow:none;filter:none;transform:translateY(-50%);color:#3aa9ff}\n@media(hover:hover){.audio-editor-widget .aew-drop .aew-tipb:hover{background:none;box-shadow:none;filter:none;transform:translateY(-50%);color:#3aa9ff}}\n.audio-editor-widget .aew-drop .aew-tipb:focus-visible{outline:1px dotted #3aa9ff;outline-offset:1px}\n.audio-editor-widget .aew-tipb svg{width:27px;height:27px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;opacity:.78}\n.audio-editor-widget .aew-tipb .aew-tipd{fill:currentColor;stroke:none}\n.audio-editor-widget .aew-tipb[aria-pressed=\"true\"] svg{opacity:1}\n.audio-editor-widget .aew-tipb[aria-pressed=\"true\"] svg circle:first-child{fill:rgba(255,122,31,.2)}\n.audio-editor-widget .aew-drop .aew-tipb[aria-pressed=\"true\"],.audio-editor-widget .aew-drop .aew-tipb[aria-pressed=\"true\"]:active,.audio-editor-widget .aew-drop .aew-tipb[aria-pressed=\"true\"]:focus{color:#ff9a4d}\n@media(hover:hover){.audio-editor-widget .aew-drop .aew-tipb[aria-pressed=\"true\"]:hover{color:#ff9a4d}}\n.audio-editor-widget .aew-tipb[aria-pressed=\"true\"] svg{filter:drop-shadow(0 0 5px rgba(255,122,31,.6))}\n@media(max-width:560px){.audio-editor-widget .aew-drop .aew-tipb,.audio-editor-widget .aew-drop .aew-tipb:hover,.audio-editor-widget .aew-drop .aew-tipb:active,.audio-editor-widget .aew-drop .aew-tipb:focus{left:23px;top:8px;transform:none}}\n.audio-editor-widget .aew-tip{position:absolute;z-index:70;width:max-content;max-width:340px;padding:7px 11px 8px;white-space:normal;background:#0b0e13;border:1px solid rgba(58,169,255,.24);border-radius:8px;box-shadow:0 8px 22px rgba(0,0,0,.55);color:#cfd8e6;font-size:12.5px;font-weight:400;line-height:1.45;text-align:left;pointer-events:none;opacity:0;transform:translateY(3px);transition:opacity .14s ease,transform .14s ease}\n.audio-editor-widget .aew-tip.aew-below{transform:translateY(-3px)}\n.audio-editor-widget .aew-tip.aew-show{opacity:1;transform:none}\n.audio-editor-widget .aew-tip[hidden]{display:none}\n.audio-editor-widget .aew-tip b{display:block;margin-bottom:3px;color:#3aa9ff;font-size:11px;letter-spacing:.08em;text-transform:uppercase}\n.audio-editor-widget .aew-tip i{position:absolute;width:9px;height:9px;background:#0b0e13;border:1px solid rgba(58,169,255,.24);border-top:0;border-left:0;transform:rotate(45deg);bottom:-5px}\n.audio-editor-widget .aew-tip.aew-below i{bottom:auto;top:-5px;border:1px solid rgba(58,169,255,.24);border-bottom:0;border-right:0}\n.audio-editor-widget .aew-drop .aew-tipb{left:27px;width:36px;height:32px;padding:3px 5px;border:1px solid transparent;border-radius:8px;box-sizing:border-box}\n.audio-editor-widget .aew-tipb svg{width:26px;height:26px}\n.audio-editor-widget .aew-drop .aew-tipb[aria-pressed=\"true\"],.audio-editor-widget .aew-drop .aew-tipb[aria-pressed=\"true\"]:active,.audio-editor-widget .aew-drop .aew-tipb[aria-pressed=\"true\"]:focus{background:none;border-color:transparent;color:#ff7a1f;box-shadow:none}\n@media(hover:hover){.audio-editor-widget .aew-drop .aew-tipb[aria-pressed=\"true\"]:hover{background:none;border-color:transparent;color:#ff7a1f;box-shadow:none}}\n.audio-editor-widget .aew-tipb[aria-pressed=\"true\"] svg{filter:none;opacity:1}\n.audio-editor-widget .aew-tipb[aria-pressed=\"true\"] svg circle:first-child{fill:none}\n@media(max-width:560px){.audio-editor-widget .aew-drop .aew-tipb,.audio-editor-widget .aew-drop .aew-tipb:hover,.audio-editor-widget .aew-drop .aew-tipb:active,.audio-editor-widget .aew-drop .aew-tipb:focus,.audio-editor-widget .aew-drop .aew-tipb[aria-pressed=\"true\"],.audio-editor-widget .aew-drop .aew-tipb[aria-pressed=\"true\"]:hover{left:18px;top:8px;transform:none}}\n.audio-editor-widget{touch-action:manipulation;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;-webkit-text-size-adjust:100%}\n@media(pointer:coarse){.audio-editor-widget input,.audio-editor-widget select,.audio-editor-widget textarea{font-size:16px!important}}\n.audio-editor-widget .aew-drow{display:flex;gap:8px}\n.audio-editor-widget button.aew-btn.aew-rg{height:28px;min-width:0;padding:0 12px;font-size:11px;font-weight:700}\n.audio-editor-widget button.aew-btn.aew-rg.aew-blocked{opacity:.45;cursor:not-allowed}\n.audio-editor-widget .aew-fld span.aew-drsum{display:block;margin-top:6px;font-size:12.5px;font-weight:400;letter-spacing:0;text-transform:none;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.audio-editor-widget .aew-imlist{max-height:7em;overflow:auto;word-break:break-all;margin:0}\n@keyframes aewnj{to{opacity:1;visibility:visible;max-height:300px;margin:0 0 14px;padding:10px 14px;border-width:1px}}\n.audio-editor-widget .aew-nojs{opacity:0;visibility:hidden;overflow:hidden;max-height:0;margin:0;padding:0 14px;border:0 solid #ff9a4d;animation:aewnj .01s linear 3s forwards;border-radius:10px;background:#241a12;color:#ffd7b0;font:13px\/1.5 -apple-system,Segoe UI,Roboto,sans-serif}\n.audio-editor-widget.aew-ready .aew-nojs{display:none}\n<\/style>\n<div class=\"aew-nojs\" role=\"status\">Wavesoniq has not started yet. If this message stays visible on a WordPress page, a cache or optimization plugin (or the page builder) is delaying or blocking the widget's script. Exclude the script from minify \/ defer \/ delay, or embed the widget in an iframe.<\/div>\n\n<div class=\"aew-drop\">\n  <svg viewBox=\"0 0 24 24\"><path d=\"M12 16V4M7 9l5-5 5 5M4 16v3a1 1 0 001 1h14a1 1 0 001-1v-3\"\/><\/svg>\n  <div><strong class=\"aew-dn\">Drop an audio or video file here<\/strong> <span class=\"aew-ds\"><\/span> <span class=\"aew-derr\" hidden><\/span><div class=\"aew-mki\" aria-live=\"polite\"><\/div><\/div>\n  <button type=\"button\" class=\"aew-tipb\" aria-pressed=\"false\" aria-label=\"Show tooltips\" data-tip=\"Tooltips off \u2013 turn on to see hints\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"9.2\"\/><path d=\"M9.5 9.5a2.6 2.6 0 1 1 3.8 2.3c-.9.5-1.3 1.1-1.3 2.1\"\/><circle class=\"aew-tipd\" cx=\"12\" cy=\"17.3\" r=\".7\"\/><\/svg><\/button>\n  <button type=\"button\" class=\"aew-demo\" data-tip=\"Load the demo audio file\">Use Demo Audio<\/button>\n  <input class=\"aew-file\" type=\"file\" multiple accept=\"audio\/*,video\/*,.mp3,.wav,.m4a,.aac,.ogg,.flac,.mp4,.m4v,.mov,.avi\" aria-label=\"Choose audio or video file\" title=\" \">\n<\/div>\n\n\n<div class=\"aew-work\">\n  <div class=\"aew-tools\">\n    <div class=\"aew-tcol\">\n      <span class=\"aew-tlab\" aria-hidden=\"true\"><b>OPERATION<\/b><\/span>\n      <div class=\"aew-grp\" role=\"group\" aria-label=\"Operation\">\n        <button type=\"button\" class=\"aew-btn aew-undo\" disabled data-tip=\"Undo last edit (Alt: Redo)\"><span class=\"aew-ulab\">UNDO<\/span><span class=\"aew-ucnt\"><\/span><\/button>\n        <button type=\"button\" class=\"aew-btn aew-cpy\" data-tip=\"Copy selection to clipboard\">COPY<\/button>\n        <button type=\"button\" class=\"aew-btn aew-cut\" data-tip=\"Cut selection to clipboard\">CUT<\/button>\n        <button type=\"button\" class=\"aew-btn aew-pst\" disabled data-tip=\"Paste at cursor or selection\">PASTE<\/button>\n        <button type=\"button\" class=\"aew-btn aew-del\" data-tip=\"Delete selection, close the gap\">DELETE<\/button>\n        <button type=\"button\" class=\"aew-btn aew-all\" data-tip=\"Select the whole file\">SELECT ALL<\/button>\n        <button type=\"button\" class=\"aew-btn aew-crop\" data-tip=\"Keep only the selection\">CROP<\/button>\n      <\/div>\n    <\/div>\n    <div class=\"aew-tcol\">\n      <span class=\"aew-tlab\" aria-hidden=\"true\"><b>X FADE<\/b><\/span>\n      <div class=\"aew-grp aew-pm\" role=\"radiogroup\" aria-label=\"X fade type\">\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-pmb aew-on\" role=\"radio\" aria-checked=\"true\" data-m=\"normal\" data-tip=\"Plain copy\/paste, no crossfades\">NORMAL<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-pmb\" role=\"radio\" aria-checked=\"false\" data-m=\"zc\" data-tip=\"Snap edges to zero crossings\">ZERO<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-pmb\" role=\"radio\" aria-checked=\"false\" data-m=\"eq\" data-tip=\"Equal-power crossfades at edits\">EQUAL<\/button>\n        <label class=\"aew-fld aew-tf aew-xfl aew-off\" title=\"Crossfade length (equal power)\"><input class=\"aew-ti aew-tin aew-xfms\" type=\"text\" inputmode=\"numeric\" spellcheck=\"false\" value=\"10\" disabled aria-label=\"Crossfade length in milliseconds\"><span class=\"aew-unit\">ms<\/span><\/label>\n      <\/div>\n    <\/div>\n    <div class=\"aew-tcol\">\n      <span class=\"aew-tlab\" aria-hidden=\"true\"><b>ENVELOPE<\/b><\/span>\n      <div class=\"aew-grp\" role=\"group\" aria-label=\"Envelope\">\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-toolenv\" aria-pressed=\"false\" data-tip=\"Edit volume envelope (E)\">EDIT<span class=\"aew-ios\"><i><\/i><\/span><\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-lrs\" aria-pressed=\"false\" data-tip=\"Edit left\/right channels separately\">L\/R<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-ico aew-live aew-on\" aria-pressed=\"true\" aria-label=\"Live preview\" data-tip=\"Show envelope live on waveform\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><circle class=\"aew-fl\" cx=\"12\" cy=\"12\" r=\"2.3\"\/><path d=\"M8 8a5.7 5.7 0 0 0 0 8M16 8a5.7 5.7 0 0 1 0 8M5 5a10 10 0 0 0 0 14M19 5a10 10 0 0 1 0 14\"\/><\/svg><\/button>\n        <button type=\"button\" class=\"aew-btn aew-ico aew-envdel\" disabled aria-label=\"Delete point\" data-tip=\"Delete selected envelope point\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"7.5\"\/><path d=\"M8.5 12h7\"\/><\/svg><\/button>\n        <button type=\"button\" class=\"aew-btn aew-ico aew-envclr\" disabled aria-label=\"Clear envelope\" data-tip=\"Clear the whole envelope\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M4.5 7h15\"\/><path d=\"M9.5 7V4.8h5V7\"\/><path d=\"M6.5 7l.9 12.2h9.2L17.5 7\"\/><path d=\"M10 10.8v5.6M14 10.8v5.6\"\/><\/svg><\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n  <div class=\"aew-stage\">\n    <div class=\"aew-wave\" tabindex=\"0\" aria-label=\"Waveform\">\n      <div class=\"aew-seln\"><\/div>\n      <div class=\"aew-selr\"><\/div>\n      <canvas class=\"aew-cv\"><\/canvas>\n      <canvas class=\"aew-ov\"><\/canvas>\n      <div class=\"aew-sh aew-shl\"><\/div><div class=\"aew-sh aew-shr\"><\/div>\n      <div class=\"aew-h aew-hs\"><\/div><div class=\"aew-h aew-he\"><\/div>\n      <div class=\"aew-gr aew-gra\"><\/div><div class=\"aew-gr aew-grb\"><\/div><div class=\"aew-grl\"><\/div>\n      <div class=\"aew-ph\"><\/div>\n      <input class=\"aew-gin\" type=\"text\" hidden spellcheck=\"false\" aria-label=\"Exact time\">\n      <div class=\"aew-ptp\" hidden><label><span>Time<\/span><input class=\"aew-ti aew-nin aew-ptt\" type=\"text\" spellcheck=\"false\" autocomplete=\"off\" aria-label=\"Envelope point time\"><\/label><label><span>dB<\/span><input class=\"aew-ti aew-nin aew-ptd\" type=\"text\" inputmode=\"decimal\" spellcheck=\"false\" autocomplete=\"off\" aria-label=\"Envelope point level in dB\"><\/label><\/div>\n      <div class=\"aew-zh\">\n        <button type=\"button\" class=\"aew-btn aew-zb aew-zout\" aria-label=\"Zoom out\" data-tip=\"Zoom out, time axis\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M5.5 12h13\"\/><circle class=\"aew-fl\" cx=\"12\" cy=\"6\" r=\"1.7\"\/><circle class=\"aew-fl\" cx=\"12\" cy=\"18\" r=\"1.7\"\/><\/svg><\/button>\n        <button type=\"button\" class=\"aew-btn aew-zb aew-zfit\" aria-label=\"Zoom to fit\" data-tip=\"Show the whole file\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M6 9h12M6 15h12\"\/><\/svg><\/button>\n        <button type=\"button\" class=\"aew-btn aew-zb aew-zin\" aria-label=\"Zoom in\" data-tip=\"Zoom in, time axis\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M12 5.5v13M5.5 12h13\"\/><\/svg><\/button>\n      <\/div>\n      <div class=\"aew-zv\">\n        <button type=\"button\" class=\"aew-btn aew-zb aew-vzi\" aria-label=\"Vertical zoom in\" data-tip=\"Zoom in on amplitude\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M12 5.5v13M5.5 12h13\"\/><\/svg><\/button>\n        <button type=\"button\" class=\"aew-btn aew-zb aew-vz1\" aria-label=\"Vertical zoom reset\" data-tip=\"Reset amplitude zoom to 1\u00d7\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M6 9h12M6 15h12\"\/><\/svg><\/button>\n        <button type=\"button\" class=\"aew-btn aew-zb aew-vzo\" aria-label=\"Vertical zoom out\" data-tip=\"Zoom out on amplitude\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M5.5 12h13\"\/><circle class=\"aew-fl\" cx=\"12\" cy=\"6\" r=\"1.7\"\/><circle class=\"aew-fl\" cx=\"12\" cy=\"18\" r=\"1.7\"\/><\/svg><\/button>\n      <\/div>\n    <\/div>\n    <input class=\"aew-scroll\" type=\"range\" min=\"0\" max=\"1000\" step=\"1\" value=\"0\" style=\"--p:0%\" aria-label=\"Scroll waveform\">\n  <\/div>\n  <div class=\"aew-barw\">\n  <div class=\"aew-bar\">\n    <button type=\"button\" class=\"aew-play\" aria-label=\"Play\" data-tip=\"Play or pause (Space)\"><svg class=\"aew-ip\" viewBox=\"0 0 24 24\"><path d=\"M7 4.5v15a1 1 0 001.5.86l12-7.5a1 1 0 000-1.72l-12-7.5A1 1 0 007 4.5z\"\/><\/svg><svg class=\"aew-ipa\" viewBox=\"0 0 24 24\"><rect x=\"6\" y=\"4\" width=\"4.2\" height=\"16\" rx=\"1.2\"\/><rect x=\"13.8\" y=\"4\" width=\"4.2\" height=\"16\" rx=\"1.2\"\/><\/svg><\/button>\n    <button type=\"button\" class=\"aew-btn aew-ico aew-home\" aria-label=\"To start\" data-tip=\"Jump to the start\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><rect class=\"aew-fl\" x=\"3.9\" y=\"4.5\" width=\"3.2\" height=\"15\"\/><path class=\"aew-fl\" d=\"M7.1 12L20.1 4.5v15z\"\/><\/svg><\/button>\n    <button type=\"button\" class=\"aew-btn aew-tgl aew-rtn\" aria-pressed=\"false\" aria-label=\"Return\" data-tip=\"Return to L after stop\">RTN<\/button>\n    <button type=\"button\" class=\"aew-btn aew-tgl aew-last\" aria-pressed=\"false\" aria-label=\"Last\" data-tip=\"Return to play start\">LAST<\/button>\n    <button type=\"button\" class=\"aew-btn aew-ico aew-lps\" aria-label=\"Loop start\" data-tip=\"Set L locator at cursor\">L<\/button>\n    <button type=\"button\" class=\"aew-btn aew-ico aew-lpe\" aria-label=\"Loop end\" data-tip=\"Set R locator at cursor\">R<\/button>\n    <button type=\"button\" class=\"aew-btn aew-tgl aew-link aew-on\" aria-pressed=\"true\" aria-label=\"Link\" data-tip=\"Selection sets L and R\">LINK<\/button>\n    <button type=\"button\" class=\"aew-btn aew-tgl aew-ico aew-loop\" aria-pressed=\"false\" aria-label=\"Loop\" data-tip=\"Loop between L and R\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M17 1l4 4-4 4\"\/><path d=\"M3 11V9a4 4 0 0 1 4-4h14\"\/><path d=\"M7 23l-4-4 4-4\"\/><path d=\"M21 13v2a4 4 0 0 1-4 4H3\"\/><\/svg><\/button>\n    <button type=\"button\" class=\"aew-btn aew-tgl aew-ico aew-fol aew-on\" aria-pressed=\"true\" aria-label=\"Follow\" data-tip=\"View follows the playhead\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M12 4v16\"\/><path d=\"M2.15 7.275L7.4 12 2.15 16.725\"\/><path d=\"M21.85 7.275L16.6 12l5.25 4.725\"\/><\/svg><\/button>\n    <button type=\"button\" class=\"aew-btn aew-tgl aew-ico aew-snap\" aria-pressed=\"false\" aria-label=\"Snap\" data-tip=\"Snap to beats, markers, cuts\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><g transform=\"translate(0 1.4) rotate(-90 12 10.6)\"><path d=\"M5 3h4.4v8.2a2.6 2.6 0 0 0 5.2 0V3H19v8.2a7 7 0 0 1-14 0z\"\/><path d=\"M5 7.6h4.4M14.6 7.6H19\"\/><\/g><\/svg><\/button>\n    <button type=\"button\" class=\"aew-btn aew-ico aew-zsel\" aria-label=\"Zoom to selection\" data-tip=\"Zoom to the selection\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M1.8 12S5.4 5 12 5s10.2 7 10.2 7-3.6 7-10.2 7S1.8 12 1.8 12z\"\/><circle cx=\"12\" cy=\"12\" r=\"3.1\"\/><\/svg><\/button>\n    <div class=\"aew-tgrp\" role=\"group\" aria-label=\"Edit tools\">\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-ico aew-tcut\" aria-pressed=\"false\" aria-label=\"Scissors\" data-tip=\"Cut audio at cursor (C)\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><circle cx=\"6.5\" cy=\"17.5\" r=\"2.7\"\/><circle cx=\"17.5\" cy=\"17.5\" r=\"2.7\"\/><path d=\"M8.4 15.6L16 4.5\"\/><path d=\"M15.6 15.6L8 4.5\"\/><\/svg><\/button>\n      <button type=\"button\" class=\"aew-btn aew-ico aew-clipl\" aria-label=\"Clip by locators\" data-tip=\"Split at L and R\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M2.2 4v16\"\/><path d=\"M21.8 4v16\"\/><g transform=\"translate(12 12) scale(.72) translate(-12 -11.4)\" stroke-width=\"3.05\"><circle cx=\"6.5\" cy=\"17.5\" r=\"2.7\"\/><circle cx=\"17.5\" cy=\"17.5\" r=\"2.7\"\/><path d=\"M8.4 15.6L16 4.5\"\/><path d=\"M15.6 15.6L8 4.5\"\/><\/g><\/svg><\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-ico aew-tsel aew-on\" aria-pressed=\"true\" aria-label=\"Arrow\" data-tip=\"Select and place cursor (V)\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M5.5 3.5l13 8.3-5.6 1.3 3.2 6-2.6 1.4-3.2-6-4.4 3.9z\"\/><\/svg><\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-ico aew-tmv\" aria-pressed=\"false\" aria-label=\"Hand\" data-tip=\"Move audio parts (H)\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M8 13V6.5a1.5 1.5 0 0 1 3 0V11\"\/><path d=\"M11 11V4.5a1.5 1.5 0 0 1 3 0V11\"\/><path d=\"M14 11V6a1.5 1.5 0 0 1 3 0v6\"\/><path d=\"M17 12V8.5a1.5 1.5 0 0 1 3 0V15a6 6 0 0 1-6 6h-1.5a6 6 0 0 1-4.8-2.4L4.6 15.2a1.6 1.6 0 0 1 2.5-2L8 14.3\"\/><\/svg><\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-ico aew-tscr\" aria-pressed=\"false\" aria-label=\"Scrub\" data-tip=\"Scrub audio by dragging\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path class=\"aew-fl\" d=\"M3.5 9.5v5h3.6L12 18.6V5.4L7.1 9.5z\"\/><path d=\"M15.4 9a4.3 4.3 0 0 1 0 6\"\/><path d=\"M18.2 6.4a8.2 8.2 0 0 1 0 11.2\"\/><\/svg><\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-ico aew-pi aew-on\" role=\"radio\" aria-checked=\"true\" aria-pressed=\"true\" aria-label=\"Insert and push\" data-tip=\"Paste inserts, pushes audio right\"><svg viewBox=\"0 0 30 20\" aria-hidden=\"true\"><g opacity=\".55\"><rect class=\"aew-fl\" x=\"1\" y=\"4.25\" width=\"1.6\" height=\"6\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"3.4\" y=\"1.75\" width=\"1.6\" height=\"11\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"5.8\" y=\"3.25\" width=\"1.6\" height=\"8\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"22.6\" y=\"2.75\" width=\"1.6\" height=\"9\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"25\" y=\"1.25\" width=\"1.6\" height=\"12\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"27.4\" y=\"4.25\" width=\"1.6\" height=\"6\" rx=\".8\"\/><\/g><rect class=\"aew-fl\" x=\"8.8\" y=\"0\" width=\"1.5\" height=\"14.5\" rx=\".75\"\/><rect class=\"aew-fl\" x=\"19.7\" y=\"0\" width=\"1.5\" height=\"14.5\" rx=\".75\"\/><rect class=\"aew-fl\" x=\"12\" y=\"4.75\" width=\"1.6\" height=\"5\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"14.2\" y=\"2.75\" width=\"1.6\" height=\"9\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"16.4\" y=\"4.25\" width=\"1.6\" height=\"6\" rx=\".8\"\/><path d=\"M11.4 16.6H18.2M15.9 14.3L18.2 16.6L15.9 18.9\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg><\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-ico aew-po\" role=\"radio\" aria-checked=\"false\" aria-pressed=\"false\" aria-label=\"Overwrite\" data-tip=\"Paste replaces existing audio\"><svg viewBox=\"0 0 30 20\" aria-hidden=\"true\"><g opacity=\".55\"><rect class=\"aew-fl\" x=\"1\" y=\"7\" width=\"1.6\" height=\"6\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"3.4\" y=\"4.5\" width=\"1.6\" height=\"11\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"5.8\" y=\"6\" width=\"1.6\" height=\"8\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"22.6\" y=\"5.5\" width=\"1.6\" height=\"9\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"25\" y=\"4\" width=\"1.6\" height=\"12\" rx=\".8\"\/><rect class=\"aew-fl\" x=\"27.4\" y=\"7\" width=\"1.6\" height=\"6\" rx=\".8\"\/><\/g><path class=\"aew-fl\" fill-rule=\"evenodd\" d=\"M11.2 3.2h7.6a2.2 2.2 0 0 1 2.2 2.2v9.2a2.2 2.2 0 0 1 -2.2 2.2h-7.6a2.2 2.2 0 0 1 -2.2 -2.2v-9.2a2.2 2.2 0 0 1 2.2 -2.2zM12 7.5h0a0.9 0.9 0 0 1 0.9 0.9v3.2a0.9 0.9 0 0 1 -0.9 0.9h-0a0.9 0.9 0 0 1 -0.9 -0.9v-3.2a0.9 0.9 0 0 1 0.9 -0.9zM15 5.5h0a0.9 0.9 0 0 1 0.9 0.9v7.2a0.9 0.9 0 0 1 -0.9 0.9h-0a0.9 0.9 0 0 1 -0.9 -0.9v-7.2a0.9 0.9 0 0 1 0.9 -0.9zM18 7.5h0a0.9 0.9 0 0 1 0.9 0.9v3.2a0.9 0.9 0 0 1 -0.9 0.9h-0a0.9 0.9 0 0 1 -0.9 -0.9v-3.2a0.9 0.9 0 0 1 0.9 -0.9z\"\/><\/svg><\/button>\n    <\/div>\n    <div class=\"aew-sp\"><\/div>\n    <div class=\"aew-lcd\">\n      <span class=\"aew-lcdf\"><b class=\"aew-tcur\">0:00.000<\/b><\/span>\n      <span class=\"aew-lcdsep\">\/<\/span>\n      <span class=\"aew-lcdf aew-dim\"><em class=\"aew-tt\">0:00.000<\/em><\/span>\n    <\/div>\n  <\/div>\n  <\/div>\n  <div class=\"aew-trim\">\n    <label class=\"aew-fld aew-tf\"><span>Start<\/span><input class=\"aew-ti aew-tin aew-fs\" type=\"text\" inputmode=\"decimal\" spellcheck=\"false\" value=\"0:00.000\"><\/label>\n    <label class=\"aew-fld aew-tf\"><span>End<\/span><input class=\"aew-ti aew-tin aew-fe\" type=\"text\" inputmode=\"decimal\" spellcheck=\"false\" value=\"0:00.000\"><\/label>\n    <div class=\"aew-fld aew-tf\"><span>Length<\/span><b class=\"aew-len\">0:00.000<\/b><\/div>\n    <div class=\"aew-unit\" role=\"radiogroup\" aria-label=\"Show time or samples\">\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-un aew-on\" role=\"radio\" aria-checked=\"true\" data-u=\"t\" data-tip=\"Show positions as time\">TIME<\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-un\" role=\"radio\" aria-checked=\"false\" data-u=\"s\" data-tip=\"Show positions as samples\">SAMPLE<\/button>\n    <\/div>\n    <button type=\"button\" class=\"aew-btn aew-reset\" data-tip=\"Reset locators to whole file\">RESET<\/button>\n  <\/div>\n\n  <section class=\"aew-meter\">\n    <div class=\"aew-mhead\">\n      <h4>Level meter<\/h4>\n      <div class=\"aew-mread\"><span class=\"aew-m1\"><\/span><span class=\"aew-m2\"><\/span><span class=\"aew-m3\"><\/span><\/div>\n      <button type=\"button\" class=\"aew-btn aew-ovl\" data-tip=\"Reset the clip counter\">OVER<\/button>\n    <\/div>\n    <div class=\"aew-mwrap\"><canvas class=\"aew-mcv\"><\/canvas><\/div>\n  <\/section>\n\n  <div class=\"aew-cards\">\n    <section class=\"aew-card aew-mkcard\">\n      <h4 class=\"aew-tlab\"><b>MARKERS NAVIGATOR<\/b><\/h4>\n      <div class=\"aew-mkg\"><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"1\" aria-pressed=\"false\" data-tip=\"Marker 1: set or jump\">1<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"2\" aria-pressed=\"false\" data-tip=\"Marker 2: set or jump\">2<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"3\" aria-pressed=\"false\" data-tip=\"Marker 3: set or jump\">3<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"4\" aria-pressed=\"false\" data-tip=\"Marker 4: set or jump\">4<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"5\" aria-pressed=\"false\" data-tip=\"Marker 5: set or jump\">5<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"6\" aria-pressed=\"false\" data-tip=\"Marker 6: set or jump\">6<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"7\" aria-pressed=\"false\" data-tip=\"Marker 7: set or jump\">7<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"8\" aria-pressed=\"false\" data-tip=\"Marker 8: set or jump\">8<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"9\" aria-pressed=\"false\" data-tip=\"Marker 9: set or jump\">9<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"10\" aria-pressed=\"false\" data-tip=\"Marker 10: set or jump\">10<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"11\" aria-pressed=\"false\" data-tip=\"Marker 11: set or jump\">11<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"12\" aria-pressed=\"false\" data-tip=\"Marker 12: set or jump\">12<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"13\" aria-pressed=\"false\" data-tip=\"Marker 13: set or jump\">13<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"14\" aria-pressed=\"false\" data-tip=\"Marker 14: set or jump\">14<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"15\" aria-pressed=\"false\" data-tip=\"Marker 15: set or jump\">15<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"16\" aria-pressed=\"false\" data-tip=\"Marker 16: set or jump\">16<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"17\" aria-pressed=\"false\" data-tip=\"Marker 17: set or jump\">17<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"18\" aria-pressed=\"false\" data-tip=\"Marker 18: set or jump\">18<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"19\" aria-pressed=\"false\" data-tip=\"Marker 19: set or jump\">19<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"20\" aria-pressed=\"false\" data-tip=\"Marker 20: set or jump\">20<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"21\" aria-pressed=\"false\" data-tip=\"Marker 21: set or jump\">21<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"22\" aria-pressed=\"false\" data-tip=\"Marker 22: set or jump\">22<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"23\" aria-pressed=\"false\" data-tip=\"Marker 23: set or jump\">23<\/button><button type=\"button\" class=\"aew-btn aew-mkb\" data-n=\"24\" aria-pressed=\"false\" data-tip=\"Marker 24: set or jump\">24<\/button><\/div>\n      <div class=\"aew-mknav\"><button type=\"button\" class=\"aew-btn aew-ico aew-mkp\" disabled aria-label=\"Previous marker\" data-tip=\"Jump to previous marker\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path class=\"aew-fl\" d=\"M17 5.5v13L6.5 12z\"\/><\/svg><\/button><button type=\"button\" class=\"aew-btn aew-ico aew-mkn\" disabled aria-label=\"Next marker\" data-tip=\"Jump to next marker\"><svg viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path class=\"aew-fl\" d=\"M7 5.5v13L17.5 12z\"\/><\/svg><\/button><\/div>\n    <\/section>\n    <section class=\"aew-card\">\n      <h4 class=\"aew-tlab\"><b>DSP<\/b><\/h4>\n      <div class=\"aew-rsg\">\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-nrm\" data-tip=\"Set loudness or peak level\">NORMALIZE<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-rsb\" data-tip=\"Lo-fi: lower rate and bits\">RESAMPLE<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-ptb\" data-tip=\"Change pitch in semitones\">PITCH<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-rev\" data-tip=\"Reverse the selected audio\">REVERSE<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-inv\" data-tip=\"Flip polarity of selection\">INVERT<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-sil\" data-tip=\"Replace selection with silence\">SILENCE<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-lcm\" aria-pressed=\"false\" data-tip=\"High-pass filter, remove rumble\">LOW CUT<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-ttb\" data-tip=\"Insert sine or noise\">TEST TONE<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-smb\" data-tip=\"Stereo to mono, whole file\">STEREO TO MONO<\/button>\n        <button type=\"button\" class=\"aew-btn aew-tgl aew-abb\" data-tip=\"About, credits and donation\">ABOUT WAVESONIQ<\/button>\n      <\/div>\n    <\/section>\n\n    <section class=\"aew-card aew-ecard\">\n      <h4 class=\"aew-tlab\"><b>Export audio<\/b><\/h4>\n      <div class=\"aew-row2\">\n        <div class=\"aew-ctl\"><span class=\"aew-lab\">Format<\/span>\n          <select class=\"aew-fmt\"><option value=\"wav\">WAV<\/option><option value=\"aiff\">AIFF<\/option><option value=\"mp3\">MP3<\/option><option value=\"avi\">AVI (PCM audio)<\/option><\/select><\/div>\n        <div class=\"aew-ctl\"><span class=\"aew-lab\">Bit depth<\/span>\n          <select class=\"aew-bits\"><option value=\"16\">16-bit<\/option><option value=\"24\">24-bit<\/option><\/select><\/div>\n      <\/div>\n      <div class=\"aew-row2\">\n        <div class=\"aew-ctl\"><span class=\"aew-lab\">Sample rate<\/span>\n          <select class=\"aew-srt\"><option value=\"0\">Original<\/option><option value=\"44100\">44.1 kHz<\/option><option value=\"48000\">48 kHz<\/option><\/select><\/div>\n        <div class=\"aew-ctl\"><span class=\"aew-lab\">Channels<\/span>\n          <select class=\"aew-chm\"><option value=\"st\">Stereo (joint)<\/option><option value=\"mono\">Mono (summed)<\/option><option value=\"split\">Stereo split (2 mono files)<\/option><\/select><\/div>\n      <\/div>\n      <div class=\"aew-ctl aew-rk\" hidden><span class=\"aew-lab\">Bitrate<\/span>\n        <select class=\"aew-kbps\"><option value=\"128\">128 kbps<\/option><option value=\"160\">160 kbps<\/option><option value=\"192\" selected>192 kbps<\/option><option value=\"256\">256 kbps<\/option><option value=\"320\">320 kbps<\/option><\/select><\/div>\n      <button type=\"button\" class=\"aew-btn aew-pri aew-big aew-exp\" data-tip=\"Save as WAV, MP3, AIFF, AVI\">EXPORT AUDIO<\/button>\n\n    <\/section>\n  <\/div>\n<\/div>\n\n<div class=\"aew-nmod aew-m-nm\" hidden role=\"dialog\" aria-modal=\"true\" aria-label=\"Normalize\">\n  <div class=\"aew-nmbox\">\n    <h4>Normalize<\/h4>\n    <select class=\"aew-nmsel\" aria-label=\"Target\">\n      <option value=\"0\">Standard: -1.0 dBTP<\/option>\n      <option value=\"1\">Spotify: -14 LUFS \/ -1.0 dBTP<\/option>\n      <option value=\"2\">YouTube \/ YouTube Music: -14 LUFS \/ -1.0 dBTP<\/option>\n      <option value=\"3\">SoundCloud: -14 LUFS \/ -1.0 dBTP<\/option>\n      <option value=\"4\">Tidal: -14 LUFS \/ -1.0 dBTP<\/option>\n      <option value=\"5\">Apple Music: -16 LUFS \/ -1.0 dBTP<\/option>\n      <option value=\"6\">Instagram \/ Facebook: -14 LUFS \/ -1.0 dBTP<\/option>\n      <option value=\"7\">Podcasts (Stereo): -16 LUFS \/ -1.0 dBTP<\/option>\n      <option value=\"8\">Podcasts (Mono): -19 LUFS \/ -1.0 dBTP<\/option>\n      <option value=\"9\">EU TV (EBU R128): -23 LUFS \/ -1.0 dBTP<\/option>\n      <option value=\"10\">USA TV (ATSC A\/85): -24 LUFS \/ -2.0 dBTP<\/option>\n      <option value=\"11\">Custom \u2026<\/option>\n    <\/select>\n    <div class=\"aew-row2 aew-nmcu\" hidden>\n      <label class=\"aew-fld\"><span>Loudness (LUFS)<\/span><input class=\"aew-ti aew-nlu\" type=\"text\" inputmode=\"decimal\" spellcheck=\"false\" autocomplete=\"off\" value=\"-16\" placeholder=\"blank = peak only\"><\/label>\n      <label class=\"aew-fld\"><span>True peak (dBTP)<\/span><input class=\"aew-ti aew-ntp\" type=\"text\" inputmode=\"decimal\" spellcheck=\"false\" autocomplete=\"off\" value=\"-1.0\"><\/label>\n    <\/div>\n    <div class=\"aew-nmr\">\n      <div class=\"aew-nmrow\"><span>Selection<\/span><b class=\"aew-nm1\">\u2013<\/b><\/div>\n      <div class=\"aew-nmrow\"><span>Gain<\/span><b class=\"aew-nm2\">\u2013<\/b><\/div>\n      <div class=\"aew-nmrow\"><span>Result<\/span><b class=\"aew-nm3\">\u2013<\/b><\/div>\n    <\/div>\n    <div class=\"aew-grp\"><button type=\"button\" class=\"aew-btn aew-nmc\">Cancel<\/button><button type=\"button\" class=\"aew-btn aew-pri aew-nmok\" disabled>Apply<\/button><\/div>\n  <\/div>\n<\/div>\n\n<div class=\"aew-nmod aew-m-rs\" hidden role=\"dialog\" aria-modal=\"true\" aria-label=\"Resample\">\n  <div class=\"aew-nmbox\">\n    <h4>Resample<\/h4>\n    <div class=\"aew-row2\">\n      <div class=\"aew-ctl\"><span class=\"aew-lab\">Sample rate<\/span>\n        <select class=\"aew-rssel\" aria-label=\"Sample rate\">\n          <option value=\"0\">Original<\/option>\n          <option value=\"8000\">8.0 kHz<\/option>\n          <option value=\"11025\">11.025 kHz<\/option>\n          <option value=\"16000\">16.0 kHz<\/option>\n          <option value=\"22050\">22.05 kHz<\/option>\n          <option value=\"32000\">32.0 kHz<\/option>\n          <option value=\"44100\">44.1 kHz<\/option>\n          <option value=\"48000\">48.0 kHz<\/option>\n        <\/select><\/div>\n      <div class=\"aew-ctl\"><span class=\"aew-lab\">Bit depth<\/span>\n        <select class=\"aew-rsbit\" aria-label=\"Bit depth\">\n          <option value=\"0\">Original<\/option>\n          <option value=\"16\">16-bit<\/option>\n          <option value=\"12\">12-bit<\/option>\n          <option value=\"8\">8-bit<\/option>\n          <option value=\"4\">4-bit<\/option>\n          <option value=\"2\">2-bit<\/option>\n        <\/select><\/div>\n    <\/div>\n    <div class=\"aew-rsg2\">\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-rspl\"><svg class=\"aew-pvi\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M7.5 4.5v15l12.5-7.5z\"\/><\/svg>PREVIEW<\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-rsdi\" aria-pressed=\"false\" title=\"Dither: adds a little noise before the bits are reduced (TPDF)\">DITHER<\/button>\n    <\/div>\n    <div class=\"aew-nmr\">\n      <div class=\"aew-nmrow\"><span>Rate<\/span><b class=\"aew-rs1\">\u2013<\/b><\/div>\n      <div class=\"aew-nmrow\"><span>Bits<\/span><b class=\"aew-rs2\">\u2013<\/b><\/div>\n    <\/div>\n    <div class=\"aew-grp\"><button type=\"button\" class=\"aew-btn aew-rsc\">Cancel<\/button><button type=\"button\" class=\"aew-btn aew-pri aew-rsok\">Apply<\/button><\/div>\n  <\/div>\n<\/div>\n<div class=\"aew-nmod aew-m-pt\" hidden role=\"dialog\" aria-modal=\"true\" aria-label=\"Pitch\">\n  <div class=\"aew-nmbox\">\n    <h4>Pitch<\/h4>\n    <div class=\"aew-prow\">\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-pplay\"><svg class=\"aew-pvi\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M7.5 4.5v15l12.5-7.5z\"\/><\/svg>PREVIEW<\/button>\n      <div class=\"aew-pwrap\">\n        <div class=\"aew-pscale\" aria-hidden=\"true\"><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 0.00000)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.04167)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.08333)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.12500)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.16667)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.20833)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.25000)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.29167)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.33333)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.37500)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.41667)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.45833)\"><\/i><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 0.50000)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.54167)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.58333)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.62500)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.66667)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.70833)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.75000)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.79167)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.83333)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.87500)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.91667)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.95833)\"><\/i><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 1.00000)\"><\/i><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.00000)\">-12<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.12500)\">-9<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.25000)\">-6<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.37500)\">-3<\/em><em class=\"aew-ptl aew-ptz\" style=\"left:calc(11px + (100% - 22px) * 0.50000)\">0<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.62500)\">+3<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.75000)\">+6<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.87500)\">+9<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 1.00000)\">+12<\/em><\/div>\n        <input class=\"aew-ps\" type=\"range\" min=\"-12\" max=\"12\" step=\"1\" value=\"0\" aria-label=\"Pitch\">\n      <\/div>\n    <\/div>\n    <div class=\"aew-grp\">\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-pfree\" aria-pressed=\"false\">FREE<\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-pmv aew-on\" aria-pressed=\"true\">VARISPEED<\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-pml\" aria-pressed=\"false\">KEEP LENGTH<\/button>\n    <\/div>\n    <div class=\"aew-nmr\">\n      <div class=\"aew-nmrow\"><span>Pitch<\/span><span class=\"aew-nvw\"><input class=\"aew-ti aew-nin aew-pin\" type=\"text\" inputmode=\"decimal\" spellcheck=\"false\" autocomplete=\"off\" value=\"0\" aria-label=\"Pitch in semitones. Type an exact value\"><i>st<\/i><b class=\"aew-pv\">\u00d71.000<\/b><\/span><\/div>\n      <div class=\"aew-nmrow\"><span>Length<\/span><b class=\"aew-pl\">\u2013<\/b><\/div>\n    <\/div>\n    <div class=\"aew-grp\"><button type=\"button\" class=\"aew-btn aew-ptc\">Cancel<\/button><button type=\"button\" class=\"aew-btn aew-pri aew-ptok\" disabled>Apply<\/button><\/div>\n  <\/div>\n<\/div>\n\n<div class=\"aew-nmod aew-m-lc\" hidden role=\"dialog\" aria-modal=\"true\" aria-label=\"Low cut\">\n  <div class=\"aew-nmbox\">\n    <h4>Low cut<\/h4>\n    <div class=\"aew-prow\">\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-lpl\"><svg class=\"aew-pvi\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M7.5 4.5v15l12.5-7.5z\"\/><\/svg>PREVIEW<\/button>\n      <div class=\"aew-pwrap\">\n        <div class=\"aew-pscale\" aria-hidden=\"true\"><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 0.00000)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.12596)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.21534)\"><\/i><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 0.28466)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.34130)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.38919)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.43068)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.46727)\"><\/i><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 0.50000)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.62596)\"><\/i><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 0.71534)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.78466)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.84130)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.88919)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.93068)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.96727)\"><\/i><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 1.00000)\"><\/i><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.00000)\">20<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.28466)\">50<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.50000)\">100<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.71534)\">200<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 1.00000)\">500<\/em><\/div>\n        <input class=\"aew-lcs\" type=\"range\" min=\"0\" max=\"1000\" step=\"1\" value=\"431\" aria-label=\"Low cut frequency\">\n      <\/div>\n    <\/div>\n    <div class=\"aew-grp\">\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-lcon\" aria-pressed=\"false\">ON<\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-lcord\">6 dB<\/button>\n    <\/div>\n    <div class=\"aew-nmr\">\n      <div class=\"aew-nmrow\"><span>Frequency<\/span><span class=\"aew-nvw\"><input class=\"aew-ti aew-nin aew-lcin\" type=\"text\" inputmode=\"decimal\" spellcheck=\"false\" autocomplete=\"off\" value=\"80.0\" aria-label=\"Low cut frequency in Hz. Type an exact value\"><i>Hz<\/i><\/span><\/div>\n      <div class=\"aew-nmrow\"><span>Slope<\/span><b class=\"aew-lcsl\">6 dB\/oct<\/b><\/div>\n    <\/div>\n    <div class=\"aew-grp\"><button type=\"button\" class=\"aew-btn aew-lcc\">Close<\/button><\/div>\n  <\/div>\n<\/div>\n\n<div class=\"aew-nmod aew-m-tt\" hidden role=\"dialog\" aria-modal=\"true\" aria-label=\"Test tone\">\n  <div class=\"aew-nmbox\">\n    <h4>Test tone<\/h4>\n    <div class=\"aew-ttt\" role=\"radiogroup\" aria-label=\"Type\">\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-tty aew-on\" role=\"radio\" aria-checked=\"true\" data-t=\"sine\">SINE<\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-tty\" role=\"radio\" aria-checked=\"false\" data-t=\"white\">WHITE NOISE<\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-tty\" role=\"radio\" aria-checked=\"false\" data-t=\"pink\">PINK NOISE<\/button>\n    <\/div>\n    <div class=\"aew-prow\">\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-ttpl\"><svg class=\"aew-pvi\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M7.5 4.5v15l12.5-7.5z\"\/><\/svg>PREVIEW<\/button>\n      <div class=\"aew-pwrap aew-ttfw\">\n        <div class=\"aew-pscale\" aria-hidden=\"true\"><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 0.00000)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.05870)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.10034)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.13265)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.15904)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.18136)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.20069)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.21774)\"><\/i><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 0.23299)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.33333)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.39203)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.43368)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.46598)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.49237)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.51469)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.53402)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.55107)\"><\/i><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 0.56632)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.66667)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.72536)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.76701)\"><\/i><i class=\"aew-pt aew-pt2\" style=\"left:calc(11px + (100% - 22px) * 0.79931)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.82571)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.84802)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.86735)\"><\/i><i class=\"aew-pt aew-pt1\" style=\"left:calc(11px + (100% - 22px) * 0.88440)\"><\/i><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 0.89966)\"><\/i><i class=\"aew-pt aew-pt3\" style=\"left:calc(11px + (100% - 22px) * 1.00000)\"><\/i><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.00000)\">20<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.23299)\">100<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.56632)\">1k<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 0.89966)\">10k<\/em><em class=\"aew-ptl\" style=\"left:calc(11px + (100% - 22px) * 1.00000)\">20k<\/em><\/div>\n        <input class=\"aew-lcs aew-ttf\" type=\"range\" min=\"0\" max=\"1000\" step=\"1\" value=\"448\" aria-label=\"Frequency\">\n      <\/div>\n    <\/div>\n    <div class=\"aew-row2\">\n      <label class=\"aew-fld aew-ttfl\"><span>Frequency (Hz)<\/span><input class=\"aew-ti aew-tthz\" type=\"text\" inputmode=\"decimal\" spellcheck=\"false\" value=\"440\"><\/label>\n      <label class=\"aew-fld\"><span>Time<\/span><input class=\"aew-ti aew-ttd\" type=\"text\" inputmode=\"decimal\" spellcheck=\"false\" value=\"0:05.000\"><\/label>\n    <\/div>\n    <div class=\"aew-ctl\"><span class=\"aew-lab\">Level (peak)<\/span><span class=\"aew-nvw aew-ttlw\"><input class=\"aew-ti aew-nin aew-ttlin\" type=\"text\" inputmode=\"decimal\" spellcheck=\"false\" autocomplete=\"off\" value=\"-12\" aria-label=\"Level in dB. Type an exact value\"><i>dB<\/i><\/span><input class=\"aew-ttl\" type=\"range\" min=\"-60\" max=\"0\" step=\"1\" value=\"-12\" aria-label=\"Level\"><\/div>\n    <div class=\"aew-nmr\">\n      <div class=\"aew-nmrow\"><span>Inserted at cursor<\/span><b class=\"aew-tt1\">\u2013<\/b><\/div>\n      <div class=\"aew-nmrow\"><span>Length<\/span><b class=\"aew-tt2\">\u2013<\/b><\/div>\n    <\/div>\n    <div class=\"aew-grp\"><button type=\"button\" class=\"aew-btn aew-ttc\">Cancel<\/button><button type=\"button\" class=\"aew-btn aew-pri aew-ttok\">Insert<\/button><\/div>\n  <\/div>\n<\/div>\n\n<div class=\"aew-nmod aew-m-sm\" hidden role=\"dialog\" aria-modal=\"true\" aria-label=\"Stereo to mono\">\n  <div class=\"aew-nmbox\">\n    <h4>Stereo to mono<\/h4>\n    <p class=\"aew-note\">Turns the whole file into mono: keep the left channel, keep the right channel, or mix both together. Undo brings the stereo file back.<\/p>\n    <div class=\"aew-smg\" role=\"radiogroup\" aria-label=\"Channel to keep\">\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-smk aew-on\" role=\"radio\" aria-checked=\"true\" data-k=\"0\">KEEP LEFT<\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-smk\" role=\"radio\" aria-checked=\"false\" data-k=\"1\">KEEP RIGHT<\/button>\n      <button type=\"button\" class=\"aew-btn aew-tgl aew-smk\" role=\"radio\" aria-checked=\"false\" data-k=\"2\" title=\"Mix: (left + right) \/ 2\">MIX L+R<\/button>\n    <\/div>\n    <div class=\"aew-grp\"><button type=\"button\" class=\"aew-btn aew-smcancel\">Cancel<\/button><button type=\"button\" class=\"aew-btn aew-pri aew-smok\">Apply<\/button><\/div>\n  <\/div>\n<\/div>\n\n<div class=\"aew-nmod aew-m-im\" hidden role=\"dialog\" aria-modal=\"true\" aria-label=\"Add audio\">\n  <div class=\"aew-nmbox\">\n    <h4>Add audio<\/h4>\n    <p class=\"aew-note aew-imtxt\"><\/p>\n    <p class=\"aew-note aew-sm aew-imlist\"><\/p>\n    <div class=\"aew-grp\"><button type=\"button\" class=\"aew-btn aew-imcancel\">Cancel<\/button><button type=\"button\" class=\"aew-btn aew-imrep\">Replace current audio<\/button><button type=\"button\" class=\"aew-btn aew-pri aew-imadd\">Add to end<\/button><\/div>\n  <\/div>\n<\/div>\n\n<div class=\"aew-nmod aew-m-ab\" hidden role=\"dialog\" aria-modal=\"true\" aria-label=\"About Wavesoniq\">\n  <div class=\"aew-nmbox aew-abbox\">\n    <h4>About Wavesoniq<\/h4>\n    <p class=\"aew-abver\">Version 1.0<\/p>\n    <p class=\"aew-abmade\">Made by Anders Kisling 2026<\/p>\n    <p class=\"aew-abdon\"><a class=\"aew-donate\">Feel free to donate<\/a><\/p>\n    <div class=\"aew-grp\"><button type=\"button\" class=\"aew-btn aew-pri aew-abok\">Close<\/button><\/div>\n  <\/div>\n<\/div>\n\n<div class=\"aew-dlg aew-nmod\" hidden role=\"dialog\" aria-modal=\"true\" aria-label=\"Save\">\n        <div class=\"aew-dlgin aew-nmbox\">\n          <h4 class=\"aew-dt\">Save as<\/h4>\n          <div class=\"aew-fld aew-dnf\"><span>File name<\/span><div class=\"aew-nm\"><input class=\"aew-ti aew-fname\" type=\"text\" spellcheck=\"false\" autocomplete=\"off\" aria-label=\"File name\"><b class=\"aew-ext\">.wav<\/b><\/div><\/div>\n          <div class=\"aew-fld aew-drng\" hidden><span>Range<\/span><div class=\"aew-drow\"><button type=\"button\" class=\"aew-btn aew-tgl aew-rg aew-rgw aew-on\" data-r=\"w\" aria-pressed=\"true\">ENTIRE FILE<\/button><button type=\"button\" class=\"aew-btn aew-tgl aew-rg aew-rgs\" data-r=\"s\" aria-pressed=\"false\">SELECTION ONLY<\/button><button type=\"button\" class=\"aew-btn aew-tgl aew-rg aew-rga\" data-r=\"a\" aria-pressed=\"false\">ALL SECTIONS<\/button><\/div><span class=\"aew-drsum\" aria-live=\"polite\"><\/span><\/div>\n          <div class=\"aew-fld aew-dmeta\" hidden><span>Metadata<\/span><div class=\"aew-dmrow\"><span class=\"aew-dmsum\">None<\/span><button type=\"button\" class=\"aew-btn aew-dmbtn\">Edit \u2026<\/button><\/div><\/div>\n          <p class=\"aew-note aew-sm aew-dnote\"><\/p>\n          <div class=\"aew-grp\"><button type=\"button\" class=\"aew-btn aew-dcancel\">Cancel<\/button><button type=\"button\" class=\"aew-btn aew-pri aew-dok\">Save<\/button><\/div>\n        <\/div>\n      <\/div>\n\n<div class=\"aew-nmod aew-m-meta\" hidden role=\"dialog\" aria-modal=\"true\" aria-label=\"Metadata\">\n  <div class=\"aew-nmbox aew-mtbox\">\n    <h4>Metadata<\/h4>\n    <p class=\"aew-note aew-sm aew-mtfmt\"><\/p>\n    <div class=\"aew-mtgrid\">\n      <label class=\"aew-mtf aew-wide\" data-k=\"title\" data-f=\"wav aiff avi mp3\"><span>Title<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"title\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\"><\/label>\n      <label class=\"aew-mtf\" data-k=\"artist\" data-f=\"wav aiff avi mp3\"><span>Artist<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"artist\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\"><\/label>\n      <label class=\"aew-mtf\" data-k=\"album\" data-f=\"wav avi mp3\"><span>Album<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"album\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\"><\/label>\n      <label class=\"aew-mtf\" data-k=\"albumArtist\" data-f=\"mp3\"><span>Album artist<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"albumArtist\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\"><\/label>\n      <label class=\"aew-mtf\" data-k=\"year\" data-f=\"wav avi mp3\"><span>Year<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"year\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\" placeholder=\"2026\"><\/label>\n      <label class=\"aew-mtf\" data-k=\"track\" data-f=\"mp3\"><span>Track<\/span><span class=\"aew-mttr\"><input class=\"aew-mti\" type=\"text\" inputmode=\"numeric\" data-k=\"track\" maxlength=\"4\" spellcheck=\"false\" autocomplete=\"off\" aria-label=\"Track number\"><i>of<\/i><input class=\"aew-mti\" type=\"text\" inputmode=\"numeric\" data-k=\"trackTotal\" maxlength=\"4\" spellcheck=\"false\" autocomplete=\"off\" aria-label=\"Number of tracks\"><\/span><\/label>\n      <label class=\"aew-mtf\" data-k=\"disc\" data-f=\"mp3\"><span>Disc<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"disc\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\" inputmode=\"numeric\"><\/label>\n      <label class=\"aew-mtf\" data-k=\"genre\" data-f=\"wav avi mp3\"><span>Genre<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"genre\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\" list=\"aew-genres\"><\/label>\n      <label class=\"aew-mtf\" data-k=\"composer\" data-f=\"mp3\"><span>Composer<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"composer\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\"><\/label>\n      <label class=\"aew-mtf\" data-k=\"publisher\" data-f=\"mp3\"><span>Publisher<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"publisher\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\"><\/label>\n      <label class=\"aew-mtf\" data-k=\"copyright\" data-f=\"wav aiff avi mp3\"><span>Copyright<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"copyright\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\" placeholder=\"\u00a9 2026 Name\"><\/label>\n      <label class=\"aew-mtf\" data-k=\"bpm\" data-f=\"mp3\"><span>BPM<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"bpm\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\" inputmode=\"numeric\"><\/label>\n      <label class=\"aew-mtf\" data-k=\"isrc\" data-f=\"mp3\"><span>ISRC<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"isrc\" maxlength=\"120\" spellcheck=\"false\" autocomplete=\"off\"><\/label>\n      <label class=\"aew-mtf aew-wide\" data-k=\"comment\" data-f=\"wav aiff avi mp3\"><span>Comment<\/span><input class=\"aew-mti\" type=\"text\" data-k=\"comment\" maxlength=\"300\" spellcheck=\"false\" autocomplete=\"off\"><\/label>\n    <\/div>\n    <datalist id=\"aew-genres\"><option value=\"Blues\"><\/option><option value=\"Classic Rock\"><\/option><option value=\"Country\"><\/option><option value=\"Dance\"><\/option><option value=\"Disco\"><\/option><option value=\"Funk\"><\/option><option value=\"Grunge\"><\/option><option value=\"Hip-Hop\"><\/option><option value=\"Jazz\"><\/option><option value=\"Metal\"><\/option><option value=\"New Age\"><\/option><option value=\"Oldies\"><\/option><option value=\"Other\"><\/option><option value=\"Pop\"><\/option><option value=\"R&amp;B\"><\/option><option value=\"Rap\"><\/option><option value=\"Reggae\"><\/option><option value=\"Rock\"><\/option><option value=\"Techno\"><\/option><option value=\"Industrial\"><\/option><option value=\"Alternative\"><\/option><option value=\"Ska\"><\/option><option value=\"Death Metal\"><\/option><option value=\"Pranks\"><\/option><option value=\"Soundtrack\"><\/option><option value=\"Euro-Techno\"><\/option><option value=\"Ambient\"><\/option><option value=\"Trip-Hop\"><\/option><option value=\"Vocal\"><\/option><option value=\"Jazz+Funk\"><\/option><option value=\"Fusion\"><\/option><option value=\"Trance\"><\/option><option value=\"Classical\"><\/option><option value=\"Instrumental\"><\/option><option value=\"Acid\"><\/option><option value=\"House\"><\/option><option value=\"Game\"><\/option><option value=\"Sound Clip\"><\/option><option value=\"Gospel\"><\/option><option value=\"Noise\"><\/option><option value=\"AlternRock\"><\/option><option value=\"Bass\"><\/option><option value=\"Soul\"><\/option><option value=\"Punk\"><\/option><option value=\"Space\"><\/option><option value=\"Meditative\"><\/option><option value=\"Instrumental Pop\"><\/option><option value=\"Instrumental Rock\"><\/option><option value=\"Ethnic\"><\/option><option value=\"Gothic\"><\/option><option value=\"Darkwave\"><\/option><option value=\"Techno-Industrial\"><\/option><option value=\"Electronic\"><\/option><option value=\"Pop-Folk\"><\/option><option value=\"Eurodance\"><\/option><option value=\"Dream\"><\/option><option value=\"Southern Rock\"><\/option><option value=\"Comedy\"><\/option><option value=\"Cult\"><\/option><option value=\"Gangsta\"><\/option><option value=\"Top 40\"><\/option><option value=\"Christian Rap\"><\/option><option value=\"Pop\/Funk\"><\/option><option value=\"Jungle\"><\/option><option value=\"Native American\"><\/option><option value=\"Cabaret\"><\/option><option value=\"New Wave\"><\/option><option value=\"Psychedelic\"><\/option><option value=\"Rave\"><\/option><option value=\"Showtunes\"><\/option><option value=\"Trailer\"><\/option><option value=\"Lo-Fi\"><\/option><option value=\"Tribal\"><\/option><option value=\"Acid Punk\"><\/option><option value=\"Acid Jazz\"><\/option><option value=\"Polka\"><\/option><option value=\"Retro\"><\/option><option value=\"Musical\"><\/option><option value=\"Rock &amp; Roll\"><\/option><option value=\"Hard Rock\"><\/option><option value=\"Audiobook\"><\/option><option value=\"Podcast\"><\/option><option value=\"Speech\"><\/option><\/datalist>\n    <div class=\"aew-mtcov\" hidden>\n      <div class=\"aew-mtimg\" aria-label=\"Cover preview\"><\/div>\n      <div class=\"aew-mtcb\">\n        <div class=\"aew-mtct\">Cover image (front cover, saved as JPG)<\/div>\n        <div class=\"aew-grp\"><button type=\"button\" class=\"aew-btn aew-mtpick\">Choose image \u2026<\/button><button type=\"button\" class=\"aew-btn aew-mtrm\" disabled>Remove<\/button><\/div>\n        <p class=\"aew-note aew-sm aew-mtcn\">JPG, PNG or WebP. It is cropped to a square and saved as a JPG of up to 1000 \u00d7 1000 px.<\/p>\n        <input class=\"aew-mtfile\" type=\"file\" accept=\"image\/jpeg,image\/png,image\/webp,image\/gif\" hidden>\n      <\/div>\n    <\/div>\n    <div class=\"aew-grp aew-mtbtns\"><button type=\"button\" class=\"aew-btn aew-mtclear\">Clear all<\/button><button type=\"button\" class=\"aew-btn aew-mtcancel\">Cancel<\/button><button type=\"button\" class=\"aew-btn aew-pri aew-mtok\">Done<\/button><\/div>\n  <\/div>\n<\/div>\n\n<script data-cfasync=\"false\" data-no-optimize=\"1\" data-noptimize=\"1\" data-no-defer=\"1\" data-no-minify=\"1\" data-nowprocket data-pagespeed-no-defer>\n(function(){\nfunction showFatal(msg){\n  try{\n    var r=document.querySelector('.audio-editor-widget');if(!r)return;\n    var d=r.querySelector('.aew-fatal');\n    if(!d){d=document.createElement('div');d.className='aew-fatal';d.setAttribute('role','alert');d.style.cssText='margin:0 0 12px;padding:10px 14px;border:1px solid #ff4055;border-radius:10px;background:#2a1217;color:#ffc2c9;font:12.5px\/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap;word-break:break-word';r.insertBefore(d,r.firstChild);}\n    if(d.textContent.indexOf(msg)<0)d.textContent=(d.textContent?d.textContent+'\\n':'Wavesoniq error \u2013 please send this text to the developer:\\n')+msg;\n  }catch(_){}\n}\nwindow.addEventListener('error',function(ev){\n  var f=String(ev&&ev.filename||'');\n  if(f&&f.split('#')[0]!==String(location.href).split('#')[0])return;\n  showFatal((ev.message||'Unknown error')+(ev.lineno?'  (line '+ev.lineno+':'+(ev.colno||0)+')':''));\n});\nwindow.addEventListener('unhandledrejection',function(ev){\n  var e=ev&&ev.reason;showFatal('Promise error: '+(e&&e.message?e.message:String(e)));\n});\n\/* MP3-encoder (lamejs) hentes kun ved MP3-eksport. L\u00e6g evt. din egen kopi i WordPress' mediebibliotek og s\u00e6t dens URL f\u00f8rst i listen. *\/\nvar ACTIVE=null,keysBound=false,CLIP=null;\n\/* filv\u00e6lger-API'erne (gem \/ v\u00e6lg mappe) virker ikke i en iframe fra et andet dom\u00e6ne \u2013 s\u00e5 bruges almindelig download *\/\nfunction fsPick(n){\n  if(typeof window[n]!=='function')return false;\n  try{if(window.top!==window.self){void window.top.location.href;}}catch(e){return false;}\n  return true;\n}\nvar LAME_SOURCES=['https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/lamejs\/1.2.1\/lame.min.js','https:\/\/cdn.jsdelivr.net\/npm\/lamejs@1.2.1\/lame.min.js'];\nvar lamePromise=null;\nfunction lameReady(){return !!(window.lamejs&&window.lamejs.Mp3Encoder);}\nfunction loadLame(){\n  if(lameReady())return Promise.resolve(window.lamejs);\n  if(lamePromise)return lamePromise;\n  lamePromise=new Promise(function(res,rej){\n    var i=0;\n    (function next(){\n      if(i>=LAME_SOURCES.length){lamePromise=null;rej(new Error('Could not load the MP3 encoder. Export as WAV, or point LAME_SOURCES to a self-hosted lame.min.js.'));return;}\n      var s=document.createElement('script');s.src=LAME_SOURCES[i++];s.async=true;\n      s.onload=function(){lameReady()?res(window.lamejs):next();};\n      s.onerror=function(){if(s.parentNode)s.parentNode.removeChild(s);next();};\n      document.head.appendChild(s);\n    })();\n  });\n  return lamePromise;\n}\nfunction tick(){return new Promise(function(r){setTimeout(r,0)});}\n\/* ---------- Eksport: AIFF-hj\u00e6lper ---------- *\/\nfunction aiffRate(rate){\n  var o=new Uint8Array(10);\n  if(!(rate>0))return o;\n  var e=Math.floor(Math.log(rate)\/Math.LN2);\n  if(Math.pow(2,e)>rate)e--;\n  var m=rate\/Math.pow(2,e),hi=Math.floor(m*2147483648),lo=Math.floor((m*2147483648-hi)*4294967296),x=e+16383;\n  o[0]=(x>>8)&127;o[1]=x&255;\n  o[2]=(hi>>>24)&255;o[3]=(hi>>>16)&255;o[4]=(hi>>>8)&255;o[5]=hi&255;\n  o[6]=(lo>>>24)&255;o[7]=(lo>>>16)&255;o[8]=(lo>>>8)&255;o[9]=lo&255;\n  return o;\n}\nfunction bstr(s){var o=new Uint8Array(s.length),i;for(i=0;i<s.length;i++)o[i]=s.charCodeAt(i)&255;return o;}\n\/* ---------- Import af video (mp4, m4v, mov, avi) og AAC: lydsporet l\u00e6ses direkte ud af filen uden at hente hele videoen ---------- *\/\nvar SFR=[96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350];\nfunction rdAt(file,off,len){return file.slice(off,off+len).arrayBuffer();}\nfunction fc4(d,o){return String.fromCharCode(d.getUint8(o),d.getUint8(o+1),d.getUint8(o+2),d.getUint8(o+3));}\nfunction mpBoxes(d,s,e){\n  var out=[],p=s;\n  while(p+8<=e){\n    var sz=d.getUint32(p),tp=fc4(d,p+4),hd=8;\n    if(sz===1){if(p+16>e)break;sz=d.getUint32(p+8)*4294967296+d.getUint32(p+12);hd=16;}\n    else if(sz===0)sz=e-p;\n    if(sz<hd)break;\n    if(p+sz>e)sz=e-p;\n    out.push({t:tp,p:p,s:p+hd,e:p+sz});\n    p+=sz;\n  }\n  return out;\n}\nfunction mpFind(d,b,path){\n  var cur=b,i,j,bs,f;\n  for(i=0;i<path.length;i++){\n    bs=mpBoxes(d,cur.s,cur.e);f=null;\n    for(j=0;j<bs.length;j++)if(bs[j].t===path[i]){f=bs[j];break;}\n    if(!f)return null;cur=f;\n  }\n  return cur;\n}\nfunction mpDeep(d,s,e,type,depth){\n  var bs=mpBoxes(d,s,e),i,r;\n  for(i=0;i<bs.length;i++){\n    if(bs[i].t===type)return bs[i];\n    if(depth>0&&(bs[i].t==='wave'||bs[i].t==='mp4a')){r=mpDeep(d,bs[i].s,bs[i].e,type,depth-1);if(r)return r;}\n  }\n  return null;\n}\nfunction esdsParse(d,b){\n  var p=b.s+4,e=b.e,r={oti:0,asc:null};\n  function ln(){var n=0,k,c;for(k=0;k<4;k++){c=d.getUint8(p++);n=(n<<7)|(c&127);if(!(c&128))break;}return n;}\n  while(p<e){\n    var tag=d.getUint8(p++),len=ln(),end=p+len;\n    if(tag===3){p+=2;var fl=d.getUint8(p++);if(fl&128)p+=2;if(fl&64)p+=1+d.getUint8(p);if(fl&32)p+=2;continue;}\n    if(tag===4){r.oti=d.getUint8(p);p+=13;continue;}\n    if(tag===5){r.asc=new Uint8Array(d.buffer.slice(d.byteOffset+p,d.byteOffset+p+len));p=end;continue;}\n    p=end;\n  }\n  return r;\n}\nfunction ascParse(a){\n  var bit=0;\n  function rb(n){var v=0,i;for(i=0;i<n;i++){v=(v*2)+((a[bit>>3]>>(7-(bit&7)))&1);bit++;}return v;}\n  var aot=rb(5);if(aot===31)aot=32+rb(6);\n  var sfi=rb(4),sr=(sfi===15)?rb(24):SFR[sfi],ch=rb(4);\n  if(aot===5||aot===29){var es=rb(4);if(es===15)rb(24);aot=rb(5);if(aot===31)aot=32+rb(6);}\n  return {aot:aot,sfi:sfi,sr:sr,ch:ch};\n}\nfunction adtsHead(aot,sfi,ch,len){\n  var fl=len+7,h=new Uint8Array(7);\n  h[0]=0xFF;h[1]=0xF1;\n  h[2]=(((aot-1)&3)<<6)|((sfi&15)<<2)|((ch>>2)&1);\n  h[3]=((ch&3)<<6)|((fl>>11)&3);\n  h[4]=(fl>>3)&255;\n  h[5]=((fl&7)<<5)|0x1F;\n  h[6]=0xFC;\n  return h;\n}\nfunction adtsFrames(u8){\n  var out=[],p=0,asc=null,sr=0,ch=0,aot=2;\n  while(p+7<=u8.length){\n    if(u8[p]!==0xFF||(u8[p+1]&0xF0)!==0xF0){p++;continue;}\n    var prot=u8[p+1]&1,a=((u8[p+2]>>6)&3)+1,sfi=(u8[p+2]>>2)&15,cn=((u8[p+2]&1)<<2)|(u8[p+3]>>6),fl=((u8[p+3]&3)<<11)|(u8[p+4]<<3)|(u8[p+5]>>5),hl=prot?7:9;\n    if(fl<hl||p+fl>u8.length)break;\n    if(!asc){asc=new Uint8Array([(a<<3)|(sfi>>1),((sfi&1)<<7)|(cn<<3)]);sr=SFR[sfi]||0;ch=cn;aot=a;}\n    out.push(u8.subarray(p+hl,p+fl));p+=fl;\n  }\n  return {frames:out,asc:asc,sr:sr,ch:ch,aot:aot};\n}\nfunction wavHead(ch,rate,bits,fl,dlen){\n  var b=new ArrayBuffer(44),v=new DataView(b),i,s='RIFF';\n  function ws(o,t){for(i=0;i<t.length;i++)v.setUint8(o+i,t.charCodeAt(i));}\n  ws(0,'RIFF');v.setUint32(4,36+dlen,true);ws(8,'WAVE');ws(12,'fmt ');v.setUint32(16,16,true);v.setUint16(20,fl?3:1,true);v.setUint16(22,ch,true);\n  v.setUint32(24,rate,true);v.setUint32(28,rate*ch*bits\/8,true);v.setUint16(32,ch*bits\/8,true);v.setUint16(34,bits,true);ws(36,'data');v.setUint32(40,dlen,true);\n  return new Uint8Array(b);\n}\nvar PCMQT={'sowt':{b:2,be:false},'twos':{b:2,be:true},'raw ':{b:1,be:false},'in24':{b:3,be:true},'in32':{b:4,be:true},'fl32':{b:4,be:true,fl:true}};\nasync function demuxMp4(file){\n  var size=file.size,off=0,d=null,i,j;\n  while(off+8<=size){\n    var hb=await rdAt(file,off,16),h=new DataView(hb),sz=h.getUint32(0),tp=fc4(h,4),hd=8;\n    if(sz===1&&hb.byteLength>=16){sz=h.getUint32(8)*4294967296+h.getUint32(12);hd=16;}\n    else if(sz===0)sz=size-off;\n    if(sz<hd)break;\n    if(tp==='moov'){d=new DataView(await rdAt(file,off+hd,sz-hd));break;}\n    off+=sz;\n  }\n  if(!d)throw new Error('Could not find the audio index in this video file.');\n  var root={s:0,e:d.byteLength},traks=mpBoxes(d,0,d.byteLength).filter(function(b){return b.t==='trak';}),mvhd=mpFind(d,root,['mvhd']);\n  var mvTs=mvhd?d.getUint32(mvhd.s+(d.getUint8(mvhd.s)===1?20:12)):1000,tk=null,info=null;\n  for(i=0;i<traks.length&&!tk;i++){\n    var hd2=mpFind(d,traks[i],['mdia','hdlr']);\n    if(hd2&&fc4(d,hd2.s+8)==='soun')tk=traks[i];\n  }\n  if(!tk)throw new Error('No audio track found in this video.');\n  var mdhd=mpFind(d,tk,['mdia','mdhd']),mdTs=mdhd?d.getUint32(mdhd.s+(d.getUint8(mdhd.s)===1?20:12)):44100;\n  var stbl=mpFind(d,tk,['mdia','minf','stbl']),stsd=stbl&&mpFind(d,stbl,['stsd']),stsz=stbl&&mpFind(d,stbl,['stsz']),stsc=stbl&&mpFind(d,stbl,['stsc']);\n  var stco=stbl&&mpFind(d,stbl,['stco']),co64=stbl&&!stco&&mpFind(d,stbl,['co64']);\n  if(!stsd||!stsz||!stsc||!(stco||co64)){\n    if(mpFind(d,root,['mvex']))throw new Error('Fragmented MP4 files are not supported.');\n    throw new Error('The audio track has no sample table.');\n  }\n  var e0=stsd.s+8,esz=d.getUint32(e0),fmt=fc4(d,e0+4),ver=d.getUint16(e0+16),ch=d.getUint16(e0+24),bits=d.getUint16(e0+26),rate=d.getUint32(e0+32)>>>16;\n  var cs=e0+36+(ver===1?16:(ver===2?36:0)),codec=null,asc=null,pcm=null,ac=null;\n  if(fmt==='mp4a'||fmt==='.mp3'){\n    var es=mpDeep(d,cs,e0+esz,'esds',2),ed=es?esdsParse(d,es):{oti:0,asc:null};\n    if(fmt==='.mp3'||ed.oti===0x6B||ed.oti===0x69)codec='mp3';\n    else if(ed.asc||ed.oti===0x40||ed.oti===0x66||ed.oti===0x67||ed.oti===0x68){\n      codec='aac';asc=ed.asc;\n      if(!asc)throw new Error('The AAC audio track has no decoder configuration.');\n      ac=ascParse(asc);\n      if(ac.aot<1||ac.aot>4||!ac.ch)throw new Error('This AAC variant cannot be read directly.');\n      if(!rate)rate=ac.sr;if(!ch)ch=ac.ch;\n    }else throw new Error('Unsupported audio codec in this file.');\n  }else if(PCMQT[fmt]){codec='pcm';pcm=PCMQT[fmt];if(!ch)ch=2;}\n  else throw new Error('The audio in this file ('+fmt.replace(\/[^\\x20-\\x7e]\/g,'?')+') is not supported.');\n  \/* pr\u00f8vetabeller *\/\n  var ssz=d.getUint32(stsz.s+4),scnt=d.getUint32(stsz.s+8),nrun=d.getUint32(stsc.s+4),nch=d.getUint32((stco||co64).s+4),runs=[];\n  for(i=0;i<nrun;i++)runs.push({f:d.getUint32(stsc.s+8+12*i),n:d.getUint32(stsc.s+12+12*i)});\n  function sizeAt(k){return ssz?ssz:d.getUint32(stsz.s+12+4*k);}\n  function chunkOff(k){return stco?d.getUint32(stco.s+8+4*k):d.getUint32(co64.s+8+8*k)*4294967296+d.getUint32(co64.s+12+8*k);}\n  var chunks=[],si=0,ri=0,total=0,nsamp=0;\n  for(i=0;i<nch;i++){\n    while(ri+1<runs.length&&runs[ri+1].f<=i+1)ri++;\n    var n=runs[ri].n,bytes=0;\n    if(ssz)bytes=n*ssz;else for(j=0;j<n&&si+j<scnt;j++)bytes+=sizeAt(si+j);\n    chunks.push({off:chunkOff(i),bytes:bytes,si:si,n:n});\n    total+=bytes;si+=n;\n  }\n  nsamp=si;\n  var out,pos=0,hdr=0;\n  if(codec==='aac')out=new Uint8Array(total+7*nsamp);\n  else if(codec==='mp3')out=new Uint8Array(total);\n  else{hdr=44;out=new Uint8Array(44+total);}\n  \/* l\u00e6s lydens bidder (sammenh\u00e6ngende bidder l\u00e6ses samlet) *\/\n  var g=0;\n  while(g<chunks.length){\n    var gs=g,gOff=chunks[g].off,gLen=chunks[g].bytes;\n    while(g+1<chunks.length&&chunks[g+1].off===gOff+gLen&&gLen+chunks[g+1].bytes<=4194304){g++;gLen+=chunks[g].bytes;}\n    g++;\n    var ab=new Uint8Array(await rdAt(file,gOff,gLen)),c,k,rp;\n    for(c=gs;c<g;c++){\n      var ck=chunks[c];rp=ck.off-gOff;\n      if(codec==='aac'){\n        for(k=0;k<ck.n;k++){\n          var fs=sizeAt(ck.si+k);\n          out.set(adtsHead(ac.aot,ac.sfi,ac.ch,fs),pos);pos+=7;\n          out.set(ab.subarray(rp,rp+fs),pos);pos+=fs;rp+=fs;\n        }\n      }else if(codec==='mp3'){\n        out.set(ab.subarray(rp,rp+ck.bytes),pos);pos+=ck.bytes;\n      }else{\n        out.set(ab.subarray(rp,rp+ck.bytes),hdr+pos);pos+=ck.bytes;\n      }\n    }\n  }\n  if(codec==='pcm'){\n    var sw=pcm.b,u8=out.subarray(44,44+pos),q,t,m2;\n    if(pcm.be&&sw>1){for(q=0;q+sw<=u8.length;q+=sw){for(t=0;t<(sw>>1);t++){m2=u8[q+t];u8[q+t]=u8[q+sw-1-t];u8[q+sw-1-t]=m2;}}}\n    out.set(wavHead(ch,rate||44100,pcm.b*8,!!pcm.fl,pos),0);\n  }\n  \/* redigeringsliste: spring pre-roll over og afkort til den angivne l\u00e6ngde *\/\n  var skip=0,limit=0,el2=mpFind(d,tk,['edts','elst']);\n  if(el2){\n    var ev=d.getUint8(el2.s),ec=d.getUint32(el2.s+4),p2=el2.s+8,k2,segd,mt;\n    for(k2=0;k2<ec;k2++){\n      if(ev===1){segd=d.getUint32(p2)*4294967296+d.getUint32(p2+4);mt=d.getInt32(p2+8)*4294967296+d.getUint32(p2+12);p2+=20;}\n      else{segd=d.getUint32(p2);mt=d.getInt32(p2+4);p2+=12;}\n      if(mt>=0){skip=Math.round(mt\/mdTs*(rate||44100));limit=Math.round(segd\/mvTs*(rate||44100));break;}\n    }\n  }\n  return {codec:codec,bytes:out.buffer.slice(out.byteOffset,out.byteOffset+(codec==='pcm'?44+pos:out.length)),sr:rate,ch:ch,aot:ac?ac.aot:0,skip:skip,limit:limit};\n}\nasync function demuxAvi(file){\n  var size=file.size,auds=null,chunks=[],total=0,pos=0,cache={b:null,s:0},BLK=8*1048576;\n  async function get(o,n){\n    if(!cache.b||o<cache.s||o+n>cache.s+cache.b.length){\n      var len=Math.min(Math.max(n,BLK),size-o);\n      if(len<=0)return new Uint8Array(0);\n      cache.b=new Uint8Array(await rdAt(file,o,len));cache.s=o;\n    }\n    return cache.b.subarray(o-cache.s,o-cache.s+n);\n  }\n  function parseStrl(dv,s,e,idx){\n    var p=s,type='';\n    while(p+8<=e){\n      var id=fc4(dv,p),sz=dv.getUint32(p+4,true),b=p+8;\n      if(id==='strh')type=fc4(dv,b);\n      else if(id==='strf'&&type==='auds'&&!auds){\n        var cb=b+18<=e&&sz>=18?dv.getUint16(b+16,true):0;\n        auds={idx:idx,tag:dv.getUint16(b,true),ch:dv.getUint16(b+2,true),sr:dv.getUint32(b+4,true),bits:dv.getUint16(b+14,true),extra:new Uint8Array(dv.buffer.slice(dv.byteOffset+b+18,dv.byteOffset+b+18+Math.min(cb,Math.max(0,sz-18))))};\n      }\n      p=b+sz+(sz&1);\n    }\n  }\n  function parseHdrl(dv){\n    var p=0,e=dv.byteLength,si=0;\n    while(p+12<=e){\n      var id=fc4(dv,p),sz=dv.getUint32(p+4,true),b=p+8;\n      if(id==='LIST'&&fc4(dv,b)==='strl'){parseStrl(dv,b+4,Math.min(e,b+sz),si);si++;}\n      p=b+sz+(sz&1);\n    }\n  }\n  async function scanMovi(s,e){\n    var off=s,a1=('0'+auds.idx).slice(-2)+'wb',a2=('0'+auds.idx.toString(16)).slice(-2)+'wb';\n    while(off+8<=e){\n      var hd=await get(off,8);\n      if(hd.length<8)break;\n      var id=String.fromCharCode(hd[0],hd[1],hd[2],hd[3]),sz=(hd[4]|(hd[5]<<8)|(hd[6]<<16)|(hd[7]<<24))>>>0;\n      if(id==='LIST'){off+=12;continue;}\n      if(off+8+sz>size)break;\n      if(id===a1||id===a2){var data=await get(off+8,sz);chunks.push(data.slice());total+=data.length;}\n      off+=8+sz+(sz&1);\n    }\n  }\n  while(pos+12<=size){\n    var h=new DataView(await rdAt(file,pos,12));\n    if(fc4(h,0)!=='RIFF')break;\n    var rsz=h.getUint32(4,true),rend=Math.min(size,pos+8+rsz+(rsz&1));\n    if(rsz===0||rend<=pos+12)rend=size;\n    var p=pos+12;\n    while(p+12<=rend){\n      var ch=new DataView(await rdAt(file,p,12)),id=fc4(ch,0),sz=ch.getUint32(4,true);\n      if(id==='LIST'){\n        var lt=fc4(ch,8);\n        if(lt==='hdrl'&&sz>=4)parseHdrl(new DataView(await rdAt(file,p+12,sz-4)));\n        else if(lt==='movi'&&auds)await scanMovi(p+12,Math.min(rend,p+8+sz));\n      }\n      p+=8+sz+(sz&1);\n    }\n    pos=rend;\n  }\n  if(!auds)throw new Error('No audio track found in this AVI file.');\n  if(!chunks.length)throw new Error('The AVI file contains no audio data.');\n  var all=new Uint8Array(total),q=0,i;\n  for(i=0;i<chunks.length;i++){all.set(chunks[i],q);q+=chunks[i].length;}\n  var tag=auds.tag;\n  if(tag===1||tag===3){\n    var bits=auds.bits||16;\n    if(tag===1&&[8,16,24,32].indexOf(bits)<0)throw new Error('Unsupported PCM format in this AVI file.');\n    var hd2=wavHead(auds.ch||2,auds.sr||44100,bits,tag===3,total),o2=new Uint8Array(44+total);o2.set(hd2,0);o2.set(all,44);\n    return {codec:'pcm',bytes:o2.buffer,sr:auds.sr,ch:auds.ch,aot:0,skip:0,limit:0};\n  }\n  if(tag===0x55)return {codec:'mp3',bytes:all.buffer,sr:auds.sr,ch:auds.ch,aot:0,skip:0,limit:0};\n  if(tag===0x1600)return {codec:'aac',bytes:all.buffer,sr:auds.sr,ch:auds.ch,aot:2,skip:0,limit:0};\n  if(tag===0xFF){\n    var ac=ascParse(auds.extra&&auds.extra.length>=2?auds.extra:new Uint8Array([0x12,0x10]));\n    if(ac.aot<1||ac.aot>4)throw new Error('This AAC variant cannot be read directly.');\n    var fr=0,k;\n    for(i=0;i<chunks.length;i++)fr+=7;\n    var oa=new Uint8Array(total+fr),pp=0;\n    for(i=0;i<chunks.length;i++){oa.set(adtsHead(ac.aot,ac.sfi,ac.ch,chunks[i].length),pp);pp+=7;oa.set(chunks[i],pp);pp+=chunks[i].length;}\n    return {codec:'aac',bytes:oa.buffer,sr:ac.sr,ch:ac.ch,aot:ac.aot,skip:0,limit:0};\n  }\n  if(tag===0x2000||tag===0x2001)throw new Error('AC-3\/DTS audio in AVI files is not supported.');\n  throw new Error('Unsupported audio format in this AVI file (0x'+tag.toString(16)+').');\n}\n\/* AAC via WebCodecs, n\u00e5r browserens lydafkoder ikke kan \u00e5bne r\u00e5 AAC-str\u00f8mme *\/\nasync function aacWebCodecs(dm,ctx){\n  if(typeof AudioDecoder==='undefined'||typeof EncodedAudioChunk==='undefined')throw new Error('This browser cannot decode the AAC audio in this file.');\n  var ad=adtsFrames(new Uint8Array(dm.bytes));\n  if(!ad.frames.length)throw new Error('No AAC audio found in this file.');\n  var cfg={codec:'mp4a.40.'+(ad.aot||2),sampleRate:ad.sr||dm.sr,numberOfChannels:ad.ch||dm.ch,description:ad.asc},sup=null;\n  try{sup=await AudioDecoder.isConfigSupported(cfg);}catch(e){}\n  if(!sup||!sup.supported)throw new Error('This browser cannot decode the AAC audio in this file.');\n  var parts=[],total=0,err=null,i;\n  var dec=new AudioDecoder({\n    output:function(a){\n      var n=a.numberOfFrames,c=a.numberOfChannels,arr=[],k,f;\n      for(k=0;k<c;k++){f=new Float32Array(n);a.copyTo(f,{planeIndex:k,format:'f32-planar'});arr.push(f);}\n      parts.push(arr);total+=n;a.close();\n    },\n    error:function(e){err=e;}\n  });\n  dec.configure(cfg);\n  var ts=0;\n  for(i=0;i<ad.frames.length;i++){\n    dec.decode(new EncodedAudioChunk({type:'key',timestamp:Math.round(ts),data:ad.frames[i]}));\n    ts+=1024\/cfg.sampleRate*1e6;\n    if(dec.decodeQueueSize>64)await tick();\n    if(err)throw err;\n  }\n  await dec.flush();dec.close();\n  if(err)throw err;\n  if(!total)throw new Error('The AAC audio could not be decoded.');\n  var nc=parts[0].length,b=ctx.createBuffer(nc,total,cfg.sampleRate),c2,at=0,j;\n  for(c2=0;c2<nc;c2++){at=0;var dst=b.getChannelData(c2);for(j=0;j<parts.length;j++){dst.set(parts[j][c2],at);at+=parts[j][0].length;}}\n  return b;\n}\nfunction fmt(t,d){\n  if(!(t>0))t=0;\n  var ms=Math.round(t*1000),m=Math.floor(ms\/60000),s=Math.floor(ms%60000\/1000),r=ms%1000,o=m+':'+('0'+s).slice(-2);\n  if(d>0)o+='.'+('00'+r).slice(-3).slice(0,d);\n  return o;\n}\nfunction fmtP(t,d){\n  if(!(t>0))t=0;\n  var sc=Math.pow(10,d),n=Math.round(t*sc),sec=Math.floor(n\/sc),fr=n-sec*sc,m=Math.floor(sec\/60),s=sec%60,o=m+':'+('0'+s).slice(-2);\n  if(d>0)o+='.'+('000000000'+fr).slice(-d);\n  return o;\n}\nfunction parseT(v){\n  v=String(v).trim().replace(',','.');if(!v)return null;\n  var p=v.split(':'),t=0,i;if(p.length>3)return null;\n  for(i=0;i<p.length;i++){if(!\/^(\\d+(\\.\\d*)?|\\.\\d+)$\/.test(p[i]))return null;t=t*60+parseFloat(p[i]);}\n  return t;\n}\nfunction kcoef(fs){\n  var f0=1681.9744509555319,G=3.999843853973347,Q=0.7071752369554196,K=Math.tan(Math.PI*f0\/fs),Vh=Math.pow(10,G\/20),Vb=Math.pow(Vh,0.4996667741545416),a0=1+K\/Q+K*K;\n  var s1={b0:(Vh+Vb*K\/Q+K*K)\/a0,b1:2*(K*K-Vh)\/a0,b2:(Vh-Vb*K\/Q+K*K)\/a0,a1:2*(K*K-1)\/a0,a2:(1-K\/Q+K*K)\/a0};\n  f0=38.13547087613982;Q=0.5003270373253953;K=Math.tan(Math.PI*f0\/fs);a0=1+K\/Q+K*K;\n  var s2={a1:2*(K*K-1)\/a0,a2:(1-K\/Q+K*K)\/a0};\n  return [s1,s2];\n}\nfunction bindKeys(){\n  if(keysBound)return;keysBound=true;\n  document.addEventListener('pointerdown',function(e){\n    var t=e.target,r=t&&t.closest?t.closest('.audio-editor-widget'):null;\n    if(r){ACTIVE=(r._ae&&r._ae.ready())?r:null;return;}\n    \/* et klik uden for editoren p\u00e5 almindelig sidetekst fjerner ikke afspilnings-tasten; et klik p\u00e5 et link, en knap eller et felt g\u00f8r *\/\n    var ia=t&&t.closest?t.closest('a,button,input,select,textarea,label,summary,[contenteditable]'):null;\n    if(ia)ACTIVE=null;\n  },true);\n  function typing(t){\n    if(!t||!t.tagName)return false;\n    var n=t.tagName.toLowerCase();\n    if(n==='textarea'||n==='select')return true;\n    if(n==='input')return \/^(text|search|number|email|url|tel|password|date|time)$\/i.test(t.type||'text');\n    return !!t.isContentEditable;\n  }\n  function usable(){return !!(ACTIVE&&ACTIVE._ae&&document.documentElement.contains(ACTIVE)&&ACTIVE._ae.ready()&&!ACTIVE._ae.modal());}\n  \/* mellemrum starter og stopper altid lyden, ogs\u00e5 n\u00e5r fokus st\u00e5r i en rullemenu eller i et af tal-felterne (Start, End, crossfade) *\/\n  function spaceTarget(t){\n    if(!t||!t.tagName||!ACTIVE||!ACTIVE.contains(t))return false;\n    var n=t.tagName.toLowerCase();\n    return n==='select'||(n==='input'&&t.classList.contains('aew-tin'));\n  }\n  document.addEventListener('keydown',function(e){\n    if(!usable())return;\n    if((e.key===' '||e.code==='Space')&&!e.ctrlKey&&!e.metaKey&&!e.altKey&&!e.shiftKey&&spaceTarget(e.target)){\n      e.preventDefault();\n      var tg=e.target;try{tg.blur();}catch(_){}\n      if(!e.repeat)ACTIVE._ae.toggle();\n      return;\n    }\n    if(typing(e.target))return;\n    var a=ACTIVE._ae;\n    if(e.ctrlKey||e.metaKey){\n      if(e.altKey||e.shiftKey)return;\n      var k=(e.key||'').toLowerCase();\n      if(k==='z'){e.preventDefault();a.undo();}\n      else if(k==='c'){e.preventDefault();a.copy();}\n      else if(k==='x'){e.preventDefault();a.cut();}\n      else if(k==='v'){e.preventDefault();a.paste();}\n      else if(k==='a'){e.preventDefault();a.all();}\n      return;\n    }\n    if(e.altKey)return;\n    if(e.key==='m'||e.key==='M'){e.preventDefault();if(!e.repeat)a.mark();return;}\n    if(!e.shiftKey&&(e.key==='s'||e.key==='S')&&a.envShape()){e.preventDefault();return;}\n    if(!e.shiftKey&&(e.key==='c'||e.key==='C')){e.preventDefault();if(!e.repeat)a.toolCut();return;}\n    if(e.key==='Escape'){a.esc();return;}\n    if(!e.shiftKey&&(e.key==='v'||e.key==='V')){e.preventDefault();if(!e.repeat)a.toolSel();return;}\n    if(!e.shiftKey&&(e.key==='h'||e.key==='H')){e.preventDefault();if(!e.repeat)a.toolMv();return;}\n    if(e.key===','){e.preventDefault();a.prevMk();return;}\n    if(e.key==='.'){e.preventDefault();a.nextMk();return;}\n    if(e.key===' '||e.code==='Space'){e.preventDefault();if(!e.repeat)a.toggle();}\n  },true);\n  document.addEventListener('keyup',function(e){\n    if(!usable())return;\n    if((e.key===' '||e.code==='Space')&&spaceTarget(e.target)){e.preventDefault();return;}\n    if(typing(e.target))return;\n    if(e.key===' '||e.code==='Space')e.preventDefault();\n  },true);\n  function altEv(e){\n    if(e.key!=='Alt')return;\n    var r=ACTIVE;\n    if(!r||!r._ae)return;\n    r._ae.alt(e.type==='keydown');\n    if(e.type==='keyup')e.preventDefault();\n  }\n  document.addEventListener('keydown',altEv,true);\n  document.addEventListener('keyup',altEv,true);\n  function modEv(e){var r=ACTIVE;if(r&&r._ae&&r._ae.redoMod)r._ae.redoMod(!!(e.altKey||e.ctrlKey));}\n  document.addEventListener('keydown',modEv,true);\n  document.addEventListener('keyup',modEv,true);\n  document.addEventListener('pointerdown',modEv,true);\n  document.addEventListener('pointermove',modEv,true);\n  window.addEventListener('blur',function(){var r=ACTIVE;if(r&&r._ae){r._ae.alt(false);r._ae.redoMod(false);}});\n}\nfunction init(root){\n  if(root.getAttribute('data-ae'))return;root.setAttribute('data-ae','1');\n  var $=function(s){return root.querySelector(s)},$$=function(s){return root.querySelectorAll(s)};\n  var el={drop:$('.aew-drop'),file:$('.aew-file'),work:$('.aew-work'),cv:$('.aew-cv'),ov:$('.aew-ov'),wave:$('.aew-wave'),shl:$('.aew-shl'),shr:$('.aew-shr'),hs:$('.aew-hs'),he:$('.aew-he'),ph:$('.aew-ph'),scroll:$('.aew-scroll'),help:$('.aew-help'),\n    tcur:$('.aew-tcur'),imm:$('.aew-m-im'),imtxt:$('.aew-imtxt'),imlist:$('.aew-imlist'),imcancel:$('.aew-imcancel'),imrep:$('.aew-imrep'),imadd:$('.aew-imadd'),drng:$('.aew-drng'),rgw:$('.aew-rgw'),rgs:$('.aew-rgs'),rga:$('.aew-rga'),drsum:$('.aew-drsum'),tipb:$('.aew-tipb'),demo:$('.aew-demo'),pin:$('.aew-pin'),lcin:$('.aew-lcin'),ttlin:$('.aew-ttlin'),nmcu:$('.aew-nmcu'),nlu:$('.aew-nlu'),ntp:$('.aew-ntp'),ptp:$('.aew-ptp'),ptt:$('.aew-ptt'),ptd:$('.aew-ptd'),dmeta:$('.aew-dmeta'),dmsum:$('.aew-dmsum'),dmbtn:$('.aew-dmbtn'),mtm:$('.aew-m-meta'),mtfmt:$('.aew-mtfmt'),mtcov:$('.aew-mtcov'),mtimg:$('.aew-mtimg'),mtfile:$('.aew-mtfile'),mtpick:$('.aew-mtpick'),mtrm:$('.aew-mtrm'),mtok:$('.aew-mtok'),mtcancel:$('.aew-mtcancel'),mtclear:$('.aew-mtclear'),mtcn:$('.aew-mtcn'),mki:$('.aew-mki'),abm:$('.aew-m-ab'),abb:$('.aew-abb'),abok:$('.aew-abok'),abdon:$('.aew-donate'),clipl:$('.aew-clipl'),gin:$('.aew-gin'),gra:$('.aew-gra'),grb:$('.aew-grb'),grl:$('.aew-grl'),tt:$('.aew-tt'),play:$('.aew-play'),home:$('.aew-home'),lps:$('.aew-lps'),lpe:$('.aew-lpe'),loop:$('.aew-loop'),fs:$('.aew-fs'),fe:$('.aew-fe'),len:$('.aew-len'),reset:$('.aew-reset'),\n    zin:$('.aew-zin'),zout:$('.aew-zout'),zfit:$('.aew-zfit'),zsel:$('.aew-zsel'),toolEnv:$('.aew-toolenv'),\n    rev:$('.aew-rev'),envdel:$('.aew-envdel'),envclr:$('.aew-envclr'),\n    fmt:$('.aew-fmt'),kbps:$('.aew-kbps'),rk:$('.aew-rk'),pplay:$('.aew-pplay'),ps:$('.aew-ps'),pv:$('.aew-pv'),pfree:$('.aew-pfree'),pmv:$('.aew-pmv'),pml:$('.aew-pml'),nrm:$('.aew-nrm'),nm:$('.aew-m-nm'),rsm:$('.aew-m-rs'),ptm:$('.aew-m-pt'),rsb:$('.aew-rsb'),rsbit:$('.aew-rsbit'),rsdi:$('.aew-rsdi'),rspl:$('.aew-rspl'),rs2:$('.aew-rs2'),ptb:$('.aew-ptb'),rssel:$('.aew-rssel'),rs1:$('.aew-rs1'),rsok:$('.aew-rsok'),rsc:$('.aew-rsc'),ptok:$('.aew-ptok'),smb:$('.aew-smb'),smm:$('.aew-m-sm'),smok:$('.aew-smok'),smcancel:$('.aew-smcancel'),ptc:$('.aew-ptc'),pl:$('.aew-pl'),nmsel:$('.aew-nmsel'),nm1:$('.aew-nm1'),nm2:$('.aew-nm2'),nm3:$('.aew-nm3'),nmok:$('.aew-nmok'),nmc:$('.aew-nmc'),exp:$('.aew-exp'),derr:$('.aew-derr'),\n    dlg:$('.aew-dlg'),dlgName:$('.aew-fname'),dlgExt:$('.aew-ext'),dlgOk:$('.aew-dok'),dlgCancel:$('.aew-dcancel'),dlgT:$('.aew-dt'),dlgNf:$('.aew-dnf'),dlgNote:$('.aew-dnote'),seln:$('.aew-seln'),undo:$('.aew-undo'),ulab:$('.aew-ulab'),crop:$('.aew-crop'),ttb:$('.aew-ttb'),ttm:$('.aew-m-tt'),ttpl:$('.aew-ttpl'),ttfs:$('.aew-ttf'),tthz:$('.aew-tthz'),ttd:$('.aew-ttd'),ttl:$('.aew-ttl'),ttlv:$('.aew-ttlv'),tt1:$('.aew-tt1'),tt2:$('.aew-tt2'),ttok:$('.aew-ttok'),ttc:$('.aew-ttc'),ttfw:$('.aew-m-tt .aew-ttfw'),ttfl:$('.aew-m-tt .aew-ttfl'),bits:$('.aew-bits'),srt:$('.aew-srt'),chm:$('.aew-chm'),mcv:$('.aew-mcv'),mwrap:$('.aew-mwrap'),m1:$('.aew-m1'),m2:$('.aew-m2'),m3:$('.aew-m3'),ovl:$('.aew-ovl'),cpy:$('.aew-cpy'),cut:$('.aew-cut'),pst:$('.aew-pst'),del:$('.aew-del'),all:$('.aew-all'),fol:$('.aew-fol'),sil:$('.aew-sil'),ucnt:$('.aew-ucnt'),vzo:$('.aew-vzo'),vzi:$('.aew-vzi'),vz1:$('.aew-vz1'),lrs:$('.aew-lrs'),mkp:$('.aew-mkp'),mkn:$('.aew-mkn'),xfms:$('.aew-xfms'),pi:$('.aew-pi'),po:$('.aew-po'),tcut:$('.aew-tcut'),link:$('.aew-link'),selr:$('.aew-selr'),rtn:$('.aew-rtn'),lastb:$('.aew-last'),tsel:$('.aew-tsel'),tscr:$('.aew-tscr'),tmv:$('.aew-tmv'),lcm:$('.aew-lcm'),lcmod:$('.aew-m-lc'),lcc:$('.aew-lcc'),lpl:$('.aew-lpl'),lcsl:$('.aew-lcsl'),lcon:$('.aew-lcon'),lcs:$('.aew-lcs'),lcv:$('.aew-lcv'),lcord:$('.aew-lcord'),live:$('.aew-live'),snap:$('.aew-snap'),inv:$('.aew-inv')};\n  \/* Donations: put the donation link here, e.g. var DONATE_URL='https:\/\/...'. While it is empty, 'Feel free to donate' is shown as plain text. *\/\n  var DONATE_URL='';\n  \/* Demo audio: the file the 'Use Demo Audio' button loads. The server must allow cross-origin reads (Access-Control-Allow-Origin) for the page the widget sits on. *\/\n  var DEMO_URL='https:\/\/audio.anderskisling.dk\/wp-content\/uploads\/2026\/10\/mozart-symphony-no.40-g-minor.mp3';\n  var BIN=256,MIN=0.02,RUL=22,HYO=14,DBMIN=-48,DBMAX=12,FXWIN=20,FXRATE=100;\n  var SSTEPS=[1,2,5,10,20,50,100,200,500,1000,2000,5000,10000,20000,50000,100000,200000,500000,1e6,2e6,5e6,1e7,2e7,5e7,1e8],STEPS=[0.00001,0.00002,0.00005,0.0001,0.0002,0.0005,0.001,0.002,0.005,0.01,0.02,0.05,0.1,0.2,0.5,1,2,5,10,15,30,60,120,300,600,900,1800,3600];\n  var buf=null,dur=0,sr=44100,chN=2,ctx=null,gainNode=null,fxNode=null,bins=null,kw=null,fileName='audio',loadId=0,busy=false;\n  var trimS=0,trimE=0,view={s:0,sp:1},pos=0,playing=false,src=null,t0=0,p0=0,raf=0,drag=null,wasPlaying=false,mt=0;\n  var meas={peak:0,lufs:null},gainInfo={g:1,limited:false};\n  var CH=[{fi:0,fo:0,env:[]},{fi:0,fo:0,env:[]}],splitCh=false,selCh=0,dragCh=0,altPrev=false,hitFadeCh=0,selPt=null,dragPt=null,tool='sel',selA=0,selX=0,selMoved=false,markers=[],selMk=null,dragMk=null,mkMoved=false,mkX0=0,selDrawn=false,selShift=false,segSel=null,pasteMode='insert',cuts=[],cutHover=-1,sgHover=null,sgDrag=null;\n  var splIn=null,fxL=null,fxR=null,fxJoin=null,fxSplitPlay=false;\n  var fxEnd=0,dW=false,dO=false,drawRaf=0,dlgRes=null,dlgFm=null,hist=[],pend=null,kwId=0;\n  var anL=null,anR=null,bufs=[null,null],mMax=0,mOver=false,mraf=0,mLast=0,mHover=-1,mLastTxt='',mLastUpd=0;\n  var mv=[{pk:-120,hold:-120,ht:0,rl:0,rd:-120},{pk:-120,hold:-120,ht:0,rl:0,rd:-120}];\n  var ctDrag=null,ctDel=false,hovCut=-1,touchDown=null,tapPend=null,TOUCH_SLOP=10,nLoop=false,loopA=0,loopB=0,cutLive=false,grip=null,gripAct=null,gripHov=null,mkDelPend=false,mkHMoved=false,mkY0=0,linkOn=true,selR=null,rtnMode='off',lastStart=0,loopOn=false,followOn=true,CLIPT=1.0002,hl=null,hlx=null,selActive=false,playEndT=0,playFrom=0,selOnly=false,vz=1,nOut=null,lcOn=false,lcOrd=6,lcHz=80,lcSlot=null,lcTimer=0,lcDry=null,lcWet=null,lcOut=null,pX0=0,pLastX=0,pMoved=false,envLive=true,editRev=0,curRate=1,playRate=1,playMode='norm',pBuf=null,pBusy=false,pTimer=0,pitchSemi=0,pitchFree=false,pitchMode='vari',snapOn=false,snapPts=[0],snapId=0,rulHot=0,envSeq=0,ovlW=0,mvOff=0,mvX0=0,mvT0=0,mvMoved=false;\n  var derrT=0;\n  function say(t,err){\n    if(!err)return;\n    el.derr.textContent=t;el.derr.hidden=false;\n    clearTimeout(derrT);derrT=setTimeout(function(){el.derr.hidden=true;},9000);\n  }\n  function dbTxt(v){return v>1e-9?(20*Math.log10(v)).toFixed(1):'\u2212\u221e';}\n  function W(){return el.wave.clientWidth||1;}\n  function H(){return el.wave.clientHeight||1;}\n  function X(t){return (t-view.s)\/view.sp*W();}\n  function T(x){return view.s+x\/W()*view.sp;}\n  function clamp(v,a,b){return v<a?a:(v>b?b:v);}\n  \/* ---------- Lyd-graf: kilde \u2192 normalisering \u2192 fx (fades\/envelope) \u2192 ud ---------- *\/\n  function ensureCtx(){\n    if(ctx)return;\n    var AC=window.AudioContext||window.webkitAudioContext;\n    if(!AC)throw new Error('Your browser does not support the Web Audio API.');\n    ctx=new AC();gainNode=ctx.createGain();fxNode=ctx.createGain();\n    nOut=ctx.createGain();\n    lcDry=ctx.createGain();lcWet=ctx.createGain();lcOut=ctx.createGain();\n    lcDry.gain.value=lcOn?0:1;lcWet.gain.value=lcOn?1:0;\n    gainNode.connect(fxNode);\n    fxNode.connect(nOut);\n    try{\n      splIn=ctx.createGain();\n      var sp2=ctx.createChannelSplitter(2),mg=ctx.createChannelMerger(2);\n      fxL=ctx.createGain();fxR=ctx.createGain();fxJoin=ctx.createGain();\n      splIn.connect(sp2);sp2.connect(fxL,0);sp2.connect(fxR,1);\n      fxL.connect(mg,0,0);fxR.connect(mg,0,1);mg.connect(fxJoin);\n      fxJoin.connect(nOut);\n    }catch(err){splIn=null;fxL=null;fxR=null;fxJoin=null;}\n    nOut.connect(lcDry);lcDry.connect(lcOut);lcWet.connect(lcOut);lcOut.connect(ctx.destination);\n    try{lcSwap(lcOrd,lcHz);}catch(err){}\n    try{\n      var spl=ctx.createChannelSplitter(2),sink=ctx.createGain();\n      anL=ctx.createAnalyser();anR=ctx.createAnalyser();\n      anL.fftSize=2048;anR.fftSize=2048;anL.smoothingTimeConstant=0;anR.smoothingTimeConstant=0;\n      bufs=[new Float32Array(anL.fftSize),new Float32Array(anR.fftSize)];\n      lcOut.connect(spl);spl.connect(anL,0);spl.connect(anR,1);\n      sink.gain.value=0;anL.connect(sink);anR.connect(sink);sink.connect(ctx.destination);\n    }catch(err){anL=null;anR=null;}\n  }\n  function decode(ab){return new Promise(function(res,rej){var pr=ctx.decodeAudioData(ab,res,rej);if(pr&&pr.then)pr.then(res,rej);});}\n  function readFile(f){return f.arrayBuffer?f.arrayBuffer():new Promise(function(res,rej){var r=new FileReader();r.onload=function(){res(r.result)};r.onerror=rej;r.readAsArrayBuffer(f);});}\n  \/* ---------- Gain-funktion: envelope (line\u00e6r i dB) \u00d7 line\u00e6re fades. S\/L = start og l\u00e6ngde i sekunder ---------- *\/\n  function mkGain(S,L,c,noFade){\n    var D=ED(c||0),pts=D.env.slice(),n=pts.length,k=0,fi=noFade?0:D.fi,fo=noFade?0:D.fo;\n    return function(t){\n      var g=1;\n      if(n){\n        var db;\n        if(t<=pts[0].t)db=pts[0].db;\n        else if(t>=pts[n-1].t)db=pts[n-1].db;\n        else{\n          while(k>0&&pts[k].t>t)k--;\n          while(k<n-2&&pts[k+1].t<=t)k++;\n          var a=pts[k],b=pts[k+1],d=b.t-a.t;\n          db=d>1e-9?a.db+(b.db-a.db)*easeF(a,(t-a.t)\/d):b.db;\n        }\n        g=db<=DBMIN+1e-6?0:Math.exp(db*0.11512925464970229);\n      }\n      var u=t-S;\n      if(fi>0&&u<fi)g*=u<0?0:u\/fi;\n      var r=L-u;\n      if(fo>0&&r<fo)g*=r<0?0:r\/fo;\n      return g;\n    };\n  }\n  function fxActive(){return CH[0].env.length>0||CH[0].fi>0||CH[0].fo>0;}\n  \/* ---------- Analyse ---------- *\/\n  function buildBins(){\n    editRev++;\n    var len=buf.length,nb=Math.ceil(len\/BIN),mn=new Float32Array(nb),mx=new Float32Array(nb),cmn=[],cmx=[],c,b,i;\n    mn.fill(1);mx.fill(-1);\n    for(c=0;c<chN;c++){\n      var d=buf.getChannelData(c),a=new Float32Array(nb),z=new Float32Array(nb);\n      for(b=0;b<nb;b++){\n        var s=b*BIN,e=Math.min(len,s+BIN),lo=1,hi=-1;\n        for(i=s;i<e;i++){var v=d[i];if(v<lo)lo=v;if(v>hi)hi=v;}\n        a[b]=lo;z[b]=hi;\n        if(lo<mn[b])mn[b]=lo;\n        if(hi>mx[b])mx[b]=hi;\n      }\n      cmn.push(a);cmx.push(z);\n    }\n    bins={mn:mn,mx:mx,cmn:cmn,cmx:cmx,nb:nb};\n  }\n  async function kweight(b){\n    var fs=b.sampleRate,seg=Math.round(fs*0.1),n=Math.floor(b.length\/seg),nc=chN,co=kcoef(fs),A=co[0],B=co[1],ss=new Float64Array(n*nc);\n    var b0=A.b0,b1=A.b1,b2=A.b2,a1=A.a1,a2=A.a2,c1=B.a1,c2=B.a2;\n    for(var c=0;c<nc;c++){\n      var d=b.getChannelData(c),z1=0,z2=0,w1=0,w2=0;\n      for(var s=0;s<n;s++){\n        var acc=0,end=(s+1)*seg;\n        for(var i=s*seg;i<end;i++){\n          var x=d[i],y=b0*x+z1;z1=b1*x-a1*y+z2;z2=b2*x-a2*y;\n          var v=y+w1;w1=-2*y-c1*v+w2;w2=y-c2*v;\n          acc+=v*v;\n        }\n        ss[c*n+s]=acc;\n        if(s%200===199)await tick();\n      }\n    }\n    return {ss:ss,n:n,nc:nc,seg:seg,sr:fs};\n  }\n  function lufsIn(a,b){\n    if(!kw)return null;\n    var n=kw.n,nc=kw.nc,ss=kw.ss,seg=kw.seg,s0=Math.ceil(a*kw.sr\/seg),s1=Math.min(n,Math.floor(b*kw.sr\/seg)),cnt=s1-s0-3;\n    if(cnt<1)return null;\n    var z=new Float64Array(cnt),i,c,sum=0,m=0;\n    for(i=0;i<cnt;i++){var t=0;for(c=0;c<nc;c++){var o=c*n+s0+i;t+=ss[o]+ss[o+1]+ss[o+2]+ss[o+3];}z[i]=t\/(4*seg);}\n    for(i=0;i<cnt;i++)if(z[i]>0&&-0.691+10*Math.log10(z[i])>-70){sum+=z[i];m++;}\n    if(!m)return null;\n    var gr=-0.691+10*Math.log10(sum\/m)-10;sum=0;m=0;\n    for(i=0;i<cnt;i++)if(z[i]>0&&-0.691+10*Math.log10(z[i])>gr){sum+=z[i];m++;}\n    return m?-0.691+10*Math.log10(sum\/m):null;\n  }\n  function peakIn(a,b){\n    var i0=Math.max(0,Math.floor(a*sr)),i1=Math.min(buf.length,Math.ceil(b*sr)),m=0,c,i,j,v;\n    if(i1<=i0)return 0;\n    function scan(x0,x1){for(c=0;c<chN;c++){var d=buf.getChannelData(c);for(i=x0;i<x1;i++){v=d[i];if(v<0)v=-v;if(v>m)m=v;}}}\n    var b0=Math.ceil(i0\/BIN),b1=Math.floor(i1\/BIN);\n    if(b1<=b0){scan(i0,i1);return m;}\n    scan(i0,b0*BIN);scan(b1*BIN,i1);\n    for(j=b0;j<b1;j++){v=-bins.mn[j];if(v>m)m=v;v=bins.mx[j];if(v>m)m=v;}\n    return m;\n  }\n  function scheduleMeasure(){}\n  function measure(){}\n  function setStats(){}\n  function applyGain(redraw){\n    gainInfo={g:1,limited:false};\n    if(gainNode)gainNode.gain.setTargetAtTime(1,ctx.currentTime,0.015);\n    if(redraw)invalidate(true,false);\n  }\n  function sync(){var f=el.fmt.value,lossy=(f==='mp3');el.rk.hidden=!lossy;el.bits.disabled=lossy;}\n  \/* ---------- Envelope \/ fades: hj\u00e6lpefunktioner ---------- *\/\n  function ED(c){return splitCh?CH[c]:CH[0];}\n  function cpCh(d){return {fi:d.fi,fo:d.fo,env:d.env.map(function(p){return {t:p.t,db:p.db,n:p.n,k:p.k,sc:p.sc};})};}\n  function envEach(fn){CH[0].env=fn(CH[0].env);CH[1].env=fn(CH[1].env);}\n  function twoLanes(){return (splitCh||altPrev)&&chN>1;}\n  function zones(){\n    var H0=H();\n    if(twoLanes()){\n      var lh=(H0-RUL)\/2;\n      return [{c:0,top:RUL,bot:RUL+lh,y0:RUL+16,y1:RUL+lh-6,hy:RUL+14},{c:1,top:RUL+lh,bot:H0,y0:RUL+lh+16,y1:H0-6,hy:RUL+lh+14}];\n    }\n    return [{c:0,top:RUL,bot:H0,y0:RUL+26,y1:H0-8,hy:RUL+HYO}];\n  }\n  function laneAt(y){return (twoLanes()&&y>=RUL+(H()-RUL)\/2)?1:0;}\n  function zoneOf(c){var z=zones();return z[z.length>1?c:0];}\n  function dbScale(z){var span=z.y1-z.y0;return {ppd:span\/(DBMAX-DBMIN)*vz,zero:z.y0+DBMAX*span\/(DBMAX-DBMIN)};}\n  function dbToY(db,z){z=z||zones()[0];var s=dbScale(z);return s.zero-db*s.ppd;}\n  function yToDb(y,z){z=z||zones()[0];var s=dbScale(z);return (s.zero-y)\/s.ppd;}\n  function snapDb(db){db=clamp(db,DBMIN,DBMAX);if(Math.abs(db)<0.8)db=0;else if(db<DBMIN+1)db=DBMIN;return Math.round(db*10)\/10;}\n  function sortEnv(c){ED(c).env.sort(function(a,b){return a.t-b.t;});}\n  function addPt(t,db,c){var p={t:clamp(t,0,dur),db:snapDb(db),n:++envSeq};ED(c).env.push(p);sortEnv(c);return p;}\n  function hitPt(x,y){\n    var zs=zones(),best=null,bd=1e9,zi,i;\n    for(zi=0;zi<zs.length;zi++){\n      var z=zs[zi],pts=ED(z.c).env;\n      for(i=0;i<pts.length;i++){var py0=dbToY(pts[i].db,z);if(py0<z.top||py0>z.bot)continue;var d=Math.hypot(X(pts[i].t)-x,py0-y);if(d<bd){bd=d;best={c:z.c,p:pts[i]};}}\n    }\n    return bd<=10?best:null;\n  }\n  function envCount(){return CH[0].env.length+(splitCh&&chN>1?CH[1].env.length:0);}\n  function envUI(){\n    el.envclr.disabled=!envCount()||tool!=='env';\n    el.envdel.disabled=!selPt||tool!=='env';\n  }\n  function envChanged(){envUI();scheduleFx();invalidate(envLive,true);}\n  function delSel(){\n    if(!selPt)return;\n    var gone=selPt,c=selCh;\n    edit(function(){\n      var arr=ED(c).env,i=arr.indexOf(gone);if(i>=0)arr.splice(i,1);\n      var prev=null,k;\n      for(k=0;k<arr.length;k++)if(arr[k].n<gone.n&&(!prev||arr[k].n>prev.n))prev=arr[k];\n      selPt=prev;\n    });\n    envChanged();\n  }\n  function clampFades(){\n    var L=trimE-trimS,c;\n    for(c=0;c<2;c++){var D=CH[c],s=D.fi+D.fo;if(s>L&&s>0){var k=L\/s;D.fi*=k;D.fo*=k;}}\n  }\n  \/* ---------- Greb p\u00e5 markeringens kanter: pr\u00e6cis trim af start og slut ---------- *\/\n  function selEdges(){\n    if(!buf)return null;\n    if(!linkOn&&selR)return {a:selR.a,b:selR.b};\n    if(linkOn&&(selActive||trimS>0.0005||trimE<dur-0.0005))return {a:trimS,b:trimE};\n    return null;\n  }\n  function gripY(){return RUL+(H()-RUL)\/2;}\n  function hitCutHandle(x,y){\n    if(y<RUL-1||y>RUL+17||!cuts.length)return -1;\n    var i,best=-1,bd=1e9,d;\n    for(i=0;i<cuts.length;i++){d=Math.abs(x-X(cuts[i]));if(d<=9&&d<bd){bd=d;best=i;}}\n    return best;\n  }\n  function hitGrip(x,y){\n    if(tool!=='sel')return null;\n    var s=selEdges();if(!s)return null;\n    if(Math.abs(y-gripY())>18)return null;\n    var da=Math.abs(x-X(s.a)),db=Math.abs(x-X(s.b));\n    if(da<=8&&(da<db||(da===db&&x<X(s.a))))return 'a';\n    if(db<=8)return 'b';\n    return null;\n  }\n  function edgeT(e){var s=selEdges();return e==='a'?s.a:s.b;}\n  function setEdge(e,t){\n    t=rs(t);\n    if(!linkOn&&selR){\n      if(e==='a')selR.a=clamp(t,0,selR.b-MIN);else selR.b=clamp(t,selR.a+MIN,dur);\n      layout();invalidate(true,true);\n    }else{\n      if(e==='a')trimS=clamp(t,0,trimE-MIN);else trimE=clamp(t,trimS+MIN,dur);\n      onTrim(false);\n    }\n  }\n  function openGripInput(e){\n    var s=selEdges();if(!s)return;\n    var t=e==='a'?s.a:s.b,w=W(),gx=clamp(X(t)-47,2,w-96);\n    el.gin.hidden=false;el.gin.style.left=gx+'px';el.gin.style.top=Math.max(RUL+4,gripY()-52)+'px';\n    el.gin.value=fU(t);el.gin.setAttribute('data-e',e);\n    setTimeout(function(){try{el.gin.focus();el.gin.select();}catch(_){}},0);\n  }\n  function closeGripInput(){el.gin.hidden=true;}\n  \/* ---------- Bl\u00f8de kurver i envelope ---------- *\/\n  var selSeg=null,hovSeg=null,crv=null,shBar=null,shiftNow=false;\n  function easeF(p,x){\n    if(p.sc===1)return x*x*(3-2*x);\n    if(p.sc===2)return x*x*x*(x*(6*x-15)+10);\n    var k=p.k;\n    if(!k||k===1)return x;\n    return Math.pow(x,k);\n  }\n  function segIdx(c,n){var pts=ED(c).env,i;for(i=0;i<pts.length-1;i++)if(pts[i].n===n)return i;return -1;}\n  function segMid(c,i,z){\n    var pts=ED(c).env,a=pts[i],b=pts[i+1],tm=(a.t+b.t)\/2,dm=a.db+(b.db-a.db)*easeF(a,0.5);\n    return {x:X(tm),y:dbToY(dm,z),db:dm};\n  }\n  function hitMid(x,y){\n    var zs=zones(),zi,i;\n    for(zi=0;zi<zs.length;zi++){\n      var z=zs[zi],pts=ED(z.c).env;\n      for(i=0;i<pts.length-1;i++){\n        if(X(pts[i+1].t)-X(pts[i].t)<18)continue;\n        var m=segMid(z.c,i,z);\n        if(m.y<z.top||m.y>z.bot)continue;\n        if(Math.hypot(m.x-x,m.y-y)<=9)return {c:z.c,i:i,n:pts[i].n,z:z};\n      }\n    }\n    return null;\n  }\n  function normShape(a){\n    if(!a.sc)delete a.sc;\n    if(!a.sc&&a.k!==undefined&&Math.abs(a.k-1)<0.02)delete a.k;\n    if(a.sc)delete a.k;\n  }\n  \/* 0 = lige, 1 = langsom start, 2 = langsom slutning, 3 = S-kurve (bl\u00f8d, kraftig, lige) *\/\n  function applyShape(idx){\n    if(!selSeg)return;\n    var c=selSeg.c,n=selSeg.n;\n    edit(function(){\n      var i=segIdx(c,n);if(i<0)return;\n      var a=ED(c).env[i],prev=a.sc||0;\n      delete a.k;delete a.sc;\n      if(idx===1)a.k=2;else if(idx===2)a.k=0.5;else if(idx===3){if(prev===0)a.sc=1;else if(prev===1)a.sc=2;}\n      normShape(a);\n    });\n    envChanged();\n  }\n  function hitShapeBar(x,y){\n    if(!shBar||tool!=='env')return -1;\n    if(x<shBar.x||x>shBar.x+shBar.w||y<shBar.y||y>shBar.y+shBar.h)return -1;\n    var i=Math.floor((x-shBar.x-4)\/26);\n    return (i>=0&&i<4)?i:-1;\n  }\n  function fadeUI(){}\n  function splitUI(){\n    var on=splitCh&&chN>1;\n    el.lrs.disabled=chN<2;\n    el.lrs.classList.toggle('aew-on',on);el.lrs.setAttribute('aria-pressed',on?'true':'false');\n  }\n  function setSplitRaw(on){\n    if(chN<2)on=false;\n    CH[1]=cpCh(CH[0]);splitCh=on;selPt=null;selCh=0;\n    splitUI();envUI();fadeUI();\n  }\n  function helpTxt(){}\n  function setTool(t){\n    tool=t;if(el.ptp)el.ptp.hidden=true;if(t!=='env'){selSeg=null;hovSeg=null;}root.classList.toggle('aew-env',t==='env');\n    el.toolEnv.classList.toggle('aew-on',t==='env');el.toolEnv.setAttribute('aria-pressed',t==='env'?'true':'false');\n    if(t!=='cut')cutLive=false;\n    el.tcut.classList.toggle('aew-on',t==='cut');el.tcut.classList.toggle('aew-live',!!(cutLive&&playing&&t==='cut'));el.tcut.setAttribute('aria-pressed',t==='cut'?'true':'false');\n    el.tmv.classList.toggle('aew-on',t==='mv');el.tmv.setAttribute('aria-pressed',t==='mv'?'true':'false');\n    el.tscr.classList.toggle('aew-on',t==='scrub');el.tscr.setAttribute('aria-pressed',t==='scrub'?'true':'false');\n    el.tsel.classList.toggle('aew-on',t==='sel');el.tsel.setAttribute('aria-pressed',t==='sel'?'true':'false');\n    el.tcut.disabled=el.tsel.disabled=el.tscr.disabled=el.tmv.disabled=el.clipl.disabled=(t==='env');\n    if(t!=='cut')cutHover=-1;\n    if(t!=='mv'){sgHover=null;if(segSel){segSel=null;invalidate(true,true);}}\n    envUI();helpTxt();invalidate(false,true);\n  }\n  function pickTool(t){if(!buf||tool==='env'||drag)return;setTool(tool===t?'sel':t);}\n  \/* ---------- Tegning ---------- *\/\n  function invalidate(w,o){\n    if(selActive!==selDrawn)w=true;\n    if(w)dW=true;if(o)dO=true;\n    if(drawRaf)return;\n    drawRaf=requestAnimationFrame(function(){\n      drawRaf=0;\n      if(dW){dW=false;drawWave();}\n      if(dO){dO=false;drawOv();}\n      layout();monoUI();mkInfoUI();\n    });\n  }\n  function drawWave(){\n    var cv=el.cv,w=W(),h=H();\n    if(!w||!h)return;\n    selDrawn=selActive;root.classList.toggle('aew-selon',!!selActive);\n    var dpr=Math.min(window.devicePixelRatio||1,2),cw=Math.round(w*dpr),ch=Math.round(h*dpr);\n    if(cv.width!==cw||cv.height!==ch){cv.width=cw;cv.height=ch;}\n    var g=cv.getContext('2d');g.setTransform(1,0,0,1,0,0);g.clearRect(0,0,cw,ch);\n    if(!buf)return;\n    try{\n      var wantN=segSel?srcLabel(segSel.a,segSel.b):baseName;\n      if(wantN!==shownName){shownName=wantN;(dnEl||$('.aew-dn')).textContent=wantN;}\n    }catch(_){}\n    var rul=Math.round(RUL*dpr),mid=rul+(ch-rul)\/2,amp=(ch-rul)\/2*0.92,pps=w\/view.sp,st=STEPS[STEPS.length-1],q;\n    for(q=0;q<STEPS.length;q++){if(STEPS[q]*pps>=90){st=STEPS[q];break;}}\n    g.fillStyle='rgba(255,255,255,.07)';g.fillRect(0,rul-1,cw,1);\n    g.font=(10.5*dpr)+'px -apple-system,Segoe UI,Roboto,sans-serif';g.textBaseline='top';\n    var smpU=(unit==='s'),stS=1;\n    if(smpU){var pxs0=pps\/sr;stS=SSTEPS[SSTEPS.length-1];for(q=0;q<SSTEPS.length;q++){if(SSTEPS[q]*pxs0>=90){stS=SSTEPS[q];break;}}st=stS\/sr;}\n    var k0=Math.ceil(view.s\/st-1e-9),k1=Math.floor((view.s+view.sp)\/st+1e-9),dd=st>=1?0:(st>=0.1?1:(st>=0.01?2:(st>=0.001?3:(st>=0.0001?4:(st>=0.00001?5:6)))));\n    for(var k=k0;k<=k1;k++){\n      var tt=k*st,tx=Math.round((tt-view.s)*pps*dpr);\n      g.fillStyle='rgba(255,255,255,.3)';g.fillRect(tx,rul-7*dpr,Math.max(1,Math.round(dpr)),7*dpr);\n      g.fillStyle='#b4c0d3';g.fillText(smpU?fN(Math.round(k*stS)):fmtP(tt,dd),tx+4*dpr,5*dpr);\n    }\n    var tints=[];\n    if(segSel)tints.push([segSel.a,segSel.b,1]);\n    if(selActive&&linkOn)tints.push([trimS,trimE,isSegRange(trimS,trimE)?1:0]);\n    if(selR&&!linkOn)tints.push([selR.a,selR.b,isSegRange(selR.a,selR.b)?1:0]);\n    tints.forEach(function(q){\n      var qx0=Math.max(0,Math.round(X(q[0])*dpr)),qx1=Math.min(cw,Math.round(X(q[1])*dpr));\n      if(qx1>qx0){\n        if(q[2]){\n          \/* segmentet valgt med h\u00e5nd-v\u00e6rkt\u00f8jet: lysere kanter, m\u00f8rk midte (ved nullinjen) *\/\n          var gl=chN>1?2:1,glh=(ch-rul)\/gl,gk;\n          for(gk=0;gk<gl;gk++){\n            var gt=rul+gk*glh,gg=g.createLinearGradient(0,gt,0,gt+glh);\n            gg.addColorStop(0,'#4c4542');gg.addColorStop(.25,'#3e3732');gg.addColorStop(.5,'#342d28');gg.addColorStop(.75,'#3e3732');gg.addColorStop(1,'#4c4542');\n            g.fillStyle=gg;g.fillRect(qx0,gt,qx1-qx0,glh);\n          }\n        }else{g.fillStyle='#1e150f';g.fillRect(qx0,rul,qx1-qx0,ch-rul);}\n      }\n    });\n    var lanes=chN>1?2:1,laneH=(ch-rul)\/lanes;\n    var vg=1,spc=view.sp*sr\/cw,s0=view.s*sr,len=buf.length,nb=bins.nb,x,j,c,ln;\n    var SS=trimS*sr,EE=trimE*sr,datas=[];\n    for(c=0;c<chN;c++)datas.push(buf.getChannelData(c));\n    var pxs=cw\/(view.sp*sr),sm=pxs>=5;\n    for(ln=0;ln<lanes;ln++){\n      var top=rul+ln*laneH,bot=top+laneH,mid2=top+laneH\/2,amp2=laneH\/2*0.92*vz,mn=bins.cmn[ln],mx=bins.cmx[ln],d0=datas[ln],last='';\n      var gf0=mkGain(trimS,trimE-trimS,ln),ge0=mkGain(0,dur,ln,true),gf=function(t){return (t>=trimS&&t<trimE)?gf0(t):ge0(t);};\n      g.fillStyle='rgba(255,255,255,.09)';g.fillRect(0,Math.round(mid2),cw,Math.max(1,Math.round(dpr)));\n      if(ln>0){g.fillStyle='rgba(255,255,255,.18)';g.fillRect(0,Math.round(top),cw,Math.max(1,Math.round(dpr)));}\n      var wg=g.createLinearGradient(0,top,0,bot);wg.addColorStop(0,'#2b86dd');wg.addColorStop(.5,'#7ccbff');wg.addColorStop(1,'#2b86dd');\n      var wgW='#ffffff';\n      if(sm){\n        var si0=Math.max(0,Math.floor(s0)-1),si1=Math.min(len-1,Math.ceil(s0+cw*spc)+1),spx=null,spy=null,si,\n            slw=Math.max(1,1.4*dpr),srad=pxs>=14?3.2*dpr:(pxs>=9?2.6*dpr:2*dpr),sstem=pxs>=12;\n        g.lineJoin='round';\n        for(si=si0;si<=si1;si++){\n          var sti=si\/sr,sxx=(si-s0)\/spc,sv=d0[si]*(envLive?vg*gf(sti):vg),syy=Math.max(top+1,Math.min(bot-1,mid2-sv*amp2));\n          var sIn=sti>=trimS&&sti<trimE,sHl=hl&&sti>=hl.s&&sti<hl.e,sSg=segSel&&sti>=segSel.a&&sti<segSel.b,\n              sSl=sIn&&selActive&&linkOn,sSr=selR&&!linkOn&&sti>=selR.a&&sti<selR.b,sClip=sIn&&Math.abs(sv)>CLIPT;\n          var scol=sSg?'#ffffff':((sSl||sSr)?(sClip?'#ff4055':'#ffffff'):(sHl?'#ff9a4d':(sClip?'#ff4055':'#7ccbff')));\n          if(spx!==null){g.strokeStyle=scol;g.lineWidth=slw;g.beginPath();g.moveTo(spx,spy);g.lineTo(sxx,syy);g.stroke();}\n          if(sstem){g.globalAlpha=.3;g.strokeStyle=scol;g.lineWidth=Math.max(1,dpr);g.beginPath();g.moveTo(sxx,mid2);g.lineTo(sxx,syy);g.stroke();g.globalAlpha=1;}\n          g.fillStyle=scol;g.beginPath();g.arc(sxx,syy,srad,0,6.2832);g.fill();\n          spx=sxx;spy=syy;\n        }\n      }else for(x=0;x<cw;x++){\n        var a=s0+x*spc,b=a+spc;\n        if(a>=len)break;\n        var ra=a,rb=b,kk=1,tcn=(a+b)\/2\/sr,inSel=tcn>=trimS&&tcn<trimE;\n        kk=envLive?vg*gf(tcn):vg;\n        if(ra<0)ra=0;if(rb>len)rb=len;if(rb<=ra)rb=ra+1;\n        var lo=1,hi=-1;\n        if(spc>=BIN){\n          var ba=Math.floor(ra\/BIN);if(ba>=nb)continue;\n          var bb=Math.min(nb,Math.max(ba+1,Math.ceil(rb\/BIN)));\n          for(j=ba;j<bb;j++){if(mn[j]<lo)lo=mn[j];if(mx[j]>hi)hi=mx[j];}\n        }else{\n          var ia=Math.floor(ra),ib=Math.min(len,Math.max(ia+1,Math.ceil(rb)));\n          for(j=ia;j<ib;j++){var v=d0[j];if(v<lo)lo=v;if(v>hi)hi=v;}\n        }\n        if(hi<lo)continue;\n        lo*=kk;hi*=kk;\n        var clip=inSel&&(hi>CLIPT||lo<-CLIPT)&&(spc<BIN||(ra>=SS+BIN&&rb<=EE-BIN)),inHL=hl&&tcn>=hl.s&&tcn<hl.e,inSG=segSel&&tcn>=segSel.a&&tcn<segSel.b,inSL=inSel&&selActive&&linkOn,inSR=selR&&!linkOn&&tcn>=selR.a&&tcn<selR.b,col=inSG?wgW:((inSL||inSR)?(clip?'#ff4055':wgW):(inHL?'#ff9a4d':(clip?'#ff4055':wg)));\n        var y1=mid2-hi*amp2,y2=mid2-lo*amp2;\n        if(y1<top)y1=top;\n        if(y2>bot)y2=bot;\n        if(y2<y1)y2=y1;\n        if(col!==last){g.fillStyle=col;last=col;}\n        g.fillRect(x,y1,1,Math.max(dpr,y2-y1));\n      }\n    }\n    g.font=(10*dpr)+'px -apple-system,Segoe UI,Roboto,sans-serif';g.textBaseline='top';g.textAlign='left';\n    if(lanes>1){g.fillStyle='rgba(176,190,212,.75)';g.fillText('L',6*dpr,rul+4*dpr);g.fillText('R',6*dpr,rul+laneH+4*dpr);}\n    if(vz!==1){g.fillStyle='#ff9a4d';g.textAlign='right';g.fillText('V \u00d7'+(+vz.toFixed(vz<1?2:1)),cw-6*dpr,5*dpr);g.textAlign='left';}\n  }\n  function drawOv(){\n    var cv=el.ov,w=W(),h=H();\n    if(!w||!h)return;\n    var dpr=Math.min(window.devicePixelRatio||1,2),cw=Math.round(w*dpr),ch=Math.round(h*dpr);\n    if(cv.width!==cw||cv.height!==ch){cv.width=cw;cv.height=ch;}\n    var g=cv.getContext('2d');g.setTransform(dpr,0,0,dpr,0,0);g.clearRect(0,0,w,h);\n    if(!buf)return;\n    var em=tool==='env',i,y;\n    if(loopOn||rulHot){\n      var bx0=Math.max(0,X(trimS)),bx1=Math.min(w,X(trimE)),rc=loopOn?'255,200,60':'255,122,31';\n      if(rulHot===2){g.fillStyle='rgba('+rc+',.08)';g.fillRect(0,0,w,RUL+8);}\n      if(bx1>bx0){\n        var al=rulHot===2?(loopOn?.62:.36):(rulHot===1?(loopOn?.42:.15):.2);\n        g.fillStyle='rgba('+rc+','+al+')';g.fillRect(bx0,0,bx1-bx0,RUL);\n      }\n    }\n    g.font='10px -apple-system,Segoe UI,Roboto,sans-serif';g.textBaseline='alphabetic';\n    var zs=zones();\n    zs.forEach(function(z){\n      var D=ED(z.c),pts=D.env;\n      g.save();g.beginPath();g.rect(0,z.top,w,z.bot-z.top);g.clip();\n      if(em||pts.length){\n        var marks;\n        if(!em)marks=[0];\n        else if(vz<=1)marks=[12,6,0,-6,-12,-24,-36,-48];\n        else{var stp=vz>=8?1:(vz>=4?2:3);marks=[];for(var mk=DBMAX;mk>=DBMIN;mk-=stp)marks.push(mk);}\n        g.lineWidth=1;g.textAlign='right';\n        for(i=0;i<marks.length;i++){\n          y=Math.round(dbToY(marks[i],z))+.5;\n          g.strokeStyle=marks[i]===0?'rgba(255,196,107,.38)':'rgba(255,196,107,.12)';\n          g.setLineDash(marks[i]===0?[5,4]:[2,4]);\n          g.beginPath();g.moveTo(0,y);g.lineTo(w,y);g.stroke();\n          if(em){g.fillStyle='rgba(255,196,107,.7)';g.fillText(marks[i]===0?'0 dB':(marks[i]>0?'+':'\u2212')+Math.abs(marks[i]),w-6,y-3);}\n        }\n        g.setLineDash([]);\n      }\n      if(em&&!pts.length){\n        var zl=Math.round(dbToY(0,z))+.5;\n        g.strokeStyle='#ffc46b';g.lineWidth=2;g.globalAlpha=1;g.setLineDash([]);\n        g.beginPath();g.moveTo(0,zl);g.lineTo(w,zl);g.stroke();\n      }\n      if(pts.length){\n        g.strokeStyle='#ffc46b';g.lineWidth=em?2:1.5;g.globalAlpha=em?1:.75;\n        g.beginPath();g.moveTo(-5,dbToY(pts[0].db,z));\n        for(i=0;i<pts.length;i++){\n          if(i>0&&(pts[i-1].sc||(pts[i-1].k&&pts[i-1].k!==1))){\n            var a0=pts[i-1],b0=pts[i],x0=X(a0.t),x1=X(b0.t),ns=clamp(Math.ceil((x1-x0)\/3),4,90),q;\n            for(q=1;q<ns;q++){var ff=q\/ns;g.lineTo(x0+(x1-x0)*ff,dbToY(a0.db+(b0.db-a0.db)*easeF(a0,ff),z));}\n          }\n          g.lineTo(X(pts[i].t),dbToY(pts[i].db,z));\n        }\n        g.lineTo(w+5,dbToY(pts[pts.length-1].db,z));g.stroke();g.globalAlpha=1;\n        for(i=0;i<pts.length;i++){\n          var px=X(pts[i].t),py=dbToY(pts[i].db,z);\n          if(px<-8||px>w+8)continue;\n          var eH=hlx&&hlx.ev.indexOf(pts[i].n)>=0;\n          g.beginPath();g.arc(px,py,(em?5.5:3.5)+(eH?1.5:0),0,6.2832);\n          g.fillStyle=(pts[i]===selPt&&em)?'#ffffff':(eH?'#ff7a1f':'#ffc46b');g.fill();\n          g.lineWidth=2;g.strokeStyle='#0d1016';g.stroke();\n        }\n        if(em){\n          for(i=0;i<pts.length-1;i++){\n            if(X(pts[i+1].t)-X(pts[i].t)<18)continue;\n            var mm2=segMid(z.c,i,z);\n            if(mm2.x<-10||mm2.x>w+10)continue;\n            var isS=selSeg&&selSeg.c===z.c&&selSeg.n===pts[i].n,isH=hovSeg&&hovSeg.c===z.c&&hovSeg.n===pts[i].n,rr=isS?7:(isH?6:4.5);\n            g.beginPath();g.moveTo(mm2.x,mm2.y-rr);g.lineTo(mm2.x+rr,mm2.y);g.lineTo(mm2.x,mm2.y+rr);g.lineTo(mm2.x-rr,mm2.y);g.closePath();\n            g.fillStyle=isS?'#ffffff':'rgba(13,16,22,.92)';g.fill();g.lineWidth=2;g.strokeStyle='#ffc46b';g.stroke();\n          }\n        }\n        if(em&&selPt&&selCh===z.c&&pts.indexOf(selPt)>=0){\n          var lx=X(selPt.t),ly=dbToY(selPt.db,z),txt=(selPt.db<=DBMIN?'\u2212\u221e dB':(selPt.db>0?'+':'')+selPt.db.toFixed(1)+' dB')+' \u00b7 '+fmt(selPt.t,2);\n          g.textAlign='left';\n          var tw=g.measureText(txt).width+10,bx=Math.min(Math.max(2,lx+8),w-tw-2),by=ly-24<z.top+2?ly+10:ly-24;\n          g.fillStyle='rgba(11,12,16,.92)';g.fillRect(bx,by,tw,16);\n          g.fillStyle='#ffc46b';g.fillText(txt,bx+5,by+11.5);\n        }\n      }\n      g.restore();\n    });\n    shBar=null;\n    if(em&&selSeg){\n      var si=segIdx(selSeg.c,selSeg.n);\n      if(si>=0){\n        var sz=zoneOf(selSeg.c),sm=segMid(selSeg.c,si,sz),sa=ED(selSeg.c).env[si],bw=4*26+8,bh=28,bx2=clamp(sm.x-bw\/2,4,w-bw-4),by2=(sm.y-bh-14>sz.top+2)?sm.y-bh-14:sm.y+14;\n        shBar={x:bx2,y:by2,w:bw,h:bh};\n        g.fillStyle='rgba(11,12,16,.95)';g.fillRect(bx2,by2,bw,bh);g.strokeStyle='rgba(255,196,107,.6)';g.lineWidth=1;g.strokeRect(bx2+.5,by2+.5,bw-1,bh-1);\n        var act=sa.sc?3:(sa.k&&sa.k>1.05?1:(sa.k&&sa.k<0.95?2:0)),ii,jj;\n        for(ii=0;ii<4;ii++){\n          var ox=bx2+4+ii*26,oy=by2+4;\n          if(ii===act){g.fillStyle='rgba(255,196,107,.22)';g.fillRect(ox,oy,24,20);}\n          g.strokeStyle=ii===act?'#ffc46b':'rgba(214,223,236,.75)';g.lineWidth=1.6;g.beginPath();\n          for(jj=0;jj<=12;jj++){\n            var fx=jj\/12,fy=ii===0?fx:(ii===1?Math.pow(fx,2):(ii===2?Math.pow(fx,0.5):fx*fx*(3-2*fx)));\n            var px2=ox+3+fx*18,py2=oy+17-fy*14;\n            if(jj===0)g.moveTo(px2,py2);else g.lineTo(px2,py2);\n          }\n          g.stroke();\n        }\n        if(sa.sc===2){g.fillStyle='#ffc46b';g.beginPath();g.arc(bx2+4+3*26+21,by2+6,2,0,6.2832);g.fill();}\n      }\n    }\n    if(em&&drag==='crv'&&crv){\n      var ci=segIdx(crv.c,crv.n);\n      if(ci>=0){\n        var cz=zoneOf(crv.c),cm=segMid(crv.c,ci,cz),ca=ED(crv.c).env[ci],cb=ED(crv.c).env[ci+1],off=cm.db-(ca.db+cb.db)\/2;\n        var ctxt='Curve '+(off>0.05?'+':(off<-0.05?'\\u2212':''))+Math.abs(off).toFixed(1)+' dB';\n        g.font='10px -apple-system,Segoe UI,Roboto,sans-serif';g.textAlign='left';\n        var cw=g.measureText(ctxt).width+10,cx=Math.min(Math.max(2,cm.x+12),w-cw-2),cy=cm.y-26<cz.top+2?cm.y+12:cm.y-26;\n        g.fillStyle='rgba(11,12,16,.92)';g.fillRect(cx,cy,cw,16);g.fillStyle='#ffc46b';g.fillText(ctxt,cx+5,cy+11.5);\n      }\n    }\n    if(markers.length){\n      var mt=RUL+3,mh=13,mw=9;\n      g.font='bold 10px -apple-system,Segoe UI,Roboto,sans-serif';g.textAlign='center';g.textBaseline='middle';\n      for(i=0;i<markers.length;i++){\n        var mm=markers[i];\n        if(mm.t>dur)continue;\n        var mx=Math.round(X(mm.t));\n        if(mx<-12||mx>w+12)continue;\n        var mH=hlx&&hlx.mk.indexOf(mm.n)>=0,mD=(drag==='mk'&&mm===dragMk&&mkDelPend);\n        g.shadowColor='rgba(0,0,0,.9)';g.shadowBlur=5;g.shadowOffsetX=0;g.shadowOffsetY=0;\n        g.strokeStyle=mD?'rgba(255,64,85,.95)':(mH?'rgba(255,122,31,.95)':'rgba(255,255,255,.85)');g.lineWidth=(mH||mD)?2:1;g.setLineDash(mD?[4,3]:[]);\n        g.beginPath();g.moveTo(mx+.5,mt+mh+6);g.lineTo(mx+.5,h);g.stroke();g.stroke();\n        g.beginPath();g.moveTo(mx-mw,mt);g.lineTo(mx+mw,mt);g.lineTo(mx+mw,mt+mh);g.lineTo(mx,mt+mh+6);g.lineTo(mx-mw,mt+mh);g.closePath();\n        g.fillStyle=mD?'#ff4055':((mm===selMk||mm===dragMk)?'#ffb877':(mH?'#ff7a1f':'#ffffff'));g.fill();\n        if(mD){g.save();g.shadowBlur=0;g.font='bold 10px -apple-system,Segoe UI,Roboto,sans-serif';g.textAlign='left';g.textBaseline='middle';var dt='Remove marker',dw=g.measureText(dt).width+10;g.fillStyle='rgba(11,12,16,.92)';g.fillRect(mx+mw+6,mt,dw,14);g.fillStyle='#ff4055';g.fillText(dt,mx+mw+11,mt+7.5);g.restore();}\n        g.lineWidth=1;g.strokeStyle='#06121f';g.stroke();g.shadowBlur=0;\n        g.fillStyle='#06121f';g.fillText(String(mm.n),mx,mt+6.5);\n      }\n      g.textBaseline='alphabetic';g.textAlign='left';\n    }\n    if(segSel){\n      var sx0=X(segSel.a),sx1=X(segSel.b);\n      g.fillStyle='#1e90ff';g.fillRect(Math.round(sx0)-1,RUL,3,h-RUL);g.fillRect(Math.round(sx1)-1,RUL,3,h-RUL);\n    }\n    if(sgHover&&!drag&&!(segSel&&Math.abs(segSel.a-sgHover.a)<1e-6&&Math.abs(segSel.b-sgHover.b)<1e-6)){\n      g.fillStyle='rgba(255,255,255,.07)';\n      var hx0=X(sgHover.a),hx1=X(sgHover.b);g.fillRect(hx0,RUL,hx1-hx0,h-RUL);\n    }\n    if(cuts.length){\n      var sbd=[0].concat(cuts).concat([dur]),si,sy0=RUL+1.5,sy1=h-1.5;\n      g.save();g.lineWidth=1;g.setLineDash([]);g.strokeStyle='rgba(255,255,255,.17)';\n      for(si=0;si<sbd.length-1;si++){\n        var bx0=X(sbd[si]),bx1=X(sbd[si+1]),bwd=bx1-bx0;\n        if(bx1<-4||bx0>w+4||bwd<8)continue;\n        var qx0=Math.round(bx0+(si===0?1:3))+.5,qx1=Math.round(bx1-(si===sbd.length-2?1:3))+.5,rr=bwd<14?2:4;\n        g.beginPath();g.moveTo(qx0+rr,sy0);g.lineTo(qx1-rr,sy0);g.arcTo(qx1,sy0,qx1,sy0+rr,rr);g.lineTo(qx1,sy1-rr);g.arcTo(qx1,sy1,qx1-rr,sy1,rr);g.lineTo(qx0+rr,sy1);g.arcTo(qx0,sy1,qx0,sy1-rr,rr);g.lineTo(qx0,sy0+rr);g.arcTo(qx0,sy0,qx0+rr,sy0,rr);g.closePath();g.stroke();\n      }\n      g.restore();\n    }\n    for(i=0;i<cuts.length;i++){\n      var cx=Math.round(X(cuts[i]))+.5;\n      if(cx<-2||cx>w+2)continue;\n      var cH=hlx&&hlx.ct.some(function(q){return Math.abs(q-cuts[i])<0.5\/sr;}),cD=(ctDrag&&ctDrag.i===i&&ctDel),cCol=cD?'#ff4055':(cH?'#ff7a1f':'#ffd84a');\n      g.strokeStyle=cCol;g.lineWidth=(cH||cD)?2:1;g.setLineDash(cD?[4,3]:[]);\n      g.beginPath();g.moveTo(cx,RUL+5);g.lineTo(cx,h);g.stroke();\n      var big=(hovCut===i||(ctDrag&&ctDrag.i===i)),tw2=big?6:4,th2=big?9:6;\n      g.setLineDash([]);\n      g.fillStyle=cCol;g.beginPath();g.moveTo(cx-tw2,RUL);g.lineTo(cx+tw2,RUL);g.lineTo(cx,RUL+th2);g.closePath();g.fill();\n      if(cD){\n        g.save();g.font='bold 10px -apple-system,Segoe UI,Roboto,sans-serif';g.textAlign='left';g.textBaseline='middle';\n        var dt2='Remove split',dw2=g.measureText(dt2).width+10;\n        g.fillStyle='rgba(11,12,16,.92)';g.fillRect(cx+10,RUL+1,dw2,14);g.fillStyle='#ff4055';g.fillText(dt2,cx+15,RUL+8.5);g.restore();\n      }else if(ctDrag&&ctDrag.i===i&&ctDrag.moved){\n        var ct0=fU(cuts[i]);g.font='bold 11px ui-monospace,SFMono-Regular,Menlo,Consolas,monospace';g.textAlign='left';g.textBaseline='middle';\n        var cw3=g.measureText(ct0).width+12,cx3=Math.min(Math.max(2,cx-cw3\/2),w-cw3-2);\n        g.fillStyle='rgba(11,12,16,.94)';g.fillRect(cx3,RUL+14,cw3,18);g.strokeStyle='#ffd84a';g.lineWidth=1;g.strokeRect(cx3+.5,RUL+14.5,cw3-1,17);\n        g.fillStyle='#ffd84a';g.fillText(ct0,cx3+6,RUL+23.5);g.textBaseline='alphabetic';\n      }\n    }\n    if(hlx&&hlx.line!=null){\n      var lx=Math.round(X(hlx.line))+.5;\n      if(lx>-6&&lx<w+6){g.strokeStyle='#ff7a1f';g.lineWidth=2;g.setLineDash([]);g.beginPath();g.moveTo(lx,RUL);g.lineTo(lx,h);g.stroke();g.fillStyle='#ff7a1f';g.beginPath();g.moveTo(lx-5,RUL);g.lineTo(lx+5,RUL);g.lineTo(lx,RUL+7);g.closePath();g.fill();}\n    }\n    if(tool==='cut'&&cutHover>=0&&!drag){\n      var gx=Math.round(X(cutHover))+.5;\n      g.strokeStyle='rgba(255,216,74,.6)';g.lineWidth=1;g.setLineDash([]);\n      g.beginPath();g.moveTo(gx,RUL);g.lineTo(gx,h);g.stroke();\n    }\n    if(drag==='sg'&&sgDrag&&sgDrag.moved){\n      var gl=sgDrag.b-sgDrag.a,gx=Math.round(X(sgDrag.c))+.5,lbl=fmt(sgDrag.c,2);\n      if(sgDrag.noop){\n        g.strokeStyle='rgba(190,198,210,.8)';g.lineWidth=2;g.setLineDash([6,4]);\n        g.beginPath();g.moveTo(gx,RUL);g.lineTo(gx,h);g.stroke();g.setLineDash([]);lbl+=' \u00b7 no change';\n      }else{\n        if(pasteMode==='over'){\n          var hs=sgDrag.right?sgDrag.c+gl:sgDrag.c,hx0=X(hs),hx1=X(hs+gl);\n          g.fillStyle='rgba(255,70,50,.34)';g.fillRect(hx0,RUL,hx1-hx0,h-RUL);\n          g.strokeStyle='rgba(255,120,90,.95)';g.lineWidth=1.5;g.setLineDash([5,4]);g.strokeRect(hx0+.5,RUL+.5,hx1-hx0-1,h-RUL-1);g.setLineDash([]);\n        }\n        var px0=X(sgDrag.c),px1=X(sgDrag.c+gl);\n        g.fillStyle='rgba(30,120,255,.45)';g.fillRect(px0,RUL,px1-px0,h-RUL);\n        g.strokeStyle='#3aa9ff';g.lineWidth=2;g.strokeRect(px0+1,RUL+1,px1-px0-2,h-RUL-2);\n        g.strokeStyle='#35e07a';g.lineWidth=2;g.shadowColor='rgba(53,224,122,.9)';g.shadowBlur=8;\n        g.beginPath();g.moveTo(gx,RUL);g.lineTo(gx,h);g.stroke();g.shadowBlur=0;\n      }\n      g.font='bold 11px -apple-system,Segoe UI,Roboto,sans-serif';g.textAlign='left';g.textBaseline='middle';\n      var tw=g.measureText(lbl).width,bx=clamp(gx-tw\/2-6,2,w-tw-14);\n      g.fillStyle='rgba(10,12,16,.92)';g.fillRect(bx,RUL+3,tw+12,17);\n      g.strokeStyle=sgDrag.noop?'rgba(190,198,210,.8)':'#35e07a';g.lineWidth=1;g.strokeRect(bx+.5,RUL+3.5,tw+11,16);\n      g.fillStyle=sgDrag.noop?'#c3cad6':'#35e07a';g.fillText(lbl,bx+6,RUL+12);\n      g.textBaseline='alphabetic';\n    }\n    if(!linkOn&&selR){\n      g.fillStyle='rgba(255,255,255,.42)';\n      var ex0=Math.round(X(selR.a)),ex1=Math.round(X(selR.b));\n      if(ex0>=0&&ex0<=w)g.fillRect(ex0,RUL,1,h-RUL);\n      if(ex1>=0&&ex1<=w)g.fillRect(ex1-1,RUL,1,h-RUL);\n    }\n    if(snapOn){\n      g.fillStyle='rgba(255,122,31,.95)';\n      var sc=0;\n      for(i=0;i<snapPts.length;i++){var sx=X(snapPts[i]);if(sx<-2||sx>w+2)continue;g.fillRect(Math.round(sx)-.5,RUL-6,1.5,6);if(++sc>1500)break;}\n    }\n  }\n  function place(e,x,off){\n    var w=W();\n    if(x<-20||x>w+20){e.style.display='none';return;}\n    e.style.display='block';e.style.transform='translateX('+(x-off)+'px)';\n  }\n  function placePH(){place(el.ph,X(getPos()),1);}\n  function layout(){\n    if(!buf)return;\n    var w=W(),xs=X(trimS),xe=X(trimE),rl=clamp(xe,0,w);\n    el.shl.style.width=clamp(xs,0,w)+'px';\n    el.shr.style.left=rl+'px';el.shr.style.width=(w-rl)+'px';\n    var ls=clamp(xs,0,w);el.seln.style.left=ls+'px';el.seln.style.width=Math.max(0,rl-ls)+'px';\n    place(el.hs,xs,8);place(el.he,xe,8);placePH();\n    el.hs.classList.toggle('aew-in',xs<22);el.he.classList.toggle('aew-in',xe>w-22);\n    var gse=selEdges(),gshow=(gse&&tool==='sel'&&(!drag||drag==='gr'));\n    ['a','b'].forEach(function(ge){\n      var gel=ge==='a'?el.gra:el.grb;\n      if(!gshow){gel.style.display='none';return;}\n      var gt=ge==='a'?gse.a:gse.b,gx=X(gt);\n      if(gx<-12||gx>w+12){gel.style.display='none';return;}\n      var gact=(gripAct===ge)||(drag==='gr'&&grip&&grip.e===ge);\n      gel.style.display='block';gel.style.left=gx+'px';gel.style.top=gripY()+'px';\n      gel.classList.toggle('aew-act',!!gact);gel.classList.toggle('aew-hov',gripHov===ge&&!gact);\n      if(gact){\n        el.grl.textContent=fU(gt);el.grl.style.display='block';\n        var lw=el.grl.offsetWidth||80;el.grl.style.left=clamp(gx-lw\/2,2,w-lw-2)+'px';el.grl.style.top=(gripY()-36)+'px';\n      }\n    });\n    if(!gshow||(!gripAct&&!(drag==='gr')))el.grl.style.display='none';\n    if(!linkOn&&selR){\n      var q0=clamp(X(selR.a),0,w),q1=clamp(X(selR.b),0,w);\n      el.selr.style.display='block';el.selr.style.left=q0+'px';el.selr.style.width=Math.max(0,q1-q0)+'px';\n    }else el.selr.style.display='none';\n  }\n  function setView(s,sp){\n    if(!buf)return;\n    sp=Math.min(dur,Math.max(Math.min(dur,32\/sr),sp));\n    s=clamp(s,0,dur-sp);\n    view.s=s;view.sp=sp;\n    var z=sp<dur-1e-6;\n    el.scroll.hidden=false;el.scroll.disabled=!z;el.scroll.classList.toggle('aew-off',!z);\n    if(z){el.scroll.value=Math.round(s\/(dur-sp)*1000);el.scroll.style.setProperty('--p',(s\/(dur-sp)*100)+'%');}\n    else{el.scroll.value=0;el.scroll.style.setProperty('--p','0%');}\n    invalidate(true,true);\n  }\n  var ZSTEP=1.25;\n  function zoomV(f){vz=clamp(vz*f,0.1,64);if(Math.abs(vz-1)<1e-6)vz=1;invalidate(true,true);}\n  function zoomAt(f,c){\n    var sp=Math.min(dur,Math.max(Math.min(dur,32\/sr),view.sp*f));\n    setView(c-(c-view.s)*(sp\/view.sp),sp);\n  }\n  \/* ---------- Transport ---------- *\/\n  function rawPos(){\n    var e=p0+(ctx.currentTime-t0)*curRate;\n    if(nLoop&&e>=loopB){var LL=loopB-loopA;e=loopA+((e-loopA)%LL);}\n    return e;\n  }\n  function getPos(){return playing&&ctx?Math.min(playEndT,rawPos()):pos;}\n  function cutBtnUI(){\n    if(!playing)cutLive=false;\n    el.tcut.classList.toggle('aew-live',!!(cutLive&&playing&&tool==='cut'));\n  }\n  function setPlayUI(on){if(!on)cutLive=false;el.tcut.classList.toggle('aew-live',!!(cutLive&&on&&tool==='cut'));el.pplay.classList.toggle('aew-on',on&&playMode!=='norm');el.lpl.classList.toggle('aew-on',on&&!el.lcmod.hidden);el.play.classList.toggle('aew-playing',on);el.play.setAttribute('aria-label',on?'Pause':'Play');}\n  function scheduleFx(){\n    if(!fxNode||!playing||!ctx)return;\n    var now=ctx.currentTime,p=Math.min(playEndT,rawPos()),end=Math.min(playEndT,p+FXWIN),span=end-p;\n    var tg=(fxSplitPlay&&fxL)?[{gp:fxL.gain,c:0},{gp:fxR.gain,c:1}]:[{gp:fxNode.gain,c:0}];\n    if(nLoop){\n      tg.forEach(function(o){var gl=mkGain(trimS,trimE-trimS,o.c);o.gp.cancelScheduledValues(now);o.gp.setValueAtTime(gl((loopA+loopB)\/2),now);});\n      fxEnd=playEndT;return;\n    }\n    fxEnd=end;\n    tg.forEach(function(o){\n      var g0=mkGain(trimS,trimE-trimS,o.c),ge=mkGain(0,dur,o.c,true),gf=function(t){return (t>=trimS&&t<trimE)?g0(t):ge(t);},gp=o.gp;\n      gp.cancelScheduledValues(now);\n      gp.setValueAtTime(gf(p),now);\n      if(span<0.004)return;\n      var n=Math.max(2,Math.ceil(span*FXRATE)),i;\n      for(i=1;i<=n;i++)gp.linearRampToValueAtTime(gf(p+span*i\/n),now+(span*i\/n)\/curRate);\n    });\n  }\n  function stopSource(){\n    var s=src;src=null;nLoop=false;\n    if(s){s.onended=null;try{s.stop();}catch(e){}try{s.disconnect();}catch(e){}}\n    if(fxNode&&ctx){var gp=fxNode.gain;gp.cancelScheduledValues(0);gp.setValueAtTime(1,ctx.currentTime);}\n    if(fxL&&ctx){fxL.gain.cancelScheduledValues(0);fxL.gain.setValueAtTime(1,ctx.currentTime);fxR.gain.cancelScheduledValues(0);fxR.gain.setValueAtTime(1,ctx.currentTime);}\n  }\n  function startSource(){\n    if(!buf)return;\n    stopSource();\n    var useLock=(playMode==='lock'&&pBuf&&pBuf.key===keyNow());\n    if(playMode==='lock'&&!useLock){playMode='norm';playRate=1;}\n    var rg=(selOnly||useLock)?selSec():[trimS,trimE],inside=pos>=rg[0]&&pos<rg[1]-0.01;\n    if(selOnly||useLock){if(!inside)pos=rg[0];playEndT=rg[1];}\n    else if(loopOn&&pos<trimE-1e-9&&trimE-trimS<0.25){playEndT=trimE;nLoop=true;loopA=trimS;loopB=trimE;}\n    else if(loopOn&&(inside||pos<trimS))playEndT=trimE;\n    else{\n      if(pos>=dur-0.01)pos=trimS;\n      playEndT=dur;\n    }\n    playFrom=pos;\n    curRate=(playMode==='vari')?playRate:1;\n    var me=ctx.createBufferSource();me.buffer=useLock?pBuf.buf:buf;\n    if(curRate!==1&&me.playbackRate)me.playbackRate.value=curRate;\n    if(nLoop){me.loop=true;me.loopStart=loopA;me.loopEnd=loopB;}\n    fxSplitPlay=!!(splitCh&&chN>1&&splIn&&me.buffer&&me.buffer.numberOfChannels>1);\n    me.connect(fxSplitPlay?splIn:gainNode);src=me;\n    me.onended=function(){\n      if(src!==me)return;\n      src=null;playing=false;\n      if(loopOn&&playEndT===trimE&&trimE-trimS>=2\/sr){pos=trimS;play();}\n      else{\n        if(selOnly||playMode!=='norm')pos=playFrom;\n        else if(rtnMode==='rtn')pos=trimS;\n        else if(rtnMode==='last')pos=lastStart;\n        else pos=playEndT;\n        setPlayUI(false);frameOnce();\n      }\n    };\n    p0=pos;t0=ctx.currentTime;\n    if(nLoop)me.start(0,pos);else me.start(0,useLock?pos-rg[0]:pos,Math.max(0.001,playEndT-pos));\n    playing=true;setPlayUI(true);scheduleFx();loopFrame();meterStart();\n  }\n  function play(){\n    if(!buf)return;\n    if(ctx.state==='running')startSource();else ctx.resume().then(startSource);\n  }\n  function pause(){\n    if(playing){pos=getPos();stopSource();playing=false;}\n    setPlayUI(false);frameOnce();\n  }\n  \/* stop fra brugeren: RTN sender cursoren til L, LAST til stedet hvor afspilningen blev startet *\/\n  function userStop(){\n    pause();\n    if(rtnMode==='rtn')pos=trimS;else if(rtnMode==='last')pos=lastStart;\n    frameOnce();\n  }\n  function toggle(){\n    if(playing){userStop();return;}\n    playMode='norm';playRate=1;selOnly=false;\n    if(tool==='mv'&&segSel){pos=segSel.a;lastStart=pos;}\n    else{\n      lastStart=(pos>=dur-0.01)?trimS:pos;\n      if(rtnMode==='rtn')pos=trimS;\n    }\n    play();\n  }\n  function rtnUI(){\n    el.rtn.classList.toggle('aew-on',rtnMode==='rtn');el.rtn.setAttribute('aria-pressed',rtnMode==='rtn'?'true':'false');\n    el.lastb.classList.toggle('aew-on',rtnMode==='last');el.lastb.setAttribute('aria-pressed',rtnMode==='last'?'true':'false');\n  }\n  function restart(){\n    if(!playing)return;\n    var p=rawPos();stopSource();pos=p;\n    if(p>=dur-0.01){playing=false;pos=playFrom;setPlayUI(false);frameOnce();}\n    else startSource();\n  }\n  function seekTo(t){\n    var was=playing;\n    if(was){pos=getPos();stopSource();playing=false;}\n    pos=clamp(t,0,dur);\n    if(was)play();else frameOnce();\n  }\n  function setIP(t){seekTo(t);}\n  function nudgeIP(dt){\n    var q=clamp(getPos()+dt,0,dur);\n    seekTo(q);\n    if(q<view.s||q>view.s+view.sp)setView(q-view.sp*0.5,view.sp);\n  }\n  \/* ---------- Markers (24 stk.) ---------- *\/\n  var MKMAX=24;\n  function mkFind(n){for(var i=0;i<markers.length;i++)if(markers[i].n===n)return markers[i];return null;}\n  function mkFree(){for(var n=1;n<=MKMAX;n++)if(!mkFind(n))return n;return 0;}\n  \/* tal der skrives i felter: accepterer komma, minus-tegn, + og enheder (st, Hz, kHz, dB, LUFS, dBTP) *\/\n  function parseNum(v){\n    var s=String(v).trim().toLowerCase().replace(\/\\u2212\/g,'-').replace(',','.').replace(\/\\s+\/g,'');\n    s=s.replace(\/(semitones?|dbtp|lufs|khz|hz|db|st)$\/,function(m){return m==='khz'?'k':'';});\n    var m=1;if(\/k$\/.test(s)){m=1000;s=s.slice(0,-1);}\n    if(!\/^[+-]?(\\d+\\.?\\d*|\\.\\d+)$\/.test(s))return NaN;\n    return parseFloat(s)*m;\n  }\n  function numTxt(x,d){return String(+(+x).toFixed(d==null?2:d));}\n  function wireNum(inp,commit){\n    inp.addEventListener('change',commit);\n    inp.addEventListener('keydown',function(e){e.stopPropagation();if(e.key==='Enter'){e.preventDefault();inp.blur();}});\n    inp.addEventListener('focus',function(){try{inp.select();}catch(_){}});\n  }\n  var mkEditing=false;\n  function mkInfoUI(){\n    if(mkEditing)return;\n    if(!el.mki)return;\n    el.mki.textContent=(buf&&selMk)?('Marker '+selMk.n+'  \\u00b7  '+fU(selMk.t)):'';\n    el.mki.classList.toggle('aew-ed',!!(buf&&selMk));\n    el.mki.title=(buf&&selMk)?'Click to type an exact position':'';\n  }\n  function mkUI(){\n    var bs=$$('.aew-mkb'),i;\n    for(i=0;i<bs.length;i++){var on=!!mkFind(+bs[i].getAttribute('data-n'));bs[i].classList.toggle('aew-mkset',on);bs[i].setAttribute('aria-pressed',on?'true':'false');}\n    el.mkp.disabled=el.mkn.disabled=!markers.length;\n    invalidate(false,true);\n  }\n  function markHere(){\n    if(!buf)return;\n    var t=getPos(),i;\n    for(i=0;i<markers.length;i++)if(Math.abs(markers[i].t-t)<0.002)return;\n    var n=mkFree();\n    if(!n){say('Maximum 24 markers.',true);return;}\n    edit(function(){markers.push({n:n,t:clamp(t,0,dur)});});\n    mkUI();\n  }\n  function mkAssign(n){\n    if(!buf||mkFind(n))return;\n    var t=getPos();\n    edit(function(){markers.push({n:n,t:clamp(t,0,dur)});});\n    mkUI();\n  }\n  function mkDel(m){\n    edit(function(){var i=markers.indexOf(m);if(i>=0)markers.splice(i,1);if(selMk===m)selMk=null;});\n    mkUI();\n  }\n  function mkSorted(){return markers.slice().sort(function(a,b){return a.t-b.t;});}\n  function mkPrev(){\n    var p=getPos()-0.001,s=mkSorted(),best=null,i;\n    for(i=0;i<s.length;i++)if(s[i].t<p)best=s[i];\n    if(best)toLoopPoint(best.t);\n  }\n  function mkNext(){\n    var p=getPos()+0.001,s=mkSorted(),i;\n    for(i=0;i<s.length;i++)if(s[i].t>p){toLoopPoint(s[i].t);return;}\n  }\n  function hitMarker(x,y){\n    if(y<RUL+2||y>RUL+24)return null;\n    for(var i=markers.length-1;i>=0;i--){var m=markers[i];if(m.t>dur)continue;if(Math.abs(x-X(m.t))<=10)return m;}\n    return null;\n  }\n  \/* ---------- Saks og flyttev\u00e6rkt\u00f8j: snitlinjer deler filen i dele ---------- *\/\n  function isSegRange(a,b){\n    if(!cuts.length)return false;\n    var bd=[0].concat(cuts,[dur]),i,e=1.5\/sr;\n    for(i=0;i<bd.length-1;i++)if(Math.abs(a-bd[i])<=e&&Math.abs(b-bd[i+1])<=e)return true;\n    return false;\n  }\n  function cutsFix(fn){\n    var e=0.5\/sr,a=[],i,v;\n    for(i=0;i<cuts.length;i++){v=fn(cuts[i]);if(v!==null&&v>e&&v<dur-e)a.push(v);}\n    a.sort(function(x,y){return x-y;});\n    cuts=[];\n    for(i=0;i<a.length;i++)if(!cuts.length||a[i]-cuts[cuts.length-1]>e)cuts.push(a[i]);\n  }\n  function cutSnapTime(t){\n    t=clamp(t,0,dur);\n    if(snapOn)t=snapT(t);\n    var s=Math.round(t*sr);\n    if(pmode==='zc'){var z=zcEdge(s);s=z.i;}\n    return s\/sr;\n  }\n  function cutClick(x){\n    if(segSel){segSel=null;invalidate(true,true);}\n    var t=cutSnapTime(T(x)),e=0.5\/sr,i,hit=-1;\n    if(t<=e||t>=dur-e)return;\n    for(i=0;i<cuts.length;i++)if(Math.abs(X(cuts[i])-x)<=5){hit=i;break;}\n    edit(function(){\n      if(hit>=0)cuts.splice(hit,1);\n      else{\n        for(var k=0;k<cuts.length;k++)if(Math.abs(cuts[k]-t)<0.002)return;\n        cuts.push(t);cuts.sort(function(a,b){return a-b;});\n        if(playing){cutLive=true;}\n      }\n    });\n    cutBtnUI();\n    invalidate(false,true);\n  }\n  function cutHere(){\n    if(!buf||tool==='env'||drag)return;\n    if(tool!=='cut')setTool('cut');\n    var s=Math.round(getPos()*sr);\n    if(pmode==='zc'){var z=zcEdge(s);s=z.i;}\n    var t=s\/sr,e=0.5\/sr,i;\n    if(t<=e||t>=dur-e)return;\n    for(i=0;i<cuts.length;i++)if(Math.abs(cuts[i]-t)<0.002)return;\n    if(segSel){segSel=null;invalidate(true,true);}\n    edit(function(){cuts.push(t);cuts.sort(function(a,b){return a-b;});});\n    if(playing){cutLive=true;cutBtnUI();}\n    invalidate(false,true);\n  }\n  function clipLocators(){\n    if(!buf||tool==='env'||drag)return;\n    var e=0.5\/sr,cand=[['L',trimS],['R',trimE]],todo=[],why=[];\n    cand.forEach(function(q){\n      var s=Math.round(q[1]*sr);\n      if(pmode==='zc'){var z=zcEdge(s);s=z.i;}\n      var t=s\/sr,k,dup=false;\n      if(t<=e||t>=dur-e){why.push(q[0]+' is at the '+(q[0]==='L'?'start':'end')+' of the file');return;}\n      for(k=0;k<cuts.length;k++)if(Math.abs(cuts[k]-t)<0.002)dup=true;\n      for(k=0;k<todo.length;k++)if(Math.abs(todo[k].t-t)<0.002)dup=true;\n      if(dup){why.push('there is already a cut at '+q[0]);return;}\n      todo.push({n:q[0],t:t});\n    });\n    if(!todo.length){say('Nothing to split: '+why.join(', ')+'.',true);return;}\n    if(segSel){segSel=null;invalidate(true,true);}\n    edit(function(){todo.forEach(function(q){cuts.push(q.t);});cuts.sort(function(a,b){return a-b;});});\n    if(playing&&tool==='cut'){cutLive=true;cutBtnUI();}\n    invalidate(false,true);\n    say(todo.length===2?'Cuts placed at L and R.':'Cut placed at '+todo[0].n+(why.length?' ('+why.join(', ')+')':'')+'.');\n  }\n  function segAt(t){\n    var b=[0].concat(cuts).concat([dur]),i;\n    for(i=0;i<b.length-1;i++)if(t>=b[i]&&t<b[i+1])return {a:b[i],b:b[i+1]};\n    return {a:b[b.length-2],b:b[b.length-1]};\n  }\n  \/* flyt en del: hullet lukkes, og delen s\u00e6ttes ind (Inds\u00e6t og skub) eller overskriver (Overskriv) ved slippestedet *\/\n  function mvSegment(a,b,c){\n    if(!buf)return false;\n    var N=buf.length,nc=buf.numberOfChannels,mode=pmode,Nx=xfSamples(),ins=(pasteMode==='insert'),ch,k,th,j;\n    var A=Math.round(a*sr),B=Math.round(b*sr),Dn=Math.round(c*sr),dirZ=0;\n    if(mode==='zc'){var zr=zcRange(A,B);A=zr[0];B=zr[1];dirZ=zr[2];}\n    var m=B-A;\n    if(m<2||m>=N)return false;\n    Dn=clamp(Dn,0,N-m);\n    var right=(Dn>=B);\n    if(!ins&&right)Dn=Math.min(Dn,N-2*m);\n    if(Dn<B&&Dn+m>A)return false;                    \/* forh\u00e5ndsvisningen overlapper delens egen plads: ingen \u00e6ndring *\/\n    var C=right?Dn+m:Dn;                             \/* inds\u00e6tningspunktet i den oprindelige lyd *\/\n    if(mode==='zc'){\n      var Cs=zcSnap(C,dirZ).i;\n      if(right?(Cs>=B&&Cs<=(ins?N:N-m)):(Cs>=0&&Cs+m<=A))C=Cs;\n    }\n    if(playing)pause();\n    var D=right?C-m:C,Np=N-m,orig=[],post=[],clip=[],half=m>>1;\n    for(ch=0;ch<nc;ch++){\n      var o=buf.getChannelData(ch),p=new Float32Array(Np);\n      p.set(o.subarray(0,A),0);p.set(o.subarray(B,N),A);\n      orig.push(o);post.push(p);clip.push(o.slice(A,B));\n    }\n    var lo=right?A:C;\n    \/* 1) hullet lukkes (equal power: det efterf\u00f8lgende tones ind, mens delens begyndelse tones ud) *\/\n    if(mode==='eq'){\n      var hasA=A>0,hasB=B<N,n;\n      if(hasA&&hasB){\n        n=Math.min(Nx,m,N-B);\n        for(ch=0;ch<nc;ch++)for(k=0;k<n;k++){th=Math.PI\/2*(k+0.5)\/n;post[ch][A+k]=Math.sin(th)*post[ch][A+k]+Math.cos(th)*orig[ch][A+k];}\n      }else if(!hasA&&hasB){\n        n=Math.min(Nx,N-B);\n        for(ch=0;ch<nc;ch++)for(k=0;k<n;k++){th=Math.PI\/2*(k+0.5)\/n;post[ch][k]*=Math.sin(th);}\n      }else if(hasA&&!hasB){\n        n=Math.min(Nx,A);\n        for(ch=0;ch<nc;ch++)for(k=0;k<n;k++){th=Math.PI\/2*(k+0.5)\/n;post[ch][A-n+k]*=Math.cos(th);}\n        lo=Math.min(lo,A-n);\n      }\n    }\n    \/* 2) delen s\u00e6ttes ind \/ overskriver ved slippestedet *\/\n    var fin=[];\n    for(ch=0;ch<nc;ch++){\n      var cl=Float32Array.from(clip[ch]),ps=post[ch],f;\n      if(ins){\n        if(mode==='eq'){\n          var xx=(D>0&&D<Np),n1=Math.min(Nx,half,xx?Np-D:half),n2=Math.min(Nx,half,xx?D:half);\n          for(k=0;k<n1;k++){th=Math.PI\/2*(k+0.5)\/n1;cl[k]=xx?Math.sin(th)*cl[k]+Math.cos(th)*ps[D+k]:Math.sin(th)*cl[k];}\n          for(k=0;k<n2;k++){th=Math.PI\/2*(k+0.5)\/n2;j=m-n2+k;cl[j]=xx?Math.cos(th)*cl[j]+Math.sin(th)*ps[D-n2+k]:Math.cos(th)*cl[j];}\n        }\n        f=new Float32Array(Np+m);f.set(ps.subarray(0,D),0);f.set(cl,D);f.set(ps.subarray(D),D+m);\n      }else{\n        f=Float32Array.from(ps);\n        var q1=Math.min(Nx,half),v,ex;\n        for(k=0;k<m;k++){\n          v=cl[k];ex=ps[D+k];\n          if(mode==='eq'){\n            if(k<q1){th=Math.PI\/2*(k+0.5)\/q1;v=Math.sin(th)*cl[k]+Math.cos(th)*ex;}\n            else if(k>=m-q1){th=Math.PI\/2*(k-(m-q1)+0.5)\/q1;v=Math.cos(th)*cl[k]+Math.sin(th)*ex;}\n          }\n          f[D+k]=v;\n        }\n      }\n      fin.push(f);\n    }\n    var hiO,hiF;\n    if(right){hiO=ins?C:C+m;hiF=C;}else{hiO=B;hiF=ins?B:A;}\n    var rp=[];\n    for(ch=0;ch<nc;ch++)rp.push(fin[ch].subarray(lo,hiF));\n    var st=pend||snap();pend=null;\n    var runsOld=srcRuns.slice(),olds=replaceSamples(lo,hiO-lo,rp);\n    (function(){\n      var clipR=srcSlice(runsOld,A,B),postR=srcDelRuns(runsOld,A,B);\n      if(!ins)postR=srcDelRuns(postR,D,Math.min(D+m,srcTotal(postR)));\n      srcRuns=srcInsRuns(postR,D,clipR);\n    })();\n    pushHist(st,{type:'rep',at:lo,old:olds,newLen:hiF-lo,mv:{a:A,b:B,d:D,m:m}});\n    \/* 3) snitlinjer og envelope f\u00f8lger lyden *\/\n    function mapS(xs){\n      var e=0.5;\n      if(xs>A+e&&xs<B-e)return {n:D+(xs-A),part:true};\n      if(right){\n        if(xs<=A+e)return {n:xs};\n        if(xs<=C+e)return {n:xs-m};\n        if(ins)return {n:xs};\n        if(xs<C+m-e)return {n:null};\n        return {n:xs-m};\n      }\n      if(xs<=C+e)return {n:xs};\n      if(xs<=A+e)return ins?{n:xs+m}:(xs<C+m-e?{n:null}:{n:xs});\n      return ins?{n:xs}:{n:xs-m};\n    }\n    cutsFix(function(q){var r=mapS(q*sr);return (r.n===null||r.part)?null:r.n\/sr;});\n    cuts.push(D\/sr,(D+m)\/sr);cutsFix(function(q){return q;});\n    envEach(function(env){\n      return env.map(function(q){var r=mapS(q.t*sr);return r.n===null?null:{t:r.n\/sr,db:q.db,n:q.n,k:q.k,sc:q.sc};}).filter(function(q){return q;}).sort(function(x,y){return x.t-y.t;});\n    });\n    selPt=null;\n    afterStruct();\n    hl={s:D\/sr,e:(D+m)\/sr};invalidate(true,true);\n    return true;\n  }\n  function toLoopPoint(t){\n    if(!buf)return;\n    seekTo(t);\n    if(t<view.s||t>view.s+view.sp)setView(t-view.sp*0.05,view.sp);\n  }\n  function toStart(){\n    if(!buf)return;\n    if(playing)pause();\n    pos=0;setIP(0);selActive=false;\n    if(view.s>0)setView(0,view.sp);\n    frameOnce();\n  }\n  function frameOnce(){\n    if(!buf)return;\n    if(selActive!==selDrawn)invalidate(true,false);\n    var p=getPos();\n    if(playing&&!drag&&followOn&&view.sp<dur-1e-6&&(p>view.s+view.sp*0.98||p<view.s)){setView(p-view.sp*0.05,view.sp);}\n    placePH();\n    el.tcur.textContent=fL(p);\n  }\n  function tickFrame(){\n    raf=0;frameOnce();\n    if(playing){\n      if(fxEnd<playEndT-0.001&&rawPos()>fxEnd-3)scheduleFx();\n      raf=requestAnimationFrame(tickFrame);\n    }\n  }\n  function loopFrame(){if(!raf)raf=requestAnimationFrame(tickFrame);}\n  \/* ---------- Scrub: sammenh\u00e6ngende varispeed som p\u00e5 et gammelt b\u00e5nd ---------- *\/\n  var scrubIv=0,scrubOn=false,scrubPos=0,scrubTgt=0,scrubVel=0,scrubP0=0,scrubX0=0,scrubLastT=0,scrubWin=null,scrubSrc=null,scrubGate=null;\n  var SCR_GEAR=1\/3,SCR_VMAX=1.25,SCR_TAU=0.10,SCR_WIN=8,SCR_MIN=0.03;\n  function scrubWindow(center){\n    var s0=Math.max(0,Math.floor((center-SCR_WIN)*sr)),s1=Math.min(buf.length,Math.ceil((center+SCR_WIN)*sr)),n=Math.max(2,s1-s0),c,i;\n    var f=ctx.createBuffer(chN,n,sr),r=ctx.createBuffer(chN,n,sr);\n    for(c=0;c<chN;c++){\n      var src=buf.getChannelData(c),df=f.getChannelData(c),dr=r.getChannelData(c);\n      df.set(src.subarray(s0,s0+n));\n      for(i=0;i<n;i++)dr[i]=df[n-1-i];\n    }\n    scrubWin={a:s0\/sr,b:(s0+n)\/sr,f:f,r:r,n:n};\n  }\n  function scrubStartSrc(dir){\n    var w=scrubWin,s=ctx.createBufferSource(),g=ctx.createGain(),now=ctx.currentTime,off=dir>0?scrubPos-w.a:w.b-scrubPos;\n    off=clamp(off,0,Math.max(0,w.n\/sr-0.005));\n    s.buffer=dir>0?w.f:w.r;\n    s.playbackRate.value=Math.max(0.01,Math.abs(scrubVel));\n    g.gain.setValueAtTime(0,now);g.gain.linearRampToValueAtTime(1,now+0.012);\n    s.connect(g);g.connect(scrubGate);\n    s.start(0,off);\n    s.onended=function(){try{s.disconnect();g.disconnect();}catch(_){}};\n    return {s:s,g:g,dir:dir};\n  }\n  function scrubStopSrc(o){\n    if(!o||!ctx)return;\n    var now=ctx.currentTime;\n    try{o.g.gain.cancelScheduledValues(now);o.g.gain.setValueAtTime(o.g.gain.value,now);o.g.gain.linearRampToValueAtTime(0,now+0.015);o.s.stop(now+0.03);}catch(_){}\n  }\n  function scrubStart(t,x){\n    if(!ctx||!buf)return;\n    try{ctx.resume();}catch(_){}\n    scrubOn=true;scrubPos=t;scrubTgt=t;scrubVel=0;scrubP0=t;scrubX0=T(x);scrubWin=null;scrubSrc=null;\n    scrubGate=ctx.createGain();scrubGate.gain.value=0;scrubGate.connect(gainNode);\n    scrubLastT=performance.now();\n    if(!scrubIv)scrubIv=setInterval(scrubTick,16);\n  }\n  function scrubStop(){\n    if(!scrubOn)return;\n    scrubOn=false;\n    if(scrubIv){clearInterval(scrubIv);scrubIv=0;}\n    scrubStopSrc(scrubSrc);scrubSrc=null;scrubWin=null;\n    var g=scrubGate;scrubGate=null;\n    if(g){try{g.gain.cancelScheduledValues(ctx.currentTime);g.gain.setTargetAtTime(0,ctx.currentTime,0.01);}catch(_){}setTimeout(function(){try{g.disconnect();}catch(_){}},200);}\n  }\n  function scrubTick(){\n    if(!scrubOn||!buf||!ctx)return;\n    var now=performance.now(),dt=Math.min(0.05,(now-scrubLastT)\/1000);\n    scrubLastT=now;\n    if(dt<=0)return;\n    var v=clamp((scrubTgt-scrubPos)\/SCR_TAU,-SCR_VMAX,SCR_VMAX);\n    scrubVel+=(v-scrubVel)*Math.min(1,dt\/0.04);\n    var np=clamp(scrubPos+scrubVel*dt,0,dur);\n    if((np<=0&&scrubVel<0)||(np>=dur&&scrubVel>0))scrubVel=0;\n    scrubPos=np;\n    var av=Math.abs(scrubVel),dir=scrubVel>0?1:-1,cn=ctx.currentTime;\n    if(av>SCR_MIN){\n      var need=!scrubWin||(scrubPos<scrubWin.a+0.4&&scrubWin.a>0)||(scrubPos>scrubWin.b-0.4&&scrubWin.b<dur-0.001);\n      if(need)scrubWindow(scrubPos);\n      if(!scrubSrc||scrubSrc.dir!==dir||need){scrubStopSrc(scrubSrc);scrubSrc=scrubStartSrc(dir);}\n      scrubSrc.s.playbackRate.setTargetAtTime(Math.max(0.01,av),cn,0.02);\n      scrubGate.gain.setTargetAtTime(1,cn,0.015);\n    }else if(scrubGate)scrubGate.gain.setTargetAtTime(0,cn,0.02);\n    pos=scrubPos;\n    if(view.sp<dur-1e-6&&(pos<view.s||pos>view.s+view.sp))setView(pos-view.sp\/2,view.sp);\n    frameOnce();\n  }\n  \/* ---------- Trim ---------- *\/\n  var unit='t';\n  function rs(t){return Math.round(t*sr)\/sr;}\n  function fN(n){return String(n).replace(\/\\B(?=(\\d{3})+(?!\\d))\/g,'.');}\n  function fU(t){return unit==='s'?fN(Math.round(t*sr)):fmtP(t,6);}\n  function fL(t){return unit==='s'?fN(Math.round(t*sr)):fmt(t,3);}\n  function parseU(v){\n    var s=String(v).trim();\n    if(unit==='s'&&(\/^[0-9]+$\/.test(s)||\/^[0-9]{1,3}([., _][0-9]{3})+$\/.test(s))){var n=parseInt(s.replace(\/[., _]\/g,''),10);return isFinite(n)?n\/sr:null;}\n    return parseT(s);\n  }\n  function unitUI(){\n    Array.prototype.forEach.call($$('.aew-un'),function(b){var on=b.getAttribute('data-u')===unit;b.classList.toggle('aew-on',on);b.setAttribute('aria-checked',on?'true':'false');});\n    root.classList.toggle('aew-smp',unit==='s');\n    if(buf){el.tt.textContent=fL(dur);trimUI();frameOnce();}\n    invalidate(true,true);\n  }\n  function trimUI(){\n    clampFades();\n    el.fs.value=fU(trimS);el.fe.value=fU(trimE);el.len.textContent=fU(trimE-trimS);\n    fadeUI();invalidate(true,true);\n  }\n  function onTrim(commit){\n    trimUI();scheduleMeasure();\n    if(commit)restart();\n  }\n  function commitField(which){\n    var inp=which==='s'?el.fs:el.fe,v=parseU(inp.value);\n    if(v==null||!buf){trimUI();return;}\n    v=rs(v);\n    edit(function(){if(which==='s')trimS=clamp(v,0,trimE-MIN);else trimE=clamp(v,trimS+MIN,dur);});\n    selActive=true;onTrim(true);\n  }\n  function setStartHere(){\n    if(!buf)return;var t=getPos();\n    if(t>trimE-MIN){say('Start must be before end.');return;}\n    edit(function(){trimS=Math.max(0,t);});selActive=true;onTrim(true);say('Start set to '+fU(trimS)+'.');\n  }\n  function setEndHere(){\n    if(!buf)return;var t=getPos();\n    if(t<trimS+MIN){say('End must be after start.');return;}\n    edit(function(){trimE=Math.min(dur,t);});selActive=true;onTrim(true);say('End set to '+fU(trimE)+'.');\n  }\n  \/* ---------- Pointer ---------- *\/\n  function ptr(e){var r=el.wave.getBoundingClientRect();return {x:e.clientX-r.left,y:e.clientY-r.top};}\n  function hitFade(){return '';}\n  function hitTrim(x,y){\n    if(y>24)return '';\n    var xs=X(trimS),xe=X(trimE),a=(xs<22?(x>=xs-3&&x<=xs+23):(x>=xs-23&&x<=xs+3)),b=(xe>W()-22?(x>=xe-23&&x<=xe+3):(x>=xe-3&&x<=xe+23));\n    if(a&&b)return x<(xs+xe)\/2?'s':'e';\n    return a?'s':(b?'e':'');\n  }\n  \/* cursor-position: magnetisk til markeringens ender (6 px), ellers SNAP (hvis aktiv), ellers pr\u00e6cis hvor musen er *\/\n  function cursorT(x){\n    var t=clamp(T(x),0,dur),xs=X(trimS),xe=X(trimE),ds=Math.abs(x-xs),de=Math.abs(x-xe);\n    if(ds<=6&&ds<=de)return trimS;\n    if(de<=6)return trimE;\n    return rs(snapT(t,8));\n  }\n  function dragMove(x,y){\n    if(touchDown&&!touchDown.armed&&drag!=='p'){\n      if(Math.hypot(x-touchDown.x,y-touchDown.y)<TOUCH_SLOP)return;\n      touchDown.armed=true;\n      if(drag==='tap'){tapPend=null;return;}\n      if(drag==='gr'&&grip){grip.x0=x;grip.t0=edgeT(grip.e);}\n      else if(drag==='crv'&&crv){crv.y0=y;}\n      else if(drag==='sg'&&sgDrag){sgDrag.x0=x;sgDrag.t0=T(x);}\n      else if(drag==='cur'){curOff=X(getPos())-x;}\n      else if(drag==='mk'){mkX0=x;mkY0=y;}\n    }\n    if(drag==='tap')return;\n    var t=clamp(T(x),0,dur),L=trimE-trimS;\n    if(drag==='s'||drag==='e')t=snapT(t,14,null,{noLR:true});\n    else if(drag==='sel')t=snapT(t,14,null,{noLR:linkOn});\n    else if(drag==='pt')t=snapT(t,14,null,{env:true,skipPt:dragPt});\n    if(drag==='s'||drag==='e'||drag==='sel')t=rs(t);\n    if(drag==='s'){trimS=clamp(t,0,trimE-MIN);onTrim(false);}\n    else if(drag==='e'){trimE=clamp(t,trimS+MIN,dur);onTrim(false);}\n    else if(drag==='sg'&&sgDrag){\n      if(!sgDrag.moved&&Math.abs(x-sgDrag.x0)<4)return;\n      sgDrag.moved=true;\n      var sl=sgDrag.b-sgDrag.a,cc=clamp(T(x),0,Math.max(0,dur-sl));\n      if(snapOn){\n        var s1=snapT(cc),s2=snapT(cc+sl)-sl,d1=Math.abs(s1-cc),d2=Math.abs(s2-cc),k1=d1>1e-9,k2=d2>1e-9;\n        if(k1&&(!k2||d1<=d2))cc=s1;else if(k2)cc=s2;\n        cc=clamp(cc,0,Math.max(0,dur-sl));\n      }\n      if(pasteMode==='over'&&cc>=sgDrag.b-1e-9)cc=Math.min(cc,Math.max(0,dur-2*sl));\n      sgDrag.c=cc;\n      sgDrag.noop=(cc<sgDrag.b-1e-9&&cc+sl>sgDrag.a+1e-9);\n      sgDrag.right=(cc>=sgDrag.b-1e-9);\n      invalidate(false,true);\n    }\n    else if(drag==='cur'){pLastX=x;pos=cursorT(x+curOff);frameOnce();}\n    else if(drag==='ct'&&ctDrag){\n      ctDel=(y<-26);\n      if(ctDel){ctDrag.moved=true;invalidate(false,true);return;}\n      if(!ctDrag.moved&&Math.abs(x-ctDrag.x0)<3)return;\n      ctDrag.moved=true;\n      var nt=clamp(T(x),0,dur);\n      if(snapOn)nt=snapT(nt,14,null,{skipCut:ctDrag.i});\n      if(pmode==='zc'){var zz=zcEdge(Math.round(nt*sr));nt=zz.i\/sr;}else nt=rs(nt);\n      var clo=(ctDrag.i>0?cuts[ctDrag.i-1]:0)+1\/sr,chi2=(ctDrag.i<cuts.length-1?cuts[ctDrag.i+1]:dur)-1\/sr;\n      cuts[ctDrag.i]=clamp(nt,clo,chi2);\n      invalidate(false,true);\n    }\n    else if(drag==='gr'&&grip){\n      if(shiftNow!==grip.fine){grip.fine=shiftNow;grip.x0=x;grip.t0=edgeT(grip.e);}\n      var gt=grip.t0+(T(x)-T(grip.x0))*(shiftNow?0.25:1);\n      if(!shiftNow&&snapOn)gt=snapT(gt,14,null,{noLR:true});\n      setEdge(grip.e,clamp(gt,0,dur));\n    }\n    else if(drag==='crv'&&crv){\n      if(!crv.moved&&Math.abs(y-crv.y0)<3)return;\n      crv.moved=true;\n      var ci=segIdx(crv.c,crv.n),arr=ED(crv.c).env;\n      if(ci<0)return;\n      var ca=arr[ci],cb=arr[ci+1],D=cb.db-ca.db;\n      if(Math.abs(D)<0.3)return;\n      var dy=y-crv.y0;if(shiftNow)dy*=0.25;\n      var target=yToDb(dbToY(crv.db0,crv.z)+dy,crv.z),m=clamp((target-ca.db)\/D,0.03,0.97);\n      if(Math.abs(m-0.5)<0.03)m=0.5;\n      delete ca.sc;if(m===0.5)delete ca.k;else ca.k=Math.log(m)\/Math.log(0.5);\n      envChanged();\n    }\n    else if(drag==='pt'&&dragPt){dragPt.t=t;dragPt.db=snapDb(yToDb(y,zoneOf(dragCh)));sortEnv(dragCh);envChanged();}\n    else if(drag==='sel'){\n      if(Math.abs(x-selX)>2)selMoved=true;\n      if(selMoved){\n        var lo=Math.min(selA,t),hi=Math.max(selA,t);\n        if(hi-lo<MIN){if(lo+MIN<=dur)hi=lo+MIN;else lo=hi-MIN;}\n        if(linkOn){trimS=Math.max(0,lo);trimE=Math.min(dur,hi);selActive=true;onTrim(false);}\n        else{selR={a:Math.max(0,lo),b:Math.min(dur,hi)};invalidate(true,true);}\n      }\n    }\n    else if(drag==='mk'&&dragMk){\n      var mkh2=Math.abs(x-mkX0)>=4;\n      if(!mkMoved&&!mkh2&&Math.abs(y-mkY0)<4)return;\n      mkMoved=true;\n      if(mkh2||mkHMoved){mkHMoved=true;dragMk.t=snapT(t,14,dragMk);}\n      mkDelPend=(y<-26);invalidate(false,true);\n    }\n    else if(drag==='mv'){\n      if(!mvMoved&&Math.abs(x-mvX0)<4)return;\n      mvMoved=true;\n      var ln=trimE-trimS,ns=clamp(T(x)-mvOff,0,dur-ln);\n      if(snapOn){\n        var s1=snapT(ns,14,null,{noLR:true}),e1=snapT(ns+ln,14,null,{noLR:true})-ln,ds=Math.abs(s1-ns),de=Math.abs(e1-ns);\n        if(s1!==ns||e1!==ns)ns=(s1!==ns&&(e1===ns||ds<=de))?s1:e1;\n        ns=clamp(ns,0,dur-ln);\n      }\n      trimS=ns;trimE=Math.min(dur,ns+ln);onTrim(false);\n    }\n    else{\n      pLastX=x;\n      if(!pMoved&&Math.abs(x-pX0)<4)return;\n      pMoved=true;scrubTgt=clamp(scrubP0+(T(x)-scrubX0)*SCR_GEAR,0,dur);\n    }\n  }\n  \/* to fingre (pinch) zoomer trinl\u00f8st og f\u00f8lger fingrenes midte *\/\n  var ptrs={},pinch=null,noDrag=false,curOff=0;\n  function ptrCount(){return Object.keys(ptrs).length;}\n  function pinchStart(){\n    var ks=Object.keys(ptrs),a=ptrs[ks[0]],b=ptrs[ks[1]];\n    if(drag){\n      if(drag==='p')scrubStop();\n      drag=null;dragPt=null;dragMk=null;sgDrag=null;pend=null;wasPlaying=false;rulHot=0;\n    }\n    touchDown=null;tapPend=null;\n    pinch={d0:Math.max(8,Math.abs(a.x-b.x)),sp0:view.sp,tc:T((a.x+b.x)\/2)};\n    noDrag=true;invalidate(false,true);\n  }\n  function pinchMove(){\n    var ks=Object.keys(ptrs);if(ks.length<2||!pinch)return;\n    var a=ptrs[ks[0]],b=ptrs[ks[1]],d=Math.max(8,Math.abs(a.x-b.x)),xm=(a.x+b.x)\/2;\n    var sp=clamp(pinch.sp0*pinch.d0\/d,Math.min(dur,32\/sr),dur);\n    setView(pinch.tc-xm\/W()*sp,sp);\n  }\n  function ptrUp(e){\n    delete ptrs[e.pointerId];\n    if(pinch&&ptrCount()<2)pinch=null;\n    if(!ptrCount())noDrag=false;\n    endDrag();\n  }\n  el.wave.addEventListener('pointerdown',function(e){\n    if(!buf||e.button>0)return;\n    if(el.ptp&&!el.ptp.hidden)el.ptp.hidden=true;\n    var p=ptr(e),x=p.x,y=p.y,h;\n    ptrs[e.pointerId]={x:x,y:y};\n    if(ptrCount()>=2){e.preventDefault();if(!pinch)pinchStart();return;}\n    if(noDrag)return;\n    touchDown=(e.pointerType==='touch')?{x:x,y:y,armed:false}:null;tapPend=null;\n    try{el.wave.setPointerCapture(e.pointerId);}catch(_){}\n    try{el.wave.focus({preventScroll:true});}catch(_){}\n    wasPlaying=false;selMk=null;\n    if(segSel&&tool!=='mv'){segSel=null;invalidate(true,true);}\n    if(e.shiftKey){pend=snap();drag='sel';selShift=true;selA=rs(snapT(clamp(T(x),0,dur),14,null,{noLR:linkOn}));selX=x;selMoved=false;e.preventDefault();return;}\n    var mkh=hitMarker(x,y);\n    if(mkh){pend=snap();drag='mk';dragMk=mkh;selMk=mkh;mkMoved=false;mkDelPend=false;mkHMoved=false;mkX0=x;mkY0=y;el.wave.style.cursor='grabbing';invalidate(false,true);e.preventDefault();return;}\n    var altSplit=e.altKey&&chN>1&&!splitCh;\n    h=hitTrim(x,y);\n    if(h){pend=snap();drag=h;dragMove(x,y);e.preventDefault();return;}\n    if(tool!=='env'&&tool!=='scrub'){\n      var chi=hitCutHandle(x,y);\n      if(chi>=0){pend=snap();drag='ct';ctDrag={i:chi,x0:x,moved:false};segSel=null;hovCut=chi;el.wave.style.cursor='grabbing';invalidate(true,true);e.preventDefault();return;}\n    }\n    var gr=hitGrip(x,y);\n    if(gr){\n      pend=snap();drag='gr';gripAct=gr;grip={e:gr,x0:x,t0:edgeT(gr),fine:shiftNow};\n      invalidate(false,true);e.preventDefault();return;\n    }\n    gripAct=null;\n    if(tool==='sel'&&Math.abs(x-X(getPos()))<=5){\n      drag='cur';curOff=X(getPos())-x;\n      if(playing){wasPlaying=true;pause();}\n      pLastX=x;frameOnce();e.preventDefault();return;\n    }\n    if(y<RUL&&x>=X(trimS)&&x<=X(trimE)){\n      pend=snap();drag='mv';mvOff=T(x)-trimS;mvX0=x;mvT0=T(x);mvMoved=false;rulHot=2;\n      el.wave.style.cursor='grabbing';invalidate(false,true);e.preventDefault();return;\n    }\n    if(tool==='cut'&&y>=RUL){if(touchDown){drag='tap';tapPend={k:'cut',x:x,y:y};e.preventDefault();return;}cutClick(x);e.preventDefault();return;}\n    if(tool==='mv'&&y>=RUL){\n      var sg=segAt(T(x));\n      pend=snap();\n      segSel={a:sg.a,b:sg.b};invalidate(true,true);\n      drag='sg';sgDrag={a:sg.a,b:sg.b,x0:x,t0:T(x),c:sg.a,moved:false};\n      el.wave.style.cursor='grabbing';invalidate(false,true);e.preventDefault();return;\n    }\n    if(tool==='env'&&y>=RUL){\n      var sbi=hitShapeBar(x,y);\n      if(sbi>=0){applyShape(sbi);e.preventDefault();return;}\n      var hmid=hitMid(x,y);\n      if(hmid&&!hitPt(x,y)){\n        pend=snap();selSeg={c:hmid.c,n:hmid.n};selPt=null;\n        drag='crv';crv={c:hmid.c,n:hmid.n,y0:y,db0:segMid(hmid.c,hmid.i,hmid.z).db,z:hmid.z,moved:false};\n        envUI();invalidate(false,true);e.preventDefault();return;\n      }\n      selSeg=null;\n      if(touchDown&&!hitPt(x,y)){drag='tap';tapPend={k:'envadd',x:x,y:y};e.preventDefault();return;}\n      pend=snap();\n      var hp=hitPt(x,y),ec=hp?hp.c:laneAt(y),pp=null;\n      if(altSplit){setSplitRaw(true);if(playing)restart();}\n      if(hp)pp=ED(ec).env.filter(function(q){return q.n===hp.p.n;})[0]||null;\n      if(!pp)pp=addPt(snapT(T(x),14,null,{env:true}),yToDb(y,zoneOf(ec)),ec);\n      selPt=pp;selCh=ec;dragPt=pp;dragCh=ec;drag='pt';envChanged();e.preventDefault();return;\n    }\n    if(tool==='scrub'){\n      drag='p';selActive=false;\n      if(playing){wasPlaying=true;pause();}\n      var ct=cursorT(x);pX0=x;pLastX=x;pMoved=false;\n      scrubStart(ct,x);pos=ct;frameOnce();e.preventDefault();return;\n    }\n    pend=snap();drag='sel';selShift=false;selA=rs(snapT(clamp(T(x),0,dur),14,null,{noLR:linkOn}));selX=x;selMoved=false;\n    if(touchDown){tapPend={k:'seek',x:x,y:y};}else{selActive=false;seekTo(cursorT(x));}\n    e.preventDefault();\n  });\n  el.wave.addEventListener('pointermove',function(e){\n    if(!buf)return;\n    var p=ptr(e);\n    if(ptrs[e.pointerId]){ptrs[e.pointerId]={x:p.x,y:p.y};if(pinch){pinchMove();return;}}\n    if(e.altKey!==altPrev){altPrev=e.altKey;invalidate(false,true);}\n    shiftNow=e.shiftKey;\n    if(drag){dragMove(p.x,p.y);return;}\n    var g2=hitGrip(p.x,p.y);if(g2!==gripHov){gripHov=g2;invalidate(false,true);}\n    var hc=(tool!=='env'&&tool!=='scrub')?hitCutHandle(p.x,p.y):-1;if(hc!==hovCut){hovCut=hc;invalidate(false,true);}\n    if(tool==='env'){var hm3=hitMid(p.x,p.y),nh=hm3?{c:hm3.c,n:hm3.n}:null;if((nh&&(!hovSeg||hovSeg.c!==nh.c||hovSeg.n!==nh.n))||(!nh&&hovSeg)){hovSeg=nh;invalidate(false,true);}}\n    var c='default';\n    if(e.shiftKey)c='crosshair';\n    else if(hitTrim(p.x,p.y))c='ew-resize';\n    else if(tool!=='env'&&tool!=='scrub'&&hitCutHandle(p.x,p.y)>=0)c='ew-resize';\n    else if(tool==='env'&&p.y>=RUL)c=hitPt(p.x,p.y)?'move':(hitMid(p.x,p.y)||hitShapeBar(p.x,p.y)>=0?'ns-resize':'crosshair');\n    else if(tool==='cut'&&p.y>=RUL)c='crosshair';\n    else if(tool==='mv'&&p.y>=RUL)c='grab';\n    else if(tool==='scrub'&&p.y>=RUL)c='col-resize';\n    else if(hitGrip(p.x,p.y))c='ew-resize';\n    else if(tool==='sel'&&Math.abs(p.x-X(getPos()))<=5)c='ew-resize';\n    var hot=(!e.shiftKey&&p.y<RUL&&p.x>=X(trimS)&&p.x<=X(trimE)&&!hitTrim(p.x,p.y))?1:0;\n    if(hot||hitMarker(p.x,p.y))c='grab';\n    if(tool==='cut'&&p.y>=RUL&&!hitMarker(p.x,p.y)){var ch2=cutSnapTime(T(p.x));if(ch2!==cutHover){cutHover=ch2;invalidate(false,true);}}\n    else if(cutHover>=0){cutHover=-1;invalidate(false,true);}\n    if(tool==='mv'&&p.y>=RUL&&!hitMarker(p.x,p.y)){var sh=segAt(T(p.x));if(!sgHover||sgHover.a!==sh.a||sgHover.b!==sh.b){sgHover=sh;invalidate(false,true);}}\n    else if(sgHover){sgHover=null;invalidate(false,true);}\n    if(hot!==rulHot){rulHot=hot;invalidate(false,true);}\n    el.wave.style.cursor=c;\n  });\n  function endDrag(){\n    if(!drag)return;\n    var d=drag;drag=null;dragPt=null;touchDown=null;\n    if(d==='tap'){\n      var tp=tapPend;tapPend=null;\n      if(tp&&tp.k==='cut')cutClick(tp.x);\n      else if(tp&&tp.k==='envadd'){\n        selSeg=null;pend=snap();\n        var ecx=laneAt(tp.y),ppx=addPt(snapT(T(tp.x),14,null,{env:true}),yToDb(tp.y,zoneOf(ecx)),ecx);\n        selPt=ppx;selCh=ecx;envChanged();\n      }\n    }\n    if(d==='mv'){rulHot=0;el.wave.style.cursor='default';}\n    if(d==='cur'){if(wasPlaying)play();else frameOnce();}\n    else if(d==='p'){var scp=scrubPos;scrubStop();if(pMoved)pos=scp;if(wasPlaying)play();else frameOnce();}\n    else if(d==='s'||d==='e'){selActive=true;onTrim(true);}\n    else if(d==='mv'){if(mvMoved){selActive=true;onTrim(true);}else{selActive=false;seekTo(cursorT(mvX0));}}\n    else if(d==='mk'){\n      el.wave.style.cursor='default';\n      if(mkDelPend&&dragMk){var di=markers.indexOf(dragMk);if(di>=0)markers.splice(di,1);selMk=null;}\n      else if(!mkMoved&&dragMk)toLoopPoint(dragMk.t);\n      mkDelPend=false;dragMk=null;mkUI();\n    }\n    else if(d==='sg'){var sd=sgDrag;sgDrag=null;el.wave.style.cursor='grab';if(sd&&sd.moved)mvSegment(sd.a,sd.b,sd.c);}\n    else if(d==='sel'){\n      if(!selMoved&&tapPend&&tapPend.k==='seek'){selActive=false;seekTo(cursorT(tapPend.x));}\n      tapPend=null;\n      if(selMoved){\n        if(linkOn){\n          selActive=true;onTrim(true);\n          if(!playing){pos=trimS;frameOnce();}\n          say('Region selected: '+fmt(trimS,3)+' \u2013 '+fmt(trimE,3)+'.');\n        }else if(selR&&!playing){pos=selR.a;frameOnce();}\n      }\n    }\n    else if(d==='ct'){\n      var cd=ctDrag,cdel=ctDel;ctDrag=null;ctDel=false;hovCut=-1;el.wave.style.cursor='default';\n      if(cd&&cdel&&cd.i<cuts.length){cuts.splice(cd.i,1);segSel=null;cutBtnUI();say('Split removed.');}\n      else if(cd&&!cd.moved&&tool==='cut')cutClick(cd.x0);\n      invalidate(true,true);\n    }\n    else if(d==='gr'){grip=null;if(linkOn&&selActive)onTrim(true);else invalidate(true,true);}\n    else if(d==='fi'||d==='fo'){scheduleFx();}\n    else if(d==='crv'){crv=null;invalidate(false,true);}\n    if(pend){if(!same(pend,snap()))pushHist(pend);pend=null;}\n    wasPlaying=false;invalidate(false,true);\n  }\n  el.wave.addEventListener('pointerup',ptrUp);\n  el.wave.addEventListener('pointercancel',ptrUp);\n  el.wave.addEventListener('pointerleave',function(){if(rulHot&&!drag){rulHot=0;invalidate(false,true);}if(!drag&&(cutHover>=0||sgHover)){cutHover=-1;sgHover=null;invalidate(false,true);}});\n  el.wave.addEventListener('dblclick',function(e){\n    if(!buf)return;\n    var pm=ptr(e),gd=hitGrip(pm.x,pm.y);\n    if(gd){openGripInput(gd);return;}\n    var mk2=hitMarker(pm.x,pm.y);\n    if(mk2){mkDel(mk2);return;}\n    if(tool!=='env')return;\n    var p=ptr(e),hp=hitPt(p.x,p.y),hm4=hitMid(p.x,p.y);\n    if(hm4&&!hp){edit(function(){var a=ED(hm4.c).env[hm4.i];delete a.k;delete a.sc;});envChanged();return;}\n    if(hp){edit(function(){var arr=ED(hp.c).env,ix=arr.indexOf(hp.p);if(ix>=0)arr.splice(ix,1);if(selPt===hp.p)selPt=null;});envChanged();}\n  });\n  function wheelPx(e){var d=e.deltaY;if(e.deltaMode===1)d*=16;else if(e.deltaMode===2)d*=400;return d;}\n  el.wave.addEventListener('wheel',function(e){\n    if(!buf)return;\n    var r=el.wave.getBoundingClientRect(),dy=wheelPx(e);\n    if(e.altKey){e.preventDefault();zoomV(Math.exp(-dy*0.002));return;}\n    if(!e.ctrlKey&&!e.metaKey&&(e.shiftKey||Math.abs(e.deltaX)>Math.abs(e.deltaY))){\n      if(view.sp<dur-1e-6){e.preventDefault();setView(view.s+(e.deltaX||e.deltaY)\/W()*view.sp,view.sp);}\n      return;\n    }\n    e.preventDefault();\n    zoomAt(Math.exp(dy*((e.ctrlKey||e.metaKey)?0.005:0.002)),T(e.clientX-r.left));\n  },{passive:false});\n  el.wave.addEventListener('keydown',function(e){\n    if(!buf)return;var k=e.key;\n    if(k==='i'||k==='I'){e.preventDefault();setStartHere();}\n    else if(k==='o'||k==='O'){e.preventDefault();setEndHere();}\n    else if(k==='e'||k==='E'){e.preventDefault();setTool(tool==='env'?'sel':'env');}\n    else if(k==='Enter'&&tool==='env'&&selPt){e.preventDefault();epOpen();}\n    else if(k==='Delete'||k==='Backspace'){e.preventDefault();if(selMk)mkDel(selMk);else if(selPt)delSel();else if(tool!=='env')removeSel(false);}\n    else if(k==='Home'){e.preventDefault();setIP(trimS);if(playing)seekTo(trimS);else{pos=trimS;frameOnce();}}\n    else if((k==='ArrowLeft'||k==='ArrowRight')&&gripAct&&selEdges()){\n      e.preventDefault();\n      var gs=e.altKey?1\/sr:(e.shiftKey?0.01:0.001),ge=gripAct;\n      edit(function(){setEdge(ge,edgeT(ge)+(k==='ArrowLeft'?-1:1)*gs);});\n      if(linkOn)selActive=true;\n      invalidate(false,true);\n    }\n    else if(k==='ArrowLeft'||k==='ArrowRight'){e.preventDefault();var stp=e.altKey?1\/sr:(e.shiftKey?1:0.01);nudgeIP((k==='ArrowLeft'?-1:1)*stp);}\n  });\n  \/* ---------- Historik (3 niveauer), reverse ---------- *\/\n  var HMAX=30;\n  function snap(){return {src:srcRuns.slice(),s:trimS,e:trimE,sp:splitCh,c:[cpCh(CH[0]),cpCh(CH[1])],mk:markers.map(function(m){return {n:m.n,t:m.t};}),ct:cuts.slice(),sl:selR?{a:selR.a,b:selR.b}:null};}\n  function same(a,b){\n    if(a.s!==b.s||a.e!==b.e||a.sp!==b.sp||a.mk.length!==b.mk.length||a.ct.length!==b.ct.length)return false;\n    if(!!a.sl!==!!b.sl||(a.sl&&(a.sl.a!==b.sl.a||a.sl.b!==b.sl.b)))return false;\n    var n=a.sp?2:1,k,i;\n    for(i=0;i<a.ct.length;i++)if(a.ct[i]!==b.ct[i])return false;\n    for(i=0;i<a.mk.length;i++)if(a.mk[i].n!==b.mk[i].n||a.mk[i].t!==b.mk[i].t)return false;\n    for(k=0;k<n;k++){\n      var x=a.c[k],y=b.c[k];\n      if(x.fi!==y.fi||x.fo!==y.fo||x.env.length!==y.env.length)return false;\n      for(i=0;i<x.env.length;i++)if(x.env[i].t!==y.env[i].t||x.env[i].db!==y.env[i].db||x.env[i].k!==y.env[i].k||x.env[i].sc!==y.env[i].sc)return false;\n    }\n    return true;\n  }\n  var redoStack=[],redoMode=false;\n  function pushHist(st,op){hl=null;hlx=null;redoStack=[];hist.push({st:st,op:op||null});while(hist.length>HMAX)hist.shift();histUI();}\n  function histUI(){\n    var n=redoMode?redoStack.length:hist.length;\n    el.ulab.textContent=redoMode?'REDO':'UNDO';\n    el.undo.disabled=!n;el.ucnt.textContent=n?String(n):'';\n  }\n  function edit(fn){var a=snap();fn();if(!same(a,snap()))pushHist(a);}\n  function reverseSamples(s0,s1){\n    for(var c=0;c<buf.numberOfChannels;c++){\n      var d=buf.getChannelData(c),i=s0,j=s1-1,t;\n      while(i<j){t=d[i];d[i]=d[j];d[j]=t;i++;j--;}\n    }\n  }\n  function rebuildAfterEdit(){\n    buildBins();computeSnap();\n    kw=null;kwId++;applyGain(true);\n  }\n  function doReverse(){\n    if(!buf)return;\n    var rr=selSamples(),s0=rr[0],s1=rr[1],qq=selSec();\n    if(s1-s0<2)return;\n    var was=playing,p=getPos();\n    if(was)pause();\n    pushHist(snap(),{type:'rev',s0:s0,s1:s1});\n    reverseSamples(s0,s1);srcRuns=srcInsRuns(srcDelRuns(srcRuns,s0,s1),s0,srcSlice(srcRuns,s0,s1).reverse());\n    pos=clamp(qq[0]+qq[1]-p,qq[0],qq[1]);\n    rebuildAfterEdit();\n    if(was)play();else frameOnce();\n    say('Selected region reversed.');\n  }\n  \/* markerer det, Undo\/Redo lige har rykket: kurven, markers, klip og envelope-punkter lyser orange *\/\n  function stDiff(from,to){\n    var mk=[],ct=[],ev=[],e=0.5\/sr,k;\n    to.mk.forEach(function(m){var f=from.mk.filter(function(x){return x.n===m.n;})[0];if(!f||Math.abs(f.t-m.t)>1e-9)mk.push(m.n);});\n    (to.ct||[]).forEach(function(c){if(!(from.ct||[]).some(function(x){return Math.abs(x-c)<e;}))ct.push(c);});\n    for(k=0;k<2;k++)(to.c[k]?to.c[k].env:[]).forEach(function(p){var f=(from.c[k]?from.c[k].env:[]).filter(function(x){return x.n===p.n;})[0];if(!f||f.t!==p.t||f.db!==p.db||f.k!==p.k||f.sc!==p.sc)ev.push(p.n);});\n    return {mk:mk,ct:ct,ev:ev};\n  }\n  function setUndoMarks(reg,line,from,to){\n    var d=stDiff(from,to),ln=line;\n    hl=null;\n    if(reg&&reg[1]-reg[0]>=1)hl={s:reg[0]\/sr,e:reg[1]\/sr};\n    else if(reg&&ln==null)ln=reg[0]\/sr;\n    hlx=(d.mk.length||d.ct.length||d.ev.length||ln!=null)?{mk:d.mk,ct:d.ct,ev:d.ev,line:ln}:null;\n    invalidate(true,true);\n  }\n  function undo(){\n    if(!buf||!hist.length||drag)return;\n    var e=hist.pop(),was=playing,o=e.op,rd={st:snap(),op:null,entry:e},c,reg=null,line=null;\n    hl=null;hlx=null;selActive=false;\n    if(was)pause();\n    if(o){\n      if(o.type==='rev'){reverseSamples(o.s0,o.s1);rd.op={type:'rev',s0:o.s0,s1:o.s1};reg=[o.s0,o.s1];}\n      else if(o.type==='ins'){undeclick(o.svB);undeclick(o.svA);rd.op={type:'ins',at:o.at,data:deleteSamples(o.at,o.at+o.len)};line=o.at\/sr;}\n      else if(o.type==='del'){\n        var post=null;\n        if(o.sv){\n          post={L:[],R:[]};\n          for(c=0;c<buf.numberOfChannels;c++){var dd=buf.getChannelData(c);post.L.push(dd.slice(o.sv.at-o.sv.xf,o.sv.at));post.R.push(dd.slice(o.sv.at,o.sv.at+o.sv.R[c].length));}\n        }\n        undeclick(o.sv);insertSamples(o.at,o.data);\n        rd.op={type:'del',at:o.at,len:o.data[0].length,post:post,sv:o.sv};reg=[o.at,o.at+o.data[0].length];\n      }\n      else if(o.type==='rep'){undeclick(o.svB);undeclick(o.svA);rd.op={type:'rep',at:o.at,oldLen:o.old[0].length,data:replaceSamples(o.at,o.newLen,o.old),mv:o.mv,crop:o.crop};reg=o.mv?[o.mv.a,o.mv.b]:(o.crop?[o.crop.s0,o.crop.s1]:[o.at,o.at+o.old[0].length]);}\n      else if(o.type==='inv'){invertSamples(o.s0,o.s1);rd.op={type:'inv',s0:o.s0,s1:o.s1};reg=[o.s0,o.s1];}\n      else if(o.type==='gain'){mulSamples(o.s0,o.s1,1\/o.g);rd.op={type:'gain',s0:o.s0,s1:o.s1,g:o.g};reg=[o.s0,o.s1];}\n      else if(o.type==='sil'){for(c=0;c<buf.numberOfChannels;c++)buf.getChannelData(c).set(o.data[c],o.s0);rd.op={type:'sil',s0:o.s0,s1:o.s1};reg=[o.s0,o.s1];}\n      else if(o.type==='mono'){\n        var nb2=ctx.createBuffer(2,buf.length,sr);\n        if(o.keep===2){nb2.getChannelData(0).set(o.other[0]);nb2.getChannelData(1).set(o.other[1]);}\n        else{nb2.getChannelData(o.keep).set(buf.getChannelData(0));nb2.getChannelData(1-o.keep).set(o.other);}\n        setBuffer(nb2);chN=2;rd.op={type:'mono',keep:o.keep};\n      }\n    }\n    redoStack.push(rd);while(redoStack.length>HMAX)redoStack.shift();\n    applyState(e.st);\n    if(o&&o.type==='mono')chanUI(true);\n    histUI();\n    if(o){afterStruct();}else{envUI();trimUI();scheduleMeasure();}\n    pos=clamp(pos,trimS,trimE);\n    setUndoMarks(reg,line,rd.st,e.st);\n    if(was)play();else frameOnce();\n    say('Undone.');\n  }\n  function applyState(st){\n    trimS=st.s;trimE=st.e;splitCh=!!st.sp&&chN>1;CH=[cpCh(st.c[0]),cpCh(st.c[1])];selPt=null;dragPt=null;splitUI();\n    markers=st.mk.map(function(m){return {n:m.n,t:m.t};});selMk=null;mkUI();cuts=(st.ct||[]).slice();if(st.src)srcRuns=st.src.slice();sgHover=null;segSel=null;selR=st.sl?{a:st.sl.a,b:st.sl.b}:null;\n  }\n  function redo(){\n    if(!buf||!redoStack.length||drag)return;\n    var r=redoStack.pop(),e=r.entry,o=r.op,was=playing,c,reg=null,line=null,pre=snap();\n    hl=null;hlx=null;selActive=false;\n    if(was)pause();\n    if(o){\n      if(o.type==='rev'){reverseSamples(o.s0,o.s1);reg=[o.s0,o.s1];}\n      else if(o.type==='ins'){insertSamples(o.at,o.data);reg=[o.at,o.at+o.data[0].length];}\n      else if(o.type==='del'){\n        deleteSamples(o.at,o.at+o.len);line=o.at\/sr;\n        if(o.post&&o.sv){for(c=0;c<buf.numberOfChannels;c++){var d=buf.getChannelData(c);d.set(o.post.L[c],o.sv.at-o.sv.xf);d.set(o.post.R[c],o.sv.at);}}\n      }\n      else if(o.type==='rep'){replaceSamples(o.at,o.oldLen,o.data);reg=o.mv?[o.mv.d,o.mv.d+o.mv.m]:(o.crop?null:[o.at,o.at+o.data[0].length]);}\n      else if(o.type==='inv'){invertSamples(o.s0,o.s1);reg=[o.s0,o.s1];}\n      else if(o.type==='gain'){mulSamples(o.s0,o.s1,o.g);reg=[o.s0,o.s1];}\n      else if(o.type==='sil'){for(c=0;c<buf.numberOfChannels;c++)buf.getChannelData(c).fill(0,o.s0,o.s1);reg=[o.s0,o.s1];}\n      else if(o.type==='mono'){monoConvert(o.keep);}\n    }\n    applyState(r.st);\n    if(o&&o.type==='mono')chanUI();\n    hist.push(e);histUI();\n    if(o){afterStruct();}else{envUI();trimUI();scheduleMeasure();}\n    pos=clamp(pos,trimS,trimE);\n    setUndoMarks(reg,line,pre,r.st);\n    if(was)play();else frameOnce();\n  }\n  function silenceSel(){\n    if(!buf||drag)return;\n    var r=selSamples(),s0=r[0],s1=r[1];\n    if(s1-s0<1)return;\n    var was=playing,p=getPos(),data=[],c;\n    if(was)pause();\n    for(c=0;c<buf.numberOfChannels;c++)data.push(buf.getChannelData(c).slice(s0,s1));\n    pushHist(snap(),{type:'sil',s0:s0,s1:s1,data:data});\n    for(c=0;c<buf.numberOfChannels;c++)buf.getChannelData(c).fill(0,s0,s1);\n    rebuildAfterEdit();\n    pos=p;\n    if(was)play();else frameOnce();\n  }\n  \/* ---------- Resample (r\u00e5, aliaset) + Pitch ---------- *\/\n  function keyNow(){var q=selSec();return editRev+'|'+q[0]+'|'+q[1]+'|'+pitchSemi.toFixed(3);}\n  function replaceSamples(at,oldLen,data){\n    var nc=buf.numberOfChannels,m=data[0].length,nb=ctx.createBuffer(nc,buf.length-oldLen+m,sr),rem=[],c;\n    for(c=0;c<nc;c++){\n      var s=buf.getChannelData(c),dst=nb.getChannelData(c);\n      rem.push(s.slice(at,at+oldLen));\n      dst.set(s.subarray(0,at),0);dst.set(data[c],at);dst.set(s.subarray(at+oldLen),at+m);\n    }\n    setBuffer(nb);return rem;\n  }\n  \/* lo-fi: samplerate (hold) og bitdybde (afrunding, evt. med TPDF-dither). bits: 0 = u\u00e6ndret, hz: 0 = u\u00e6ndret *\/\n  function lofiProcess(chs,n,hz,bits,dith){\n    var out=[],c,i,ratio=(hz>0&&hz<sr)?sr\/hz:0,L=bits>0?Math.pow(2,bits-1):0,top=L?(L-1)\/L:0;\n    for(c=0;c<chs.length;c++){\n      var s=chs[c],o=new Float32Array(n),x,idx;\n      for(i=0;i<n;i++){\n        if(ratio){idx=Math.round(Math.floor(i\/ratio)*ratio);if(idx>=n)idx=n-1;x=s[idx];}else x=s[i];\n        if(L){\n          if(dith)x+=(Math.random()-Math.random())\/L;\n          x=Math.round(x*L)\/L;\n          if(x>top)x=top;else if(x<-1)x=-1;\n        }\n        o[i]=x;\n      }\n      out.push(o);\n    }\n    return out;\n  }\n  function resampleSel(hz,bits,dith){\n    if(!buf||drag)return;\n    var rate=(hz>0&&hz<sr)?hz:0;\n    if(!rate&&!(bits>0))return;\n    var r=selSamples(),s0=r[0],s1=r[1],n=s1-s0;\n    if(n<2)return;\n    var was=playing,p=getPos();\n    if(was)pause();\n    var nc=buf.numberOfChannels,chs=[],c;\n    for(c=0;c<nc;c++)chs.push(buf.getChannelData(c).subarray(s0,s1));\n    var out=lofiProcess(chs,n,rate,bits,dith);\n    var st=snap(),old=replaceSamples(s0,n,out);\n    pushHist(st,{type:'rep',at:s0,old:old,newLen:n});\n    afterStruct();\n    pos=clamp(p,0,dur);\n    if(was)play();else frameOnce();\n  }\n  function resampleCubic(chs,step,m){\n    var out=[],c,j;\n    for(c=0;c<chs.length;c++){\n      var a=chs[c],L=a.length,o=new Float32Array(m);\n      for(j=0;j<m;j++){\n        var x=j*step,i=Math.floor(x),f=x-i;\n        var p0=a[i-1<0?0:Math.min(i-1,L-1)],p1=a[i<L?i:L-1],p2=a[i+1<L?i+1:L-1],p3=a[i+2<L?i+2:L-1];\n        o[j]=p1+0.5*f*(p2-p0+f*(2*p0-5*p1+4*p2-p3+f*(3*(p1-p2)+p3-p0)));\n      }\n      out.push(o);\n    }\n    return out;\n  }\n  \/* WSOLA tidsstr\u00e6kning (bevarer toneh\u00f8jde), l\u00e6ngde = n*ratio *\/\n  async function wsola(chs,n,ratio){\n    var nc=chs.length,win=Math.max(256,Math.round(sr*0.04)&~1),hopS=win>>1,hopA=hopS\/ratio,tol=Math.round(sr*0.012);\n    var outLen=Math.max(1,Math.round(n*ratio)),nf=Math.ceil(outLen\/hopS)+1,out=[],c,i,j,k;\n    for(c=0;c<nc;c++)out.push(new Float32Array(outLen+win));\n    var hann=new Float32Array(win);for(i=0;i<win;i++)hann[i]=0.5-0.5*Math.cos(2*Math.PI*i\/win);\n    var mono=new Float32Array(n);\n    for(i=0;i<n;i++){var s=0;for(c=0;c<nc;c++)s+=chs[c][i];mono[i]=s\/nc;}\n    var prev=0,SC=4;\n    function score(cand,nat){\n      var sc=0,e=0,a,b;\n      for(var q=0;q<win;q+=SC){a=mono[cand+q];b=(nat+q<n)?mono[nat+q]:0;sc+=a*b;e+=a*a;}\n      return sc\/Math.sqrt(e+1e-9);\n    }\n    for(k=0;k<nf;k++){\n      var outPos=k*hopS,cand=0;\n      if(k>0){\n        var tgt=Math.round(k*hopA),nat=prev+hopS,lo=Math.max(0,tgt-tol),hi=Math.min(n-win,tgt+tol);\n        if(hi<lo)cand=Math.max(0,Math.min(n-win,tgt));\n        else{\n          var best=-1e30,bc=lo,v;\n          for(c=lo;c<=hi;c+=2){v=score(c,nat);if(v>best){best=v;bc=c;}}\n          for(c=Math.max(lo,bc-1);c<=Math.min(hi,bc+1);c++){v=score(c,nat);if(v>best){best=v;bc=c;}}\n          cand=bc;\n        }\n      }\n      prev=cand;\n      for(c=0;c<nc;c++){\n        var src=chs[c],dst=out[c];\n        for(j=0;j<win;j++){var idx=cand+j;if(idx<n)dst[outPos+j]+=src[idx]*hann[j];}\n      }\n      if((k&31)===0)await tick();\n    }\n    return out.map(function(a){return a.slice(0,outLen);});\n  }\n  async function pitchLock(chs,rate){\n    var n=chs[0].length,st=await wsola(chs,n,rate);\n    return resampleCubic(st,rate,n);\n  }\n  function lockMin(){return Math.round(sr*0.12);}\n  async function ensurePitched(){\n    if(pBuf&&pBuf.key===keyNow())return true;\n    var rev=editRev,key=keyNow(),r=selSamples(),s0=r[0],s1=r[1],n=s1-s0,rate=Math.pow(2,pitchSemi\/12);\n    if(n<lockMin()){say('Selection too short for KEEP LENGTH.');return false;}\n    say('Rendering \u2026');\n    var chs=[],c;\n    for(c=0;c<chN;c++)chs.push(buf.getChannelData(c).slice(s0,s1));\n    var out=await pitchLock(chs,rate);\n    if(rev!==editRev){say('Cancelled: audio changed.',true);return false;}\n    var nb=ctx.createBuffer(chN,n,sr);\n    for(c=0;c<chN;c++)nb.getChannelData(c).set(out[c]);\n    pBuf={key:key,buf:nb};say('');\n    return true;\n  }\n  async function pitchPlay(){\n    if(!buf||pBusy)return;\n    if(playing){pause();return;}\n    selOnly=true;\n    var neutral=Math.abs(pitchSemi)<0.005;\n    if(neutral){playMode='norm';playRate=1;play();return;}\n    if(pitchMode==='vari'){playMode='vari';playRate=Math.pow(2,pitchSemi\/12);play();return;}\n    pBusy=true;\n    try{\n      if(await ensurePitched()){playMode='lock';playRate=1;play();}\n    }finally{pBusy=false;}\n  }\n  function pitchLive(){\n    if(!playing)return;\n    if(playMode==='vari'&&pitchMode==='vari'){\n      var p=getPos();\n      playRate=Math.pow(2,pitchSemi\/12);\n      p0=p;t0=ctx.currentTime;curRate=playRate;\n      if(src&&src.playbackRate)src.playbackRate.value=playRate;\n      scheduleFx();\n    }else if(playMode==='lock'){\n      clearTimeout(pTimer);\n      pTimer=setTimeout(async function(){\n        if(!playing||pBusy)return;\n        var p=getPos();pause();pos=p;\n        pBusy=true;\n        try{if(await ensurePitched()){playMode='lock';playRate=1;play();}}finally{pBusy=false;}\n      },300);\n    }\n  }\n  async function pitchApply(){\n    if(!buf||drag||pBusy)return;\n    var st=pitchSemi;\n    if(Math.abs(st)<0.005)return;\n    var rate=Math.pow(2,st\/12),r=selSamples(),s0=r[0],s1=r[1],n=s1-s0;\n    if(n<2)return;\n    pBusy=true;\n    try{\n      var was=playing,p=getPos();\n      if(was)pause();\n      var rev=editRev,nc=buf.numberOfChannels,chs=[],c,out;\n      for(c=0;c<nc;c++)chs.push(buf.getChannelData(c).slice(s0,s1));\n      if(pitchMode==='vari')out=resampleCubic(chs,rate,Math.max(1,Math.round(n\/rate)));\n      else{\n        if(n<lockMin()){say('Selection too short for KEEP LENGTH.');return;}\n        say('Rendering \u2026');\n        out=await pitchLock(chs,rate);\n        if(rev!==editRev){say('Cancelled: audio changed.',true);return;}\n        say('');\n      }\n      var m=out[0].length,snp=snap(),t0=s0\/sr,t1=s1\/sr,kk=m\/n,dd=(m-n)\/sr;\n      var pitRuns=srcFit(srcSlice(srcRuns,s0,s0+n),m),old=replaceSamples(s0,n,out);srcRuns=srcInsRuns(srcDelRuns(srcRuns,s0,s0+n),s0,pitRuns);\n      pushHist(snp,{type:'rep',at:s0,old:old,newLen:m});\n      if(linkOn){trimS=t0;trimE=t0+m\/sr;}else remapLR(t0,t1,dd);\n      envEach(function(env){return env.map(function(q){var t=q.t;if(t>=t1)t+=dd;else if(t>t0)t=t0+(t-t0)*kk;return {t:t,db:q.db,n:q.n,k:q.k,sc:q.sc};});});\n      cutsFix(function(q){var t=q;if(t>=t1)t+=dd;else if(t>t0)t=t0+(t-t0)*kk;return t;});\n      selPt=null;pos=clamp(p,0,dur);\n      afterStruct();\n    }finally{pBusy=false;}\n  }\n  function pitchUI(){\n    var qs=selSec(),v=pitchSemi,rate=Math.pow(2,v\/12),n=qs[1]-qs[0],m=pitchMode==='vari'?n\/rate:n;\n    el.pv.textContent='\\u00d7'+rate.toFixed(3);\n    if(document.activeElement!==el.pin)el.pin.value=(v>0.004?'+':'')+(pitchFree?v.toFixed(2):String(Math.round(v)));\n    var a=(Math.min(0,v)+12)\/24*100,b=(Math.max(0,v)+12)\/24*100;\n    el.ps.style.setProperty('--a',a+'%');el.ps.style.setProperty('--b',b+'%');\n    el.pfree.classList.toggle('aew-on',pitchFree);el.pfree.setAttribute('aria-pressed',pitchFree?'true':'false');\n    el.pmv.classList.toggle('aew-on',pitchMode==='vari');el.pmv.setAttribute('aria-pressed',pitchMode==='vari'?'true':'false');\n    el.pml.classList.toggle('aew-on',pitchMode==='lock');el.pml.setAttribute('aria-pressed',pitchMode==='lock'?'true':'false');\n    var neutral=Math.abs(v)<0.005,short=pitchMode==='lock'&&!neutral&&buf&&(n*sr<lockMin());\n    el.pl.textContent=short?'Selection too short':fmt(n,2)+' \u2192 '+fmt(m,2);\n    el.ptok.disabled=neutral||!!short||!buf;\n  }\n  \/* ---------- Modaler: Resample + Pitch ---------- *\/\n  var rsDither=false,rsPrev=null,rsTimer=0;\n  function rsK(hz){var k=hz\/1000,s=String(+k.toFixed(3));return s.indexOf('.')<0?s+'.0':s;}\n  function rsUpd(){\n    var hz=+el.rssel.value,bits=+el.rsbit.value,rateOn=!!buf&&hz>0&&hz<sr,bitsOn=bits>0;\n    el.rs1.textContent=hz===0?'Original':(rateOn?rsK(sr)+' kHz \\u2192 '+rsK(hz)+' kHz':'Already at or below '+rsK(hz)+' kHz');\n    el.rs2.textContent=bitsOn?('Original \\u2192 '+bits+'-bit'+(rsDither?' + dither':'')):'Original';\n    el.rsdi.classList.toggle('aew-on',rsDither);el.rsdi.setAttribute('aria-pressed',rsDither?'true':'false');\n    el.rsok.disabled=!(rateOn||bitsOn);\n  }\n  function rsStop(){\n    var p=rsPrev;rsPrev=null;\n    if(p&&ctx){try{p.g.gain.cancelScheduledValues(ctx.currentTime);p.g.gain.setTargetAtTime(0,ctx.currentTime,0.01);}catch(_){}}\n    setTimeout(function(){if(p){try{p.s.stop();}catch(_){}try{p.g.disconnect();}catch(_){}}},120);\n    el.rspl.classList.remove('aew-on');\n  }\n  function rsPlay(){\n    if(rsPrev){rsStop();return;}\n    if(!buf)return;\n    ensureCtx();try{ctx.resume();}catch(_){}\n    var hz=+el.rssel.value,bits=+el.rsbit.value,rate=(hz>0&&hz<sr)?hz:0,r=selSamples(),s0=r[0],s1=Math.min(r[1],s0+Math.round(sr*30)),n=s1-s0;\n    if(n<2)return;\n    var nc=buf.numberOfChannels,chs=[],c;\n    for(c=0;c<nc;c++)chs.push(buf.getChannelData(c).subarray(s0,s1));\n    var out=lofiProcess(chs,n,rate,bits,rsDither),nb=ctx.createBuffer(nc,n,sr);\n    for(c=0;c<nc;c++)nb.getChannelData(c).set(out[c]);\n    var s=ctx.createBufferSource(),g=ctx.createGain();\n    s.buffer=nb;s.loop=true;g.gain.value=0;g.gain.setTargetAtTime(1,ctx.currentTime,0.01);\n    s.connect(g);g.connect(lcOut||ctx.destination);s.start();\n    rsPrev={s:s,g:g};el.rspl.classList.add('aew-on');\n  }\n  function rsRefresh(){\n    rsUpd();\n    if(!rsPrev)return;\n    clearTimeout(rsTimer);\n    rsTimer=setTimeout(function(){if(rsPrev&&!el.rsm.hidden){rsStop();setTimeout(rsPlay,140);}},160);\n  }\n  function rsOpen(){\n    if(!buf||drag)return;\n    if(playing)pause();\n    el.rsm.hidden=false;rsUpd();\n    setTimeout(function(){try{el.rssel.focus();}catch(_){}},30);\n  }\n  function rsClose(){rsStop();clearTimeout(rsTimer);el.rsm.hidden=true;}\n  function rsApply(){var hz=+el.rssel.value,bits=+el.rsbit.value,d=rsDither;rsClose();resampleSel(hz,bits,d);}\n  function ptOpen(){\n    if(!buf||drag)return;\n    if(playing)pause();\n    pitchSemi=0;el.ps.value='0';pitchUI();\n    el.ptm.hidden=false;\n    setTimeout(function(){try{el.ps.focus();}catch(_){}},30);\n  }\n  function ptClose(){\n    clearTimeout(pTimer);\n    if(playing&&playMode!=='norm')pause();\n    el.ptm.hidden=true;\n  }\n  async function ptApply(){\n    if(el.ptok.disabled)return;\n    await pitchApply();\n    ptClose();\n  }\n  \/* ---------- Test tone (modal): sinus, white noise og pink noise ---------- *\/\n  var ttType='sine',ttHz=440,ttDur=5,ttDb=-12,ttOsc=null,ttSrcN=null,ttG=null,TT_MAXDUR=300;\n  function ttHzMax(){return Math.min(20000,Math.floor(sr*0.49));}\n  function ttHzFromSlider(v){return clamp(20*Math.pow(1000,v\/1000),20,ttHzMax());}\n  function ttSliderFromHz(f){return 1000*Math.log(clamp(f,20,20000)\/20)\/Math.log(1000);}\n  function ttLvl(){return Math.pow(10,ttDb\/20);}\n  function ttGen(type,hz,n,db){\n    var out=new Float32Array(n),A=Math.pow(10,db\/20),i,mx=0;\n    if(type==='sine'){\n      var w=2*Math.PI*hz\/sr;\n      for(i=0;i<n;i++)out[i]=A*Math.sin(w*i);\n      return out;\n    }\n    if(type==='white'){\n      for(i=0;i<n;i++){var v=Math.random()*2-1;out[i]=v;if(v<0?-v>mx:v>mx)mx=v<0?-v:v;}\n    }else{\n      var b0=0,b1=0,b2=0,b3=0,b4=0,b5=0,b6=0,wn,k,pre=2000;\n      for(k=-pre;k<n;k++){\n        wn=Math.random()*2-1;\n        b0=0.99886*b0+wn*0.0555179;b1=0.99332*b1+wn*0.0750759;b2=0.96900*b2+wn*0.1538520;\n        b3=0.86650*b3+wn*0.3104856;b4=0.55000*b4+wn*0.5329522;b5=-0.7616*b5-wn*0.0168980;\n        var p=b0+b1+b2+b3+b4+b5+b6+wn*0.5362;b6=wn*0.115926;\n        if(k>=0){out[k]=p;var ap=p<0?-p:p;if(ap>mx)mx=ap;}\n      }\n    }\n    var sc=mx>0?A\/mx:0;\n    for(i=0;i<n;i++)out[i]*=sc;\n    return out;\n  }\n  function ttUI(fromSlider){\n    var sine=ttType==='sine';\n    Array.prototype.forEach.call($$('.aew-tty'),function(b){var on=b.getAttribute('data-t')===ttType;b.classList.toggle('aew-on',on);b.setAttribute('aria-checked',on?'true':'false');});\n    el.ttfw.classList.toggle('aew-dis',!sine);el.ttfl.classList.toggle('aew-dis',!sine);\n    el.tthz.disabled=el.ttfs.disabled=!sine;\n    if(!fromSlider)el.ttfs.value=String(Math.round(ttSliderFromHz(ttHz)));\n    el.ttfs.style.setProperty('--p',(+el.ttfs.value\/10)+'%');\n    el.tthz.value=String(Math.round(ttHz*10)\/10);\n    el.ttd.value=fmt(ttDur,3);\n    el.ttl.value=String(ttDb);el.ttl.style.setProperty('--p',((ttDb+60)\/60*100)+'%');\n    if(document.activeElement!==el.ttlin)el.ttlin.value=numTxt(ttDb,1);\n    el.tt1.textContent=buf?fmt(pos,3):'New file';\n    el.tt2.textContent=fmt(ttDur,3);\n    el.ttok.disabled=false;\n  }\n  function ttStop(){\n    var o=ttOsc,s=ttSrcN,g=ttG;ttOsc=null;ttSrcN=null;ttG=null;\n    if(g&&ctx){try{g.gain.cancelScheduledValues(ctx.currentTime);g.gain.setTargetAtTime(0,ctx.currentTime,0.01);}catch(_){}}\n    setTimeout(function(){try{if(o)o.stop();}catch(_){}try{if(s)s.stop();}catch(_){}try{if(g)g.disconnect();}catch(_){}},150);\n    el.ttpl.classList.remove('aew-on');\n  }\n  function ttPlay(){\n    if(ttG){ttStop();return;}\n    ensureCtx();try{ctx.resume();}catch(_){}\n    var g=ctx.createGain();g.gain.value=0;g.gain.setTargetAtTime(ttLvl(),ctx.currentTime,0.01);\n    g.connect(lcOut||ctx.destination);\n    if(ttType==='sine'){\n      var o=ctx.createOscillator();o.type='sine';o.frequency.value=ttHz;o.connect(g);o.start();ttOsc=o;\n    }else{\n      var n=Math.round(sr*2),b=ctx.createBuffer(1,n,sr),s=ctx.createBufferSource();\n      b.getChannelData(0).set(ttGen(ttType,0,n,0));s.buffer=b;s.loop=true;s.connect(g);s.start();ttSrcN=s;\n    }\n    ttG=g;el.ttpl.classList.add('aew-on');\n  }\n  function ttOpen(){\n    if(drag)return;\n    if(!buf){ensureCtx();sr=ctx.sampleRate;}\n    if(playing)pause();\n    ttUI();el.ttm.hidden=false;\n    setTimeout(function(){try{el.ttd.focus();el.ttd.select();}catch(_){}},30);\n  }\n  function ttClose(){ttStop();el.ttm.hidden=true;}\n  function ttSetType(t){\n    if(ttType===t)return;\n    ttType=t;\n    if(ttG){ttStop();setTimeout(function(){if(!el.ttm.hidden&&!ttG)ttPlay();},170);}\n    ttUI();\n  }\n  function ttApply(){\n    if(drag)return;\n    var fresh=!buf;\n    if(fresh){ensureCtx();sr=ctx.sampleRate;}\n    var n=Math.round(ttDur*sr);\n    if(n<1)return;\n    var nc=fresh?2:buf.numberOfChannels,sig=ttGen(ttType,ttHz,n,ttDb),f=Math.min(Math.round(0.005*sr),n>>1),k,c,data=[];\n    for(k=0;k<f;k++){var gg=0.5-0.5*Math.cos(Math.PI*(k+0.5)\/f);sig[k]*=gg;sig[n-1-k]*=gg;}\n    for(c=0;c<nc;c++)data.push(c===0?sig:sig.slice());\n    ttClose();\n    if(fresh){\n      var nb=ctx.createBuffer(2,n,sr);\n      nb.getChannelData(0).set(data[0]);nb.getChannelData(1).set(data[1]);\n      adopt(nb,'Test tone','');\n      hl={s:0,e:dur};invalidate(true,true);\n      return;\n    }\n    if(playing)pause();\n    var st=snap(),at=Math.min(buf.length,Math.round(clamp(pos,0,dur)*sr)),t=at\/sr,len=n\/sr;\n    insertSamples(at,data);srcRuns=srcInsRuns(srcRuns,at,[{n:n,id:srcId('Test tone')}]);\n    envEach(function(env){return env.map(function(q){return {t:q.t>=t?q.t+len:q.t,db:q.db,n:q.n,k:q.k,sc:q.sc};});});\n    cutsFix(function(q){return q>t+0.5\/sr?q+len:q;});\n    selPt=null;if(linkOn){trimS=t;trimE=t+len;}else remapLR(t,t,len);pos=t+len;selActive=false;\n    pushHist(st,{type:'ins',at:at,len:n,svA:null,svB:null});\n    hl={s:t,e:t+len};\n    afterStruct();\n  }\n  \/* ---------- Stereo to mono (hele filen) ---------- *\/\n  var smKeep=0;\n  function chanUI(back){\n    var spo=el.chm.querySelector('option[value=\"split\"]');if(spo)spo.disabled=chN<2;\n    if(chN<2)el.chm.value='mono';\n    else if(back&&el.chm.value==='mono')el.chm.value='st';\n    splitUI();envUI();\n  }\n  function partialSel(){\n    if(!buf)return false;\n    var e=0.0005;\n    if(!linkOn&&selR)return selR.a>e||selR.b<dur-e;\n    if(linkOn)return trimS>e||trimE<dur-e;\n    return false;\n  }\n  function monoMsg(){\n    if(!buf)return 'Load an audio file first.';\n    if(chN<2)return 'The file is already mono.';\n    if(partialSel())return 'Stereo to mono works on the whole file. Clear the selection first (Esc, or RESET).';\n    return '';\n  }\n  function monoUI(){\n    var m=monoMsg();\n    el.smb.classList.toggle('aew-blocked',!!m);\n    el.smb.setAttribute('aria-disabled',m?'true':'false');\n    el.smb.setAttribute('data-tip',!buf?'Load audio first':(chN<2?'File is already mono':(partialSel()?'Clear selection first (Esc)':'Stereo to mono, whole file')));\n  }\n  function monoConvert(keep){\n    var len=buf.length,nb=ctx.createBuffer(1,len,sr),o=nb.getChannelData(0),i;\n    if(keep===2){\n      var a=buf.getChannelData(0),b=buf.getChannelData(1);\n      for(i=0;i<len;i++)o[i]=(a[i]+b[i])*0.5;\n    }else o.set(buf.getChannelData(keep));\n    setBuffer(nb);chN=1;\n  }\n  function monoOpen(){\n    var m=monoMsg();\n    if(m){say(m,true);return;}\n    if(playing)pause();\n    smKeep=0;monoKeepUI();el.smm.hidden=false;\n    setTimeout(function(){try{el.smok.focus();}catch(_){}},30);\n  }\n  function monoKeepUI(){\n    Array.prototype.forEach.call($$('.aew-smk'),function(b){var on=(+b.getAttribute('data-k'))===smKeep;b.classList.toggle('aew-on',on);b.setAttribute('aria-checked',on?'true':'false');});\n  }\n  function monoApply(){\n    el.smm.hidden=true;\n    var m=monoMsg();\n    if(m){say(m,true);return;}\n    var keep=smKeep,st=snap(),other=(keep===2)?[buf.getChannelData(0).slice(),buf.getChannelData(1).slice()]:buf.getChannelData(1-keep).slice();\n    monoConvert(keep);\n    if(splitCh)CH[0]=cpCh(CH[keep===1?1:0]);\n    splitCh=false;CH[1]=cpCh(CH[0]);selPt=null;\n    pushHist(st,{type:'mono',keep:keep,other:other});\n    chanUI();afterStruct();resetMeter();\n    hl=null;invalidate(true,true);\n  }\n  \/* ---------- Lo-cut filter (realtid) ---------- *\/\n  var LCORD=[6,12,18,24];\n  function lcMake(order,hz){\n    var inn=ctx.createGain(),out=ctx.createGain(),nodes=[],bq=[],last=inn;\n    function bqN(Q){\n      var f=ctx.createBiquadFilter();f.type='highpass';f.frequency.value=hz;f.Q.value=20*Math.log10(Q);\n      last.connect(f);last=f;nodes.push(f);bq.push(f);\n    }\n    function one(){\n      var K=Math.tan(Math.PI*hz\/ctx.sampleRate),b0=1\/(1+K),a1=(K-1)\/(1+K),f=ctx.createIIRFilter([b0,-b0],[1,a1]);\n      last.connect(f);last=f;nodes.push(f);\n    }\n    if(order===6)one();\n    else if(order===12)bqN(Math.SQRT1_2);\n    else if(order===18){one();bqN(1);}\n    else{bqN(0.5411961);bqN(1.3065630);}\n    last.connect(out);\n    out.gain.value=0;\n    nOut.connect(inn);\n    return {inn:inn,out:out,nodes:nodes,bq:bq,hasIIR:(order===6||order===18)};\n  }\n  function lcSwap(order,hz){\n    var old=lcSlot,nw=lcMake(order,hz),now=ctx.currentTime;\n    nw.out.connect(lcWet);\n    if(old){\n      nw.out.gain.setValueAtTime(0,now);nw.out.gain.linearRampToValueAtTime(1,now+0.02);\n      old.out.gain.cancelScheduledValues(now);old.out.gain.setValueAtTime(1,now);old.out.gain.linearRampToValueAtTime(0,now+0.02);\n      setTimeout(function(){\n        try{nOut.disconnect(old.inn);}catch(_){}\n        old.nodes.forEach(function(n){try{n.disconnect();}catch(_){}});\n        try{old.inn.disconnect();}catch(_){}try{old.out.disconnect();}catch(_){}\n      },150);\n    }else nw.out.gain.value=1;\n    lcSlot=nw;\n  }\n  function lcPower(on){\n    lcOn=on;\n    if(!ctx||!lcDry)return;\n    var now=ctx.currentTime;\n    lcWet.gain.cancelScheduledValues(now);lcDry.gain.cancelScheduledValues(now);\n    lcWet.gain.setTargetAtTime(on?1:0,now,0.01);lcDry.gain.setTargetAtTime(on?0:1,now,0.01);\n  }\n  function lcFreq(hz){\n    lcHz=hz;\n    if(!ctx||!lcSlot)return;\n    if(!lcSlot.hasIIR){\n      for(var i=0;i<lcSlot.bq.length;i++)lcSlot.bq[i].frequency.setTargetAtTime(hz,ctx.currentTime,0.01);\n    }else if(!lcTimer){\n      lcTimer=setTimeout(function(){lcTimer=0;if(ctx)lcSwap(lcOrd,lcHz);},35);\n    }\n  }\n  function lcOrder(o){\n    lcOrd=o;\n    if(lcTimer){clearTimeout(lcTimer);lcTimer=0;}\n    if(ctx&&lcDry)lcSwap(o,lcHz);\n  }\n  function lcUI(){\n    if(document.activeElement!==el.lcin)el.lcin.value=(lcHz<100?lcHz.toFixed(1):String(Math.round(lcHz)));\n    el.lcs.style.setProperty('--p',(+el.lcs.value\/10)+'%');\n    el.lcord.textContent=lcOrd+' dB';\n    el.lcsl.textContent=lcOrd+' dB\/oct';\n    el.lcon.classList.toggle('aew-on',lcOn);el.lcon.setAttribute('aria-pressed',lcOn?'true':'false');\n    el.lcm.classList.toggle('aew-on',lcOn);el.lcm.setAttribute('aria-pressed',lcOn?'true':'false');\n  }\n  function lcOpen(){\n    if(!buf||drag)return;\n    if(playing)pause();\n    lcUI();el.lcmod.hidden=false;\n    setTimeout(function(){try{el.lcs.focus();}catch(_){}},30);\n  }\n  function lcClose(){if(playing)pause();el.lcmod.hidden=true;}\n  function lcPlay(){\n    if(!buf)return;\n    if(playing){pause();return;}\n    selOnly=true;playMode='norm';playRate=1;play();\n  }\n  \/* samme filter i JS til eksport (cascade af 1. ordens og RBJ-biquads) *\/\n  function lcProcessor(order,hz){\n    var w0=2*Math.PI*hz\/sr,co=[];\n    function bq(Q){var cs=Math.cos(w0),al=Math.sin(w0)\/(2*Q),a0=1+al;return {t:2,b0:(1+cs)\/2\/a0,b1:-(1+cs)\/a0,b2:(1+cs)\/2\/a0,a1:-2*cs\/a0,a2:(1-al)\/a0};}\n    function one(){var K=Math.tan(w0\/2),b0=1\/(1+K);return {t:1,b0:b0,b1:-b0,a1:(K-1)\/(1+K)};}\n    if(order===6)co.push(one());\n    else if(order===12)co.push(bq(Math.SQRT1_2));\n    else if(order===18){co.push(one());co.push(bq(1));}\n    else{co.push(bq(0.5411961));co.push(bq(1.3065630));}\n    var s=[],n=co.length,k;\n    for(k=0;k<n;k++)s.push({x1:0,x2:0,y1:0,y2:0});\n    return function(x){\n      for(var j=0;j<n;j++){\n        var c=co[j],t=s[j],y;\n        if(c.t===1){y=c.b0*x+c.b1*t.x1-c.a1*t.y1;t.x1=x;t.y1=y;}\n        else{y=c.b0*x+c.b1*t.x1+c.b2*t.x2-c.a1*t.y1-c.a2*t.y2;t.x2=t.x1;t.x1=x;t.y2=t.y1;t.y1=y;}\n        x=y;\n      }\n      return x;\n    };\n  }\n  \/* ---------- Normalize (modal DSP) ---------- *\/\n  var NP=[\n    {lufs:null,tp:-1},{lufs:-14,tp:-1},{lufs:-14,tp:-1},{lufs:-14,tp:-1},{lufs:-14,tp:-1},\n    {lufs:-16,tp:-1},{lufs:-14,tp:-1},{lufs:-16,tp:-1},{lufs:-19,tp:-1},{lufs:-23,tp:-1},{lufs:-24,tp:-2},{lufs:-16,tp:-1}\n  ];\n  var nmM=null,nmId=0;\n  \/* 4x oversampling (windowed sinc, 12 taps) til true-peak *\/\n  var TPW=(function(){\n    var o=[],F=[0.25,0.5,0.75],k,j;\n    for(k=0;k<3;k++){\n      var w=[],s=0;\n      for(j=0;j<12;j++){\n        var d=F[k]+5-j,sc=Math.abs(d)<1e-9?1:Math.sin(Math.PI*d)\/(Math.PI*d),hw=0.5*(1+Math.cos(Math.PI*d\/6));\n        w.push(sc*hw);s+=sc*hw;\n      }\n      for(j=0;j<12;j++)w[j]\/=s;\n      o.push(w);\n    }\n    return o;\n  })();\n  async function truePeak(s0,s1){\n    var qp=selSec(),sp=peakIn(qp[0],qp[1]);\n    if(sp<1e-9)return 0;\n    var best=sp,thr=sp*0.35,len=buf.length,c,i,k,j,cnt=0;\n    for(c=0;c<chN;c++){\n      var d=buf.getChannelData(c);\n      for(i=Math.max(s0,5);i<Math.min(s1-1,len-7);i++){\n        var a=d[i],b=d[i+1];\n        if(a<0)a=-a;\n        if(b<0)b=-b;\n        if(a<thr&&b<thr){if((i&1048575)===0)await tick();continue;}\n        for(k=0;k<3;k++){\n          var w=TPW[k],y=0,q;\n          for(j=0;j<12;j++){q=i-5+j;if(q<0)q=0;else if(q>=len)q=len-1;y+=d[q]*w[j];}\n          if(y<0)y=-y;\n          if(y>best)best=y;\n        }\n        if(++cnt>=150000){cnt=0;await tick();}\n      }\n    }\n    return best;\n  }\n  async function measureSel(){\n    var r=selSamples(),tp=await truePeak(r[0],r[1]);\n    if(!kw){var kk=++kwId,k=await kweight(buf);if(kk===kwId)kw=k;}\n    var ql=selSec();return {tp:tp,lufs:lufsIn(ql[0],ql[1])};\n  }\n  function nmCalc(pr,m){\n    if(!m||m.tp<1e-6)return null;\n    var gT=Math.pow(10,pr.tp\/20)\/m.tp,g=gT,lim=false;\n    if(pr.lufs!=null){\n      if(m.lufs==null)return null;\n      var gL=Math.pow(10,(pr.lufs-m.lufs)\/20);\n      if(gL>gT){lim=true;g=gT;}else g=gL;\n    }\n    if(g>1000)return null;\n    var gd=20*Math.log10(g);\n    return {g:g,gd:gd,lim:lim,tp:m.tp*g,lufs:m.lufs==null?null:m.lufs+gd};\n  }\n  function nmUpd(){\n    if(!nmM)return;\n    var m=nmM,pr=NP[+el.nmsel.value],r=nmCalc(pr,m);\n    el.nm1.textContent=(m.lufs==null?'\u2013 LUFS':m.lufs.toFixed(1)+' LUFS')+' \u00b7 '+fdb(l2d(m.tp))+' dBTP';\n    if(!r){\n      el.nm2.textContent='\u2013';\n      el.nm3.textContent=m.tp<1e-6?'Selection is silent':(m.lufs==null&&pr.lufs!=null?'Loudness not measurable (too short)':'Gain out of range');\n      el.nmok.disabled=true;return;\n    }\n    el.nm2.textContent=(r.gd>=0?'+':'')+r.gd.toFixed(1)+' dB';\n    el.nm3.textContent=(r.lufs==null?'':r.lufs.toFixed(1)+' LUFS \u00b7 ')+fdb(l2d(r.tp))+' dBTP'+(r.lim?' \u00b7 LIMITED':'');\n    el.nmok.disabled=false;\n  }\n  function nmClose(){el.nm.hidden=true;nmId++;nmM=null;}\n  function nmOpen(){\n    if(!buf||drag)return;\n    if(playing)pause();\n    var id=++nmId;nmM=null;\n    el.nm1.textContent='Measuring \u2026';el.nm2.textContent='\u2013';el.nm3.textContent='\u2013';el.nmok.disabled=true;\n    el.nm.hidden=false;\n    setTimeout(function(){try{el.nmsel.focus();}catch(_){}},30);\n    measureSel().then(function(m){if(id!==nmId||el.nm.hidden)return;nmM=m;nmUpd();}).catch(function(e){if(id===nmId)el.nm1.textContent='Measurement failed';});\n  }\n  function mulSamples(s0,s1,g){\n    for(var c=0;c<buf.numberOfChannels;c++){var d=buf.getChannelData(c);for(var i=s0;i<s1;i++)d[i]*=g;}\n  }\n  function nmApply(){\n    var pr=NP[+el.nmsel.value],r=nmCalc(pr,nmM);\n    if(!r||!buf)return;\n    var sel=selSamples(),s0=sel[0],s1=sel[1],was=playing,p=getPos();\n    nmClose();\n    if(was)pause();\n    pushHist(snap(),{type:'gain',s0:s0,s1:s1,g:r.g});\n    mulSamples(s0,s1,r.g);\n    rebuildAfterEdit();\n    pos=p;\n    if(was)play();else frameOnce();\n  }\n  \/* ---------- SNAP: detektion af peaks\/beats (onsets) ---------- *\/\n  function detectOnsets(){\n    var len=buf.length,HOP=256,WIN=512,nb=Math.floor((len-WIN)\/HOP)+1,nc=chN,data=[],c,i,j,k,out=[0];\n    if(nb<8){out.push(dur);return out;}\n    for(c=0;c<nc;c++)data.push(buf.getChannelData(c));\n    var e=new Float32Array(nb),lg=new Float32Array(nb),fl=new Float32Array(nb);\n    for(i=0;i<nb;i++){\n      var s0=i*HOP,acc=0;\n      for(c=0;c<nc;c++){var d=data[c];for(j=s0;j<s0+WIN;j+=2){var v=d[j];acc+=v*v;}}\n      e[i]=Math.sqrt(acc\/(nc*WIN\/2));lg[i]=Math.log(1e-4+e[i]);\n    }\n    for(i=2;i<nb;i++){var df=lg[i]-lg[i-2];fl[i]=df>0?df:0;}\n    var pre=new Float64Array(nb+1);for(i=0;i<nb;i++)pre[i+1]=pre[i]+fl[i];\n    var R=Math.round(0.5*sr\/HOP),minGap=Math.round(0.09*sr\/HOP),last=-1e9,cand=[];\n    for(i=2;i<nb-1;i++){\n      var a=Math.max(0,i-R),b=Math.min(nb,i+R+1),thr=0.22+1.5*(pre[b]-pre[a])\/(b-a);\n      if(fl[i]<thr)continue;\n      var ok=true;for(j=Math.max(0,i-3);j<=Math.min(nb-1,i+3);j++)if(fl[j]>fl[i]){ok=false;break;}\n      if(!ok)continue;\n      if(i-last<minGap){if(cand.length&&fl[i]>cand[cand.length-1].f){cand[cand.length-1]={i:i,f:fl[i]};last=i;}continue;}\n      cand.push({i:i,f:fl[i]});last=i;\n    }\n    function mx(p){var s=0;for(var q=0;q<nc;q++)s+=data[q][p];return s\/nc;}\n    function ax(p){var m=0,q,v;for(q=0;q<nc;q++){v=data[q][p];if(v<0)v=-v;if(v>m)m=v;}return m;}\n    \/* gammel metode: f\u00f8rste sample over 25 % af lokal top (bruges kun hvis den nye ikke finder noget) *\/\n    function refineOld(bi){\n      var w0=Math.max(0,(bi-3)*HOP),w1=Math.min(len,(bi+2)*HOP+WIN),M=0,p;\n      for(p=w0;p<w1;p++){var av=Math.abs(mx(p));if(av>M)M=av;}\n      var th=M*0.25,pk=w0;\n      for(p=w0;p<w1;p++){if(Math.abs(mx(p))>=th){pk=p;break;}}\n      return pk;\n    }\n    \/* ny metode: finder hvor lyden begynder at stige over niveauet LIGE F\u00d8R slaget (ikke et fast procenttal af toppen) *\/\n    var BIN=Math.max(8,Math.round(0.0005*sr)),PRE=40,GAP=8,LB=PRE+GAP;   \/* 0,5 ms-trin, 20 ms bagudblik, 4 ms hul *\/\n    function refine(bi){\n      var c0=bi*HOP,pad=Math.round(0.02*sr),a0=Math.max(0,c0-pad),a1=Math.min(len,c0+WIN+pad);\n      var b0=Math.max(0,a0-LB*BIN),tot=Math.ceil((a1-b0)\/BIN);\n      if(tot<LB+4)return -1;\n      var pe=new Float32Array(tot),off=Math.round((a0-b0)\/BIN),Pk=0,t,q,s,e,m,v;\n      for(t=0;t<tot;t++){m=0;s=b0+t*BIN;e=Math.min(len,s+BIN);for(q=s;q<e;q++){v=ax(q);if(v>m)m=v;}pe[t]=m;if(t>=off&&m>Pk)Pk=m;}\n      if(Pk<1e-4)return -1;\n      var rhos=[1.3,1.15],ri,found=-1,thr=0,u,u0,Bm;\n      for(ri=0;ri<rhos.length&&found<0;ri++){\n        for(t=off;t<tot-2;t++){\n          u0=t-LB;if(u0<0)u0=0;Bm=0;\n          for(u=u0;u<t-GAP;u++)if(pe[u]>Bm)Bm=pe[u];\n          thr=Math.max(rhos[ri]*Bm,0.05*Pk);\n          if(pe[t]>thr&&pe[t+1]>=0.8*thr&&pe[t+2]>=0.8*thr){found=t;break;}\n        }\n      }\n      if(found<0)return -1;\n      var ps=b0+found*BIN,pe2=Math.min(len,ps+BIN),pk=ps;\n      for(q=ps;q<pe2;q++){if(ax(q)>thr){pk=q;break;}}\n      return pk;\n    }\n    for(k=0;k<cand.length;k++){\n      var bi=cand[k].i,pk=refine(bi);\n      if(pk<0)pk=refineOld(bi);\n      \/* tilbage til n\u00e6rmeste nulgennemgang (max 3 ms), s\u00e5 der ikke klippes midt i en svingning *\/\n      var z=pk,lim=Math.max(1,pk-Math.round(0.010*sr));\n      while(z>lim&&mx(z)*mx(z-1)>0)z--;\n      if(z<=lim&&mx(z)*mx(z-1)>0){var f2=pk,lim2=Math.min(len-1,pk+Math.round(0.003*sr));while(f2<lim2&&mx(f2)*mx(f2+1)>0)f2++;z=(mx(f2)*mx(f2+1)<=0)?f2:pk;}\n      out.push(z\/sr);\n    }\n    out.push(dur);\n    out.sort(function(x,y){return x-y;});\n    return out;\n  }\n  function computeSnap(){\n    var id=++snapId;snapPts=[0,dur];\n    setTimeout(function(){\n      if(id!==snapId||!buf)return;\n      var pts=detectOnsets();\n      if(id!==snapId)return;\n      snapPts=pts;\n      if(snapOn)invalidate(false,true);\n    },0);\n  }\n  function snapT(t,px,skipMk,o){\n    if(!snapOn)return t;\n    var tol=(px||14)\/W()*view.sp,best=t,bd=1e9,i,d,c,u=t,ud=1e9,beat=t,bb=1e9;\n    \/* ting du selv har sat (cursor, markers, klip, locatorer, markering, envelope-punkter) har forrang over de automatiske slag *\/\n    function cand(v){d=Math.abs(v-t);if(d<ud){ud=d;u=v;}}\n    if(snapPts.length>=2){\n      var lo=0,hi=snapPts.length-1,mid;\n      while(hi-lo>1){mid=(lo+hi)>>1;if(snapPts[mid]<=t)lo=mid;else hi=mid;}\n      c=(t-snapPts[lo]<=snapPts[hi]-t)?snapPts[lo]:snapPts[hi];\n      bb=Math.abs(c-t);beat=c;\n    }\n    for(i=0;i<markers.length;i++){if(markers[i]===skipMk)continue;cand(markers[i].t);}\n    for(i=0;i<cuts.length;i++){if(o&&o.skipCut===i)continue;cand(cuts[i]);}\n    cand(getPos());\n    if(!(o&&o.noLR)){\n      cand(trimS);cand(trimE);\n      if(selR&&!linkOn){cand(selR.a);cand(selR.b);}\n    }\n    if(o&&o.env){\n      var ec,ep;\n      for(ec=0;ec<(splitCh&&chN>1?2:1);ec++){\n        for(ep=0;ep<CH[ec].env.length;ep++){\n          if(CH[ec].env[ep]===o.skipPt)continue;\n          cand(CH[ec].env[ep].t);\n        }\n      }\n    }\n    if(ud<=tol)return u;\n    return bb<=tol?beat:t;\n  }\n  \/* ---------- Invert (fase) ---------- *\/\n  function invertSamples(s0,s1){\n    for(var c=0;c<buf.numberOfChannels;c++){var d=buf.getChannelData(c);for(var i=s0;i<s1;i++)d[i]=-d[i];}\n  }\n  function invertSel(){\n    if(!buf||drag)return;\n    var r=selSamples(),s0=r[0],s1=r[1];\n    if(s1-s0<1)return;\n    var was=playing,p=getPos();\n    if(was)pause();\n    pushHist(snap(),{type:'inv',s0:s0,s1:s1});\n    invertSamples(s0,s1);\n    rebuildAfterEdit();\n    pos=p;\n    if(was)play();else frameOnce();\n  }\n  \/* ---------- Klip \/ kopi\u00e9r \/ inds\u00e6t ---------- *\/\n  function setBuffer(nb){\n    var wasFull=view.sp>=dur-1e-6;\n    buf=nb;dur=nb.duration;MIN=Math.min(1\/nb.sampleRate,dur\/2);\n    if(wasFull)view={s:0,sp:dur};\n  }\n  function insertSamples(at,data){\n    var nc=buf.numberOfChannels,m=data[0].length,nb=ctx.createBuffer(nc,buf.length+m,sr),c;\n    for(c=0;c<nc;c++){\n      var s=buf.getChannelData(c),dst=nb.getChannelData(c);\n      dst.set(s.subarray(0,at),0);dst.set(data[c],at);dst.set(s.subarray(at),at+m);\n    }\n    setBuffer(nb);\n  }\n  function deleteSamples(s0,s1){\n    var nc=buf.numberOfChannels,m=s1-s0,nb=ctx.createBuffer(nc,buf.length-m,sr),rem=[],c;\n    for(c=0;c<nc;c++){\n      var s=buf.getChannelData(c),dst=nb.getChannelData(c);\n      rem.push(s.slice(s0,s1));dst.set(s.subarray(0,s0),0);dst.set(s.subarray(s1),s0);\n    }\n    setBuffer(nb);return rem;\n  }\n  function afterStruct(){\n    segSel=null;\n    el.tt.textContent=fL(dur);\n    trimS=clamp(trimS,0,Math.max(0,dur-MIN));trimE=clamp(trimE,trimS+MIN,dur);\n    if(selR){selR.a=clamp(selR.a,0,dur);selR.b=clamp(selR.b,0,dur);if(selR.b-selR.a<MIN)selR=null;}\n    pos=clamp(pos,0,dur);envUI();trimUI();setView(view.s,Math.min(view.sp,dur));\n    rebuildAfterEdit();frameOnce();\n  }\n  function declickJoint(at,limit){\n    var nc=buf.numberOfChannels,len=buf.length,c,k;\n    if(at<3||at>len-3)return null;\n    var xf=Math.min(Math.max(8,Math.round(sr*0.0015)),at,len-at);\n    if(limit)xf=Math.min(xf,limit);\n    var worst=0;\n    for(c=0;c<nc;c++){\n      var d=buf.getChannelData(c),a=d[at-1],b=d[at],sl=Math.max(Math.abs(a-d[at-2]),Math.abs(d[at+1]-b)),ex=Math.abs(b-a)-3*sl;\n      if(ex>worst)worst=ex;\n    }\n    if(worst<0.003)return null;\n    var sv={at:at,xf:xf,L:[],R:[]};\n    for(c=0;c<nc;c++){\n      var dd=buf.getChannelData(c);\n      sv.L.push(dd.slice(at-xf,at));sv.R.push(dd.slice(at,at+xf));\n      for(k=0;k<xf;k++){var g=k\/xf;dd[at-1-k]*=g;dd[at+k]*=g;}\n    }\n    return sv;\n  }\n  function undeclick(sv){\n    if(!sv)return;\n    for(var c=0;c<buf.numberOfChannels;c++){var d=buf.getChannelData(c);d.set(sv.L[c],sv.at-sv.xf);d.set(sv.R[c],sv.at);}\n  }\n  \/* L\u2013R (locatorerne) og markeringen (n\u00e5r LINK er slukket) er to forskellige ting *\/\n  function lrSamples(){return [Math.max(0,Math.round(trimS*sr)),Math.min(buf.length,Math.round(trimE*sr))];}\n  function selSamples(){\n    if(!linkOn&&selR)return [Math.max(0,Math.round(selR.a*sr)),Math.min(buf.length,Math.round(selR.b*sr))];\n    return lrSamples();\n  }\n  function selSec(){\n    if(!buf)return [trimS,trimE];\n    var r=selSamples();return [r[0]\/sr,r[1]\/sr];\n  }\n  \/* efter en redigering f\u00f8lger L og R lyden, n\u00e5r LINK er slukket: [a,b) er det omr\u00e5de, der blev erstattet, delta \u00e6ndringen i l\u00e6ngde *\/\n  function remapLR(a,b,delta){\n    var f=function(t){return t<=a?t:(t>=b?t+delta:a);};\n    trimS=clamp(f(trimS),0,dur);trimE=clamp(f(trimE),trimS+MIN,dur);selR=null;\n  }\n  function linkUI(){\n    el.link.classList.toggle('aew-on',linkOn);el.link.setAttribute('aria-pressed',linkOn?'true':'false');\n    root.classList.toggle('aew-nolink',!linkOn);\n    invalidate(true,true);\n  }\n  function clipUI(){\n    el.pst.disabled=!CLIP;\n    \n  }\n  function fitClip(c){\n    var nc=buf.numberOfChannels,src=c.ch,chs=[],i,k,j,avg=null;\n    for(i=0;i<nc;i++){\n      if(src.length===nc)chs.push(src[i]);\n      else if(src.length===1)chs.push(src[0]);\n      else if(nc===1){\n        if(!avg){avg=new Float32Array(src[0].length);for(k=0;k<avg.length;k++){var s=0;for(j=0;j<src.length;j++)s+=src[j][k];avg[k]=s\/src.length;}}\n        chs.push(avg);\n      }else chs.push(src[Math.min(i,src.length-1)]);\n    }\n    if(c.sr===sr)return chs;\n    var ratio=c.sr\/sr,n=Math.max(1,Math.round(chs[0].length\/ratio)),out=[];\n    for(i=0;i<nc;i++){\n      var a=chs[i],o=new Float32Array(n),L=a.length;\n      for(k=0;k<n;k++){var x=k*ratio,i0=Math.floor(x),fr=x-i0,v0=a[Math.min(i0,L-1)],v1=a[Math.min(i0+1,L-1)];o[k]=v0+(v1-v0)*fr;}\n      out.push(o);\n    }\n    return out;\n  }\n  function hasSelection(){return (!linkOn&&!!selR)||selActive||trimS>0.0005||trimE<dur-0.0005;}\n  \/* ---------- Copy\/paste-type: Normal \/ Equal power \/ Zero crossing ---------- *\/\n  var pmode='normal',xfMs=10;\n  function xfSamples(){return Math.max(1,Math.round(xfMs\/1000*sr));}\n  function mixAtBuf(chs,i){var s=0;for(var c=0;c<chs.length;c++)s+=chs[c][i];return s\/chs.length;}\n  function crossDir(chs,i){var a=mixAtBuf(chs,i-1),b=mixAtBuf(chs,i);return (a<0&&b>=0)?1:((a>0&&b<=0)?-1:0);}\n  \/* n\u00e6rmeste nulgennemgang (\u00b120 ms); dir=+1 stigende, -1 faldende, 0 = begge. Falder tilbage til enhver retning. *\/\n  function zcSnap(p,dir){\n    var chs=[],c,len=buf.length,win=Math.round(0.02*sr),k,sg,q,d,pass;\n    for(c=0;c<buf.numberOfChannels;c++)chs.push(buf.getChannelData(c));\n    for(pass=0;pass<2;pass++){\n      for(k=0;k<=win;k++){\n        for(sg=-1;sg<=1;sg+=2){\n          q=p+sg*k;\n          if(q<1||q>=len)continue;\n          d=crossDir(chs,q);\n          if(d===0)continue;\n          if(pass===0&&dir&&d!==dir)continue;\n          return {i:q,dir:d};\n        }\n      }\n      if(!dir)break;\n    }\n    return {i:p,dir:0};\n  }\n  function zcEdge(p){return (p<=0||p>=buf.length)?{i:p,dir:0}:zcSnap(p,0);}\n  \/* markeringens kanter til nulgennemgange (filens start\/slut r\u00f8res ikke); returnerer [s0,s1,retning] *\/\n  function zcRange(s0,s1){\n    var a=zcEdge(s0),b=(s1>=buf.length)?{i:s1,dir:0}:zcSnap(s1,a.dir);\n    if(b.i-a.i<1)return [s0,s1,0];\n    return [a.i,b.i,a.dir||b.dir];\n  }\n  \/* trim det indsatte stykkes kanter til nulgennemgange af samme retning som inds\u00e6tningspunktet *\/\n  function zcTrimClip(data,dir){\n    var nc=data.length,m=data[0].length,win=Math.min(Math.round(0.02*sr),m>>2),h0=0,e0=m,k,c,found;\n    function cd(i){var a=0,b=0;for(c=0;c<nc;c++){a+=data[c][i-1];b+=data[c][i];}a\/=nc;b\/=nc;return (a<0&&b>=0)?1:((a>0&&b<=0)?-1:0);}\n    for(var pass=0;pass<2;pass++){\n      if(pass===1&&!dir)break;\n      found=false;\n      for(k=1;k<=win&&!found;k++){var d=cd(k);if(d!==0&&(pass===1||!dir||d===dir)){h0=k;found=true;}}\n      if(found)break;\n    }\n    for(pass=0;pass<2;pass++){\n      if(pass===1&&!dir)break;\n      found=false;\n      for(k=m-1;k>=m-win&&k>h0+1&&!found;k--){var d2=cd(k);if(d2!==0&&(pass===1||!dir||d2===dir)){e0=k;found=true;}}\n      if(found)break;\n    }\n    if(e0-h0<1)return data;\n    var out=[];\n    for(c=0;c<nc;c++)out.push(data[c].slice(h0,e0));\n    return out;\n  }\n  \/* equal power: det indsatte tones ind\/ud, og den originale lyd tones ud\/ind under det (bevarer alt, intet fjernes) *\/\n  function eqBlendClip(data,hasA,hasB,cStart,cLen,lEnd,lLen){\n    var nc=data.length,m=data[0].length,N=xfSamples(),half=Math.floor(m\/2),c,k;\n    var x1=hasA&&cLen>=1,x2=hasB&&lLen>=1;\n    var N1=Math.max(0,Math.min(N,half,x1?cLen:half)),N2=Math.max(0,Math.min(N,half,x2?lLen:half)),out=[];\n    for(c=0;c<nc;c++){\n      var o=new Float32Array(data[c]),src=buf.getChannelData(c),th,gi,go,j;\n      for(k=0;k<N1;k++){th=Math.PI\/2*(k+0.5)\/N1;gi=Math.sin(th);go=Math.cos(th);o[k]=x1?gi*o[k]+go*src[cStart+k]:gi*o[k];}\n      for(k=0;k<N2;k++){th=Math.PI\/2*(k+0.5)\/N2;gi=Math.sin(th);go=Math.cos(th);j=m-N2+k;o[j]=x2?go*o[j]+gi*src[lEnd-N2+k]:go*o[j];}\n      out.push(o);\n    }\n    return out;\n  }\n  \/* equal power ved cut\/delete: B's start tones ind, mens det fjernedes f\u00f8rste del (A's naturlige forts\u00e6ttelse) tones ud *\/\n  function eqDeleteBlend(s0,removed){\n    var nc=buf.numberOfChannels,Lr=removed[0].length,Lb=buf.length-s0,N=xfSamples(),hasA=s0>0,hasB=Lb>0,c,k,n,th,sv=null,d;\n    if(hasA&&hasB){\n      n=Math.min(N,Lr,Lb);if(n<1)return null;\n      sv={at:s0,xf:0,L:[],R:[]};\n      for(c=0;c<nc;c++){\n        d=buf.getChannelData(c);sv.L.push(new Float32Array(0));sv.R.push(d.slice(s0,s0+n));\n        for(k=0;k<n;k++){th=Math.PI\/2*(k+0.5)\/n;d[s0+k]=Math.sin(th)*d[s0+k]+Math.cos(th)*removed[c][k];}\n      }\n    }else if(!hasA&&hasB){\n      n=Math.min(N,Lb);if(n<1)return null;\n      sv={at:0,xf:0,L:[],R:[]};\n      for(c=0;c<nc;c++){\n        d=buf.getChannelData(c);sv.L.push(new Float32Array(0));sv.R.push(d.slice(0,n));\n        for(k=0;k<n;k++){th=Math.PI\/2*(k+0.5)\/n;d[k]*=Math.sin(th);}\n      }\n    }else if(hasA&&!hasB){\n      n=Math.min(N,s0);if(n<1)return null;\n      sv={at:s0,xf:n,L:[],R:[]};\n      for(c=0;c<nc;c++){\n        d=buf.getChannelData(c);sv.L.push(d.slice(s0-n,s0));sv.R.push(new Float32Array(0));\n        for(k=0;k<n;k++){th=Math.PI\/2*(k+0.5)\/n;d[s0-n+k]*=Math.cos(th);}\n      }\n    }\n    return sv;\n  }\n  function pmSet(m){\n    pmode=m;\n    Array.prototype.forEach.call($$('.aew-pmb'),function(b){var on=b.getAttribute('data-m')===m;b.classList.toggle('aew-on',on);b.setAttribute('aria-checked',on?'true':'false');});\n    el.xfms.disabled=(m!=='eq');\n    el.xfms.parentNode.classList.toggle('aew-off',m!=='eq');\n  }\n  function xfCommit(){\n    var v=parseFloat(String(el.xfms.value).replace(',','.'));\n    if(!isFinite(v))v=xfMs;\n    xfMs=clamp(Math.round(v),1,500);\n    el.xfms.value=String(xfMs);\n  }\n  function copySel(){\n    if(!buf)return;\n    if(!segSel&&!hasSelection()){say('Select a region first.');return;}\n    var r=segSel?[Math.round(segSel.a*sr),Math.round(segSel.b*sr)]:selSamples();if(r[1]-r[0]<1)return;\n    if(pmode==='zc'){\n      var z=zcRange(r[0],r[1]);\n      if(z[1]-z[0]>=1){r=[z[0],z[1]];if(!segSel){if(!linkOn&&selR){selR={a:r[0]\/sr,b:r[1]\/sr};invalidate(true,true);}else{trimS=r[0]\/sr;trimE=r[1]\/sr;trimUI();invalidate(false,true);}}}\n    }\n    var ch=[],c;\n    for(c=0;c<buf.numberOfChannels;c++)ch.push(buf.getChannelData(c).slice(r[0],r[1]));\n    CLIP={sr:sr,ch:ch,runs:srcSlice(srcRuns,r[0],r[1])};clipUI();\n    say('Copied '+fmt((r[1]-r[0])\/sr,2)+'.');\n  }\n  function removeSel(toClip){\n    if(!buf||drag)return;\n    if(!segSel&&!hasSelection()){say('Select a region first.');return;}\n    var r=segSel?[Math.round(segSel.a*sr),Math.round(segSel.b*sr)]:selSamples(),s0=r[0],s1=r[1],m=s1-s0;\n    if(m<1)return;\n    if(pmode==='zc'){var z=zcRange(s0,s1);s0=z[0];s1=z[1];m=s1-s0;}\n    if(buf.length-m<Math.round(sr*0.05)){say('Select a region first.');return;}\n    var st=snap(),t0=s0\/sr,t1=s1\/sr,len=m\/sr;\n    if(playing)pause();\n    var removed=deleteSamples(s0,s1),sv=null,runsOut=srcSlice(srcRuns,s0,s1);srcRuns=srcDelRuns(srcRuns,s0,s1);\n    if(pmode==='eq')sv=eqDeleteBlend(s0,removed);\n    if(toClip){CLIP={sr:sr,ch:removed,runs:runsOut};clipUI();}\n    envEach(function(env){return env.filter(function(p){return p.t<t0||p.t>=t1;}).map(function(p){return {t:p.t>=t1?p.t-len:p.t,db:p.db,n:p.n,k:p.k,sc:p.sc};});});\n    cutsFix(function(c){var e=0.5\/sr;if(c>t0+e&&c<t1-e)return null;return c>=t1-e?c-len:c;});\n    selPt=null;if(linkOn){trimS=0;trimE=dur;}else remapLR(t0,t1,-len);pos=clamp(t0,0,dur);selActive=false;\n    pushHist(st,{type:'del',at:s0,data:removed,sv:sv});\n    afterStruct();\n    say((toClip?'Cut ':'Deleted ')+fmt(len,2)+'.');\n  }\n  \/* Inds\u00e6t: er der en markering, erstattes den; ellers inds\u00e6ttes ved cursoren. Det indsatte bliver markeret. *\/\n  function pmodeSet(m){\n    pasteMode=m;\n    el.pi.classList.toggle('aew-on',m==='insert');el.pi.setAttribute('aria-pressed',m==='insert'?'true':'false');el.pi.setAttribute('aria-checked',m==='insert'?'true':'false');\n    el.po.classList.toggle('aew-on',m==='over');el.po.setAttribute('aria-pressed',m==='over'?'true':'false');el.po.setAttribute('aria-checked',m==='over'?'true':'false');\n  }\n  \/* Overskriv: den nye lyd erstatter det, der ligger der. Med markering fylder den pr\u00e6cis markeringen (afkortes, eller resten bliver stilhed); uden markering l\u00e6gges den fra cursoren og filen forl\u00e6nges om n\u00f8dvendigt *\/\n  function pasteReplaces(){\n    if(!linkOn&&selR){var pp=getPos();return pp>=selR.a-1e-6&&pp<=selR.b+1e-6;}\n    return !!selActive;\n  }\n  function pasteOver(data){\n    var N=buf.length,m=data[0].length,mode=pmode,Nx=xfSamples(),nc=buf.numberOfChannels,C,L,k,ch,st=snap();\n    if(pasteReplaces()){\n      var r=selSamples(),s0=r[0],s1=r[1];\n      if(s1-s0<1)return;\n      if(mode==='zc'){var z=zcRange(s0,s1);s0=z[0];s1=z[1];data=zcTrimClip(data,z[2]);m=data[0].length;}\n      C=s0;L=s1-s0;\n    }else{\n      C=Math.min(N,Math.round(clamp(pos,0,dur)*sr));\n      if(mode==='zc'){var zz=zcEdge(C);C=zz.i;data=zcTrimClip(data,zz.dir);m=data[0].length;}\n      L=m;\n    }\n    var w=Math.min(m,L),oldLen=Math.min(L,N-C),n1=Math.min(Nx,w>>1),out=[];\n    for(ch=0;ch<nc;ch++){\n      var d=buf.getChannelData(ch),o=new Float32Array(L),cl=data[ch],v,th,ex;\n      for(k=0;k<L;k++){\n        ex=(C+k<N)?d[C+k]:0;\n        if(k>=w){v=0;}\n        else{\n          v=cl[k];\n          if(mode==='eq'){\n            if(k<n1){th=Math.PI\/2*(k+0.5)\/n1;v=Math.sin(th)*cl[k]+Math.cos(th)*ex;}\n            else if(k>=w-n1){th=Math.PI\/2*(k-(w-n1)+0.5)\/n1;v=Math.cos(th)*cl[k]+Math.sin(th)*(w<L?0:ex);}\n          }\n        }\n        o[k]=v;\n      }\n      out.push(o);\n    }\n    if(playing)pause();\n    var old=replaceSamples(C,oldLen,out),t0=C\/sr,t1=(C+L)\/sr;srcRuns=srcInsRuns(srcDelRuns(srcRuns,C,C+oldLen),C,srcFit(CLIP&&CLIP.runs||[],L));\n    cutsFix(function(q){var e=0.5\/sr;return (q>t0+e&&q<t1-e)?null:q;});\n    selPt=null;if(linkOn){trimS=t0;trimE=t1;}else remapLR(t0,t0+oldLen\/sr,(L-oldLen)\/sr);pos=t1;selActive=false;\n    pushHist(st,{type:'rep',at:C,old:old,newLen:L});\n    hl={s:t0,e:t1};\n    afterStruct();\n  }\n  function pasteClip(){\n    if(!buf||!CLIP||drag)return;\n    if(playing)pause();\n    var data=fitClip(CLIP),m=data[0].length;\n    if(m<1)return;\n    if(pasteMode==='over'){pasteOver(data);return;}\n    var st=snap(),len,t,op;\n    if(pasteReplaces()){\n      var r=selSamples(),s0=r[0],s1=r[1];\n      if(s1-s0<1)return;\n      if(pmode==='zc'){var z=zcRange(s0,s1);s0=z[0];s1=z[1];data=zcTrimClip(data,z[2]);m=data[0].length;}\n      var n=s1-s0;\n      if(pmode==='eq')data=eqBlendClip(data,s0>0,s1<buf.length,s0,n,s1,n);\n      len=m\/sr;\n      var t0=s0\/sr,t1=s1\/sr,old=replaceSamples(s0,n,data),sA=null,sB=null;srcRuns=srcInsRuns(srcDelRuns(srcRuns,s0,s0+n),s0,srcFit(CLIP&&CLIP.runs||[],m));\n      envEach(function(env){return env.filter(function(q){return q.t<t0||q.t>=t1;}).map(function(q){return {t:q.t>=t1?q.t+(len-(t1-t0)):q.t,db:q.db,n:q.n,k:q.k,sc:q.sc};});});\n      cutsFix(function(c){var e=0.5\/sr;if(c>t0+e&&c<t1-e)return null;return c>=t1-e?c+(len-(t1-t0)):c;});\n      t=t0;op={type:'rep',at:s0,old:old,newLen:m,svA:sA,svB:sB};\n    }else{\n      var at=Math.min(buf.length,Math.round(clamp(pos,0,dur)*sr));\n      if(pmode==='zc'){var zz=zcEdge(at);at=zz.i;data=zcTrimClip(data,zz.dir);m=data[0].length;}\n      if(pmode==='eq')data=eqBlendClip(data,at>0,at<buf.length,at,buf.length-at,at,at);\n      len=m\/sr;t=at\/sr;\n      insertSamples(at,data);srcRuns=srcInsRuns(srcRuns,at,srcFit(CLIP&&CLIP.runs||[],m));\n      var sA2=null,sB2=null;\n      envEach(function(env){return env.map(function(q){return {t:q.t>=t?q.t+len:q.t,db:q.db,n:q.n,k:q.k,sc:q.sc};});});\n      cutsFix(function(c){return c>t+0.5\/sr?c+len:c;});\n      op={type:'ins',at:at,len:m,svA:sA2,svB:sB2};\n    }\n    selPt=null;if(linkOn){trimS=t;trimE=t+len;}else{if(op.type==='rep')remapLR(t0,t1,len-(t1-t0));else remapLR(t,t,len);}pos=t+len;selActive=false;\n    pushHist(st,op);\n    hl={s:t,e:t+len};\n    afterStruct();\n    say('Pasted '+fmt(len,2)+' at '+fmt(t,2)+'.');\n  }\n  function selectAll(){\n    if(!buf)return;\n    if(!linkOn){edit(function(){selR={a:0,b:dur};});invalidate(true,true);say('Whole file selected.');return;}\n    edit(function(){trimS=0;trimE=dur;});selActive=true;onTrim(true);say('Whole file selected.');\n  }\n  \/* CROP: behold kun lyden mellem L- og R-locatorerne *\/\n  function cropSel(){\n    if(!buf||drag)return;\n    var cr=selSamples(),s0=cr[0],s1=cr[1];\n    if(pmode==='zc'){var z=zcRange(s0,s1);s0=z[0];s1=z[1];}\n    if(s0<=0&&s1>=buf.length){say('Nothing to crop: the selection already covers the whole file.',true);return;}\n    if(s1-s0<2){say('Select a region first.',true);return;}\n    if(playing)pause();\n    var st=snap(),t0=s0\/sr,t1=s1\/sr,nc=buf.numberOfChannels,kept=[],c;\n    for(c=0;c<nc;c++)kept.push(buf.getChannelData(c).slice(s0,s1));\n    var cropRuns=srcSlice(srcRuns,s0,s1),old=replaceSamples(0,buf.length,kept);srcRuns=cropRuns;\n    envEach(function(env){return env.filter(function(q){return q.t>=t0&&q.t<t1;}).map(function(q){return {t:q.t-t0,db:q.db,n:q.n,k:q.k,sc:q.sc};});});\n    cutsFix(function(q){var e=0.5\/sr;return (q>t0+e&&q<t1-e)?q-t0:null;});\n    markers=markers.filter(function(m){return m.t>=t0&&m.t<=t1;}).map(function(m){return {n:m.n,t:m.t-t0};});\n    selPt=null;if(linkOn){trimS=0;trimE=dur;}else{trimS=clamp(trimS-t0,0,dur);trimE=clamp(trimE-t0,trimS+MIN,dur);selR=null;}pos=0;selActive=false;\n    pushHist(st,{type:'rep',at:0,old:old,newLen:s1-s0,crop:{s0:s0,s1:s1}});\n    afterStruct();setView(0,dur);mkUI();\n  }\n  \/* ---------- Level meter ---------- *\/\n  var DMIN=-60,DMAX=6,MROW=28,MPL=30,MPR=16,MSC=30;\n  function l2d(v){return v>1e-6?20*Math.log10(v):-120;}\n  function fdb(v){return v<=-100?'-\u221e':(v>0?'+':'')+v.toFixed(1);}\n  function resetMeter(){\n    for(var i=0;i<2;i++)mv[i]={pk:-120,hold:-120,ht:0,rl:0,rd:-120};\n    mMax=0;mOver=false;drawMeter();updRead();\n  }\n  function readMeters(dt,now){\n    var n=chN>1?2:1,an=[anL,anR],i,k,m,b,pk,s,v,a,d;\n    for(i=0;i<2;i++){\n      m=mv[i];pk=0;s=0;\n      if(i<n&&an[i]&&playing){\n        b=bufs[i];an[i].getFloatTimeDomainData(b);\n        for(k=0;k<b.length;k++){v=b[k];a=v<0?-v:v;if(a>pk)pk=a;s+=v*v;}\n        s=Math.sqrt(s\/b.length);\n      }\n      d=l2d(pk);\n      if(d>=m.pk)m.pk=d;else m.pk=Math.max(d,m.pk-40*dt);\n      if(m.pk>=m.hold){m.hold=m.pk;m.ht=now;}\n      else if(playing&&now-m.ht>1500)m.hold=Math.max(m.pk,m.hold-30*dt);\n      m.rl+=(s-m.rl)*Math.min(1,dt\/0.3);\n      m.rd=l2d(m.rl);\n      if(pk>mMax)mMax=pk;\n      if(pk>CLIPT)mOver=true;\n    }\n  }\n  function drawMeter(){\n    var cv=el.mcv,w=el.mwrap.clientWidth||600,rows=chN>1?2:1,h=rows*MROW+MSC+6;\n    var dpr=Math.min(window.devicePixelRatio||1,2),cw=Math.round(w*dpr),ch=Math.round(h*dpr);\n    if(cv.width!==cw||cv.height!==ch){cv.width=cw;cv.height=ch;}\n    cv.style.height=h+'px';\n    var g=cv.getContext('2d');if(!g)return;\n    g.setTransform(dpr,0,0,dpr,0,0);g.clearRect(0,0,w,h);\n    var x0=MPL,x1=w-MPR,span=Math.max(10,x1-x0),r,db,i,pxdb=span\/(DMAX-DMIN),sy=rows*MROW+4;\n    var bw=Math.max(18,Math.round(span*DMAX\/(DMAX-DMIN)));\n    if(bw!==ovlW){ovlW=bw;el.ovl.style.width=bw+'px';el.ovl.style.marginRight=MPR+'px';el.ovl.style.fontSize=bw<46?'8px':'10px';}\n    function MX(d){return x0+(Math.min(DMAX,Math.max(DMIN,d))-DMIN)\/(DMAX-DMIN)*span;}\n    var grad=g.createLinearGradient(x0,0,x1,0),st=[[-60,'#1d68bd'],[-36,'#2c8be6'],[-18,'#4db3ff'],[-9,'#93d2ff'],[-3,'#ffa550'],[0,'#ff7a1f'],[0.01,'#ff3b30'],[6,'#ff3b30']];\n    for(i=0;i<st.length;i++)grad.addColorStop((st[i][0]-DMIN)\/(DMAX-DMIN),st[i][1]);\n    var bh=MROW-6,pkH=Math.round(bh*0.62);\n    for(r=0;r<rows;r++){\n      var y=r*MROW+3,m=mv[r];\n      g.fillStyle='#0b0e13';g.fillRect(x0,y,span,bh);\n      g.globalAlpha=.13;g.fillStyle=grad;g.fillRect(x0,y,span,bh);g.globalAlpha=1;\n      g.fillStyle=grad;\n      if(m.pk>DMIN)g.fillRect(x0,y,MX(m.pk)-x0,pkH);\n      g.globalAlpha=.75;\n      if(m.rd>DMIN)g.fillRect(x0,y+pkH+2,MX(m.rd)-x0,bh-pkH-2);\n      g.globalAlpha=1;\n      if(m.hold>DMIN){g.fillStyle=m.hold>=0?'#ff3b30':'#ffffff';g.fillRect(Math.round(MX(m.hold))-1,y-1,2,bh+2);}\n      g.fillStyle='#8794a8';g.font='11px -apple-system,Segoe UI,Roboto,sans-serif';g.textAlign='left';g.textBaseline='middle';\n      g.fillText(rows===1?'M':(r?'R':'L'),10,y+bh\/2);\n    }\n    g.lineWidth=1;\n    for(db=DMIN;db<=DMAX;db++){\n      var gx=Math.round(MX(db))+.5,major=db%6===0,med=db%3===0;\n      if(major){g.strokeStyle=db===0?'rgba(255,59,48,.6)':'rgba(255,255,255,.12)';g.beginPath();g.moveTo(gx,2);g.lineTo(gx,sy);g.stroke();}\n      if(major||med||pxdb>=4){\n        g.strokeStyle=db>=0?'rgba(255,138,92,.9)':'rgba(200,210,230,.55)';\n        g.beginPath();g.moveTo(gx,sy);g.lineTo(gx,sy+(major?9:(med?6:3)));g.stroke();\n      }\n    }\n    var steps=[1,2,3,6,12],ls=12,q;\n    for(q=0;q<steps.length;q++){if(steps[q]*pxdb>=30){ls=steps[q];break;}}\n    g.font='10.5px -apple-system,Segoe UI,Roboto,sans-serif';g.textAlign='center';g.textBaseline='top';\n    for(db=DMIN;db<=DMAX;db++){\n      if(db%ls!==0)continue;\n      g.fillStyle=db>=0?'#ff8a5c':'#8794a8';\n      g.fillText(db>0?'+'+db:''+db,MX(db),sy+11);\n    }\n    g.textAlign='left';g.fillStyle='#8794a8';g.fillText('dB',6,sy+11);\n    if(mHover>=x0&&mHover<=x1){\n      var hd=DMIN+(mHover-x0)\/span*(DMAX-DMIN),hx=Math.round(mHover)+.5,tx=(hd>0?'+':'')+hd.toFixed(1)+' dB';\n      g.strokeStyle='rgba(255,255,255,.7)';g.beginPath();g.moveTo(hx,0);g.lineTo(hx,sy+9);g.stroke();\n      g.font='11px -apple-system,Segoe UI,Roboto,sans-serif';\n      var tw=g.measureText(tx).width+12,bx=Math.min(Math.max(2,hx-tw\/2),w-tw-2);\n      g.fillStyle='#0d1016';g.fillRect(bx,sy+9,tw,16);\n      g.strokeStyle='rgba(255,255,255,.5)';g.strokeRect(bx+.5,sy+9.5,tw-1,15);\n      g.fillStyle='#ffffff';g.textAlign='center';g.fillText(tx,bx+tw\/2,sy+12);\n    }\n  }\n  function pd(s,n){s=String(s);while(s.length<n)s=' '+s;return s;}\n  function updRead(thr){\n    el.ovl.classList.toggle('aew-lit',mOver);\n    if(thr){var nw=performance.now();if(nw-mLastUpd<100)return;mLastUpd=nw;}\n    var n=chN>1?2:1,i,t=[];\n    for(i=0;i<2;i++){\n      var m=mv[i];\n      t[i]=i<n?((n===1?'M':(i?'R':'L'))+' Peak '+pd(fdb(m.hold),5)+' \u00b7 Now '+pd(fdb(m.pk),5)+' \u00b7 RMS '+pd(fdb(m.rd),5)+' dB'):'';\n    }\n    t[2]='Max '+pd(mMax>0?fdb(l2d(mMax)):'-\u221e',5)+' dB';\n    var key=t.join('|');\n    if(key===mLastTxt)return;\n    mLastTxt=key;\n    el.m1.textContent=t[0];el.m2.textContent=t[1];el.m3.textContent=t[2];\n    el.ovl.textContent='OVER';\n  }\n  function meterTick(now){\n    mraf=0;\n    var dt=mLast?Math.min(0.1,(now-mLast)\/1000):0.016;mLast=now;\n    readMeters(dt,now);drawMeter();updRead(true);\n    var live=playing,i;\n    for(i=0;i<2;i++)if(mv[i].pk>DMIN+0.5||mv[i].rl>0.0003)live=true;\n    if(live)mraf=requestAnimationFrame(meterTick);else{mLast=0;updRead();}\n  }\n  function meterStart(){if(!mraf){mLast=0;mraf=requestAnimationFrame(meterTick);}}\n  \/* henter lyden fra lydfiler og fra video (mp4, m4v, mov, avi) *\/\n  async function decodeMedia(file){\n    var ext=((\/\\.([^.]+)$\/.exec(file.name)||[])[1]||'').toLowerCase(),isAvi=(ext==='avi'||file.type==='video\/x-msvideo');\n    var isVid=isAvi||\/^(mp4|m4v|mov|qt|3gp)$\/.test(ext)||\/^video\\\/\/.test(file.type);\n    if(!isVid){\n      try{return await decode(await readFile(file));}\n      catch(e){\n        if(ext==='aac'||file.type==='audio\/aac'||file.type==='audio\/x-aac'){\n          var ab=await readFile(file),ad=adtsFrames(new Uint8Array(ab));\n          if(ad.frames.length)return await aacWebCodecs({bytes:ab,sr:ad.sr,ch:ad.ch},ctx);\n        }\n        throw e;\n      }\n    }\n    if(!isAvi&&file.size<=150*1048576){try{return await decode(await readFile(file));}catch(e){}}\n    var dm=isAvi?await demuxAvi(file):await demuxMp4(file),b=null,err=null;\n    try{b=await decode(dm.bytes.slice(0));}catch(e){err=e;}\n    if(!b&&dm.codec==='aac')b=await aacWebCodecs(dm,ctx);\n    if(!b)throw err||new Error('The audio in this file could not be decoded.');\n    return trimEdit(b,dm);\n  }\n  \/* fjerner pre-roll (redigeringsliste) og overskydende lyd i enden *\/\n  function trimEdit(b,dm){\n    var skip=Math.max(0,dm.skip||0),n=b.length;\n    if(skip>=n-1)skip=0;\n    var len=dm.limit>0?Math.min(dm.limit,n-skip):n-skip;\n    if(len<=0||(skip===0&&len===n))return b;\n    var nb=ctx.createBuffer(b.numberOfChannels,len,b.sampleRate),c;\n    for(c=0;c<b.numberOfChannels;c++)nb.getChannelData(c).set(b.getChannelData(c).subarray(skip,skip+len));\n    return nb;\n  }\n  \/* 5.1 \/ 7.1 og andre flerkanalslyde nedmikses til stereo *\/\n  function downmix(b){\n    var nc=b.numberOfChannels;\n    if(nc<=2)return b;\n    var n=b.length,nb=ctx.createBuffer(2,n,b.sampleRate),L=nb.getChannelData(0),R=nb.getChannelData(1),i,c,s=Math.SQRT1_2,cl=[],cr=[];\n    for(c=0;c<nc;c++){cl.push(0);cr.push(0);}\n    if(nc>=6){cl[0]=1;cr[1]=1;cl[2]=s;cr[2]=s;cl[4]=s;cr[5]=s;if(nc>=8){cl[6]=s;cr[7]=s;}}\n    else if(nc===3){cl[0]=1;cr[1]=1;cl[2]=s;cr[2]=s;}\n    else if(nc===4){cl[0]=1;cr[1]=1;cl[2]=s;cr[3]=s;}\n    else{cl[0]=1;cr[1]=1;cl[2]=s;cr[2]=s;cl[3]=s;cr[4>=nc?3:4]=s;}\n    var sl=0,sr2=0;for(c=0;c<nc;c++){sl+=cl[c];sr2+=cr[c];}\n    var g=1\/Math.max(sl,sr2,1),d=[];\n    for(c=0;c<nc;c++)d.push(b.getChannelData(c));\n    for(i=0;i<n;i++){\n      var a=0,r=0;\n      for(c=0;c<nc;c++){var v=d[c][i];if(cl[c])a+=v*cl[c];if(cr[c])r+=v*cr[c];}\n      L[i]=a*g;R[i]=r*g;\n    }\n    return nb;\n  }\n  \/* tager en lydbuffer i brug som den \u00e5bne fil (indl\u00e6st fil eller ny testtone) *\/\n  \/* ---------- Hvilken fil kommer lyden fra? En kort liste af stykker f\u00f8lger lyden gennem alle redigeringer ---------- *\/\n  var srcRuns=[],srcNames=[],baseName='',shownName=null,dnEl=$('.aew-dn');\n  function srcId(name){var i=srcNames.indexOf(name);if(i<0){srcNames.push(name);i=srcNames.length-1;}return i;}\n  function srcTotal(runs){var t=0,i;runs=runs||srcRuns;for(i=0;i<runs.length;i++)t+=runs[i].n;return t;}\n  function srcNorm(runs){\n    var a=[],i,r;\n    for(i=0;i<runs.length;i++){r=runs[i];if(r.n<=0)continue;if(a.length&&a[a.length-1].id===r.id)a[a.length-1]={n:a[a.length-1].n+r.n,id:r.id};else a.push({n:r.n,id:r.id});}\n    return a;\n  }\n  function srcSlice(runs,s0,s1){\n    var out=[],p=0,i,r,a,b;\n    for(i=0;i<runs.length&&p<s1;i++){r=runs[i];a=Math.max(p,s0);b=Math.min(p+r.n,s1);if(b>a)out.push({n:b-a,id:r.id});p+=r.n;}\n    return out;\n  }\n  function srcDelRuns(runs,s0,s1){var t=srcTotal(runs);return srcNorm(srcSlice(runs,0,s0).concat(srcSlice(runs,s1,t)));}\n  function srcInsRuns(runs,at,add){var t=srcTotal(runs);return srcNorm(srcSlice(runs,0,at).concat(add,srcSlice(runs,at,t)));}\n  function srcFit(runs,m){\n    var t=srcTotal(runs),out=[],acc=0,done=0,i;\n    if(!runs.length||t<1)return [{n:m,id:-1}];\n    for(i=0;i<runs.length;i++){acc+=runs[i].n;var e=(i===runs.length-1)?m:Math.round(acc\/t*m);if(e>done)out.push({n:e-done,id:runs[i].id});done=e;}\n    return srcNorm(out);\n  }\n  function srcReset(len,name){srcNames=[name];srcRuns=len>0?[{n:len,id:0}]:[];}\n  function srcLabel(a,b){\n    var s0=Math.round(a*sr),s1=Math.round(b*sr);\n    if(!buf||srcTotal()!==buf.length||s1<=s0)return baseName;\n    var runs=srcSlice(srcRuns,s0,s1),cnt={},ids=[],i,best=-1,bn=-1;\n    for(i=0;i<runs.length;i++){var id=runs[i].id;if(cnt[id]===undefined){cnt[id]=0;ids.push(id);}cnt[id]+=runs[i].n;}\n    for(i=0;i<ids.length;i++)if(cnt[ids[i]]>bn){bn=cnt[ids[i]];best=ids[i];}\n    var nm=best>=0&&srcNames[best]?srcNames[best]:'Pasted audio';\n    return nm+(ids.length>1?'  +  '+(ids.length-1)+' more':'');\n  }\n  \/* tager en lydbuffer i brug som den \u00e5bne fil (indl\u00e6st fil eller ny testtone) *\/\n  function adopt(b,name,tag){\n      buf=b;sr=b.sampleRate;dur=b.duration;chN=Math.min(2,b.numberOfChannels);MIN=Math.min(1\/b.sampleRate,dur\/2);\n      fileName=name.replace(\/\\.[^.]+$\/,'')||'audio';\n      kw=null;buildBins();computeSnap();try{srcReset(b.length,name);}catch(_){srcRuns=[];srcNames=[name];}baseName=name;shownName=null;\n      trimS=0;trimE=dur;pos=0;CH=[{fi:0,fo:0,env:[]},{fi:0,fo:0,env:[]}];splitCh=false;selPt=null;dragPt=null;splitUI();markers=[];selMk=null;dragMk=null;mkUI();cuts=[];cutHover=-1;sgHover=null;sgDrag=null;segSel=null;hist=[];redoStack=[];pend=null;hl=null;hlx=null;selR=null;histUI();resetMeter();var spo=el.chm.querySelector('option[value=\"split\"]');if(spo)spo.disabled=chN<2;el.chm.value=chN<2?'mono':'st';\n      meas={peak:peakIn(0,dur),lufs:null};\n      root.classList.remove('aew-blank');el.work.inert=false;ACTIVE=root;\n      el.drop.classList.add('aew-has');\n      try{(dnEl||$('.aew-dn')).textContent=name;}catch(_){}shownName=name;\n      $('.aew-ds').textContent=(tag||'')+' \u00b7 '+fmt(dur,1)+' \u00b7 '+fN(Math.round(sr))+' Hz \u00b7 '+(b.numberOfChannels>1?'stereo':'mono');\n      el.tt.textContent=fL(dur);\n      setTool('sel');envUI();\n      view={s:0,sp:dur};setView(0,dur);trimUI();applyGain(true);frameOnce();\n      kw=null;kwId++;selActive=false;\n      say('');\n  }\n  async function load(file){\n    if(!file)return;\n    impNames=[file.name];\n    if(!\/^(audio|video)\\\/\/.test(file.type)&&!\/\\.(mp3|wav|m4a|aac|ogg|flac|mp4|m4v|mov|avi)$\/i.test(file.name)){say('Unsupported file. Use an audio file (MP3, WAV, M4A, AAC, OGG, FLAC) or a video file (MP4, M4V, MOV, AVI).',true);return;}\n    var id=++loadId;\n    pause();el.derr.hidden=true;\n    try{\n      ensureCtx();\n      var b=downmix(await decodeMedia(file));\n      if(id!==loadId)return;\n      adopt(b,file.name,(\/^(mp4|m4v|mov|avi)$\/i.test(((\/\\.([^.]+)$\/.exec(file.name)||[])[1]||''))||\/^video\\\/\/.test(file.type)?' \u00b7 video':''));\n    }catch(e){\n      if(id===loadId)say('Could not decode the file'+(e&&e.message?': '+e.message:'.'),true);\n    }\n  }\n  \/* ---------- Import\u00e9r flere filer: nye filer l\u00e6gges bagerst som egne segmenter ---------- *\/\n  var impBusy=false,impRes=null,impNames=[];\n  function okFile(f){return \/^(audio|video)\\\/\/.test(f.type)||\/\\.(mp3|wav|m4a|aac|ogg|flac|mp4|m4v|mov|avi)$\/i.test(f.name);}\n  function natCmp(a,b){return a.name.localeCompare(b.name,undefined,{numeric:true,sensitivity:'base'});}\n  function askImport(files){\n    return new Promise(function(res){\n      impRes=res;\n      el.imtxt.textContent=files.length===1?'Add this file after the current audio as a new section, or replace everything you have now?':'Add these '+files.length+' files after the current audio, each as its own section, or replace everything you have now?';\n      var names=files.slice(0,6).map(function(f){return f.name;});\n      if(files.length>6)names.push('\u2026 and '+(files.length-6)+' more');\n      el.imlist.textContent=names.join('  \\u00b7  ');\n      el.imm.hidden=false;\n      try{el.imadd.focus();}catch(_){}\n      setTimeout(function(){try{el.imadd.focus();}catch(_){}},30);\n    });\n  }\n  function closeImp(r){el.imm.hidden=true;var f=impRes;impRes=null;if(f)f(r);}\n  async function adaptBuffer(b){\n    var nc=buf.numberOfChannels,n,c,i,data=[],note=false;\n    if(Math.abs(b.sampleRate-sr)>0.5){\n      var OAC=window.OfflineAudioContext||window.webkitOfflineAudioContext;\n      var n2=Math.max(1,Math.round(b.length*sr\/b.sampleRate)),oc=new OAC(b.numberOfChannels,n2,sr),s=oc.createBufferSource();\n      s.buffer=b;s.connect(oc.destination);s.start();b=await oc.startRendering();\n    }\n    n=b.length;\n    var src=[];for(c=0;c<b.numberOfChannels;c++)src.push(b.getChannelData(c));\n    if(nc===1){\n      if(src.length===1)data=[src[0].slice()];\n      else{var mm=new Float32Array(n);for(i=0;i<n;i++)mm[i]=(src[0][i]+src[1][i])*0.5;data=[mm];note=true;}\n    }else data=[src[0].slice(),(src.length>1?src[1]:src[0]).slice()];\n    return {data:data,n:n,note:note};\n  }\n  async function appendFile(file){\n    var b;\n    try{b=downmix(await decodeMedia(file));}\n    catch(e){say('Could not decode '+file.name+(e&&e.message?': '+e.message:'.'),true);return false;}\n    var a=await adaptBuffer(b);\n    if(!buf||drag)return false;\n    if(playing)pause();\n    var st=snap(),at=buf.length,t=at\/sr,len=a.n\/sr,wasWhole=trimS<=0.0005&&trimE>=dur-0.0005;\n    insertSamples(at,a.data);srcRuns=srcInsRuns(srcRuns,at,[{n:a.n,id:srcId(file.name)}]);\n    if(t>0.5\/sr){cuts.push(t);cuts.sort(function(x,y){return x-y;});}\n    if(wasWhole){trimS=0;trimE=t+len;}\n    selPt=null;selActive=false;pos=t;\n    pushHist(st,{type:'ins',at:at,len:a.n,svA:null,svB:null});\n    hl={s:t,e:t+len};\n    afterStruct();\n    impNames.push(file.name);\n    baseName=impNames[0]+(impNames.length>1?'  +  '+(impNames.length-1)+' more':'');shownName=null;dnEl.textContent=baseName;shownName=baseName;\n    $('.aew-ds').textContent=' \u00b7 '+fmt(dur,1)+' \u00b7 '+fN(Math.round(sr))+' Hz \u00b7 '+(chN>1?'stereo':'mono');\n    cutBtnUI();\n    if(a.note)say('Note: '+file.name+' is stereo and was mixed down to mono to match the current audio.',true);\n    return true;\n  }\n  function importSafe(list){\n    var p;\n    try{p=importFiles(list);}catch(e){say('Could not import the file: '+(e&&e.message?e.message:e),true);impBusy=false;return;}\n    if(p&&p.catch)p.catch(function(e){impBusy=false;say('Could not import the file: '+(e&&e.message?e.message:e),true);});\n  }\n  async function importFiles(list){\n    var all=Array.prototype.slice.call(list||[]),files=all.filter(okFile),bad=all.length-files.length;\n    if(!files.length){if(all.length)say('Unsupported file. Use an audio file (MP3, WAV, M4A, AAC, OGG, FLAC) or a video file (MP4, M4V, MOV, AVI).',true);return;}\n    if(impBusy){say('Still importing \u2013 wait a moment.',true);return;}\n    if(files.length>1)files.sort(natCmp);\n    impBusy=true;\n    try{\n      var replace=!buf,i0=0;\n      if(buf){\n        var ch=await askImport(files);\n        if(!ch)return;\n        replace=(ch==='replace');\n      }\n      if(replace){\n        await load(files[0]);\n        if(!buf)return;\n        impNames=[files[0].name];i0=1;\n      }\n      for(var i=i0;i<files.length;i++){await appendFile(files[i]);}\n      if(bad)say(bad+' unsupported file'+(bad>1?'s were':' was')+' skipped.',true);\n    }finally{impBusy=false;}\n  }\n  \/* ---------- Eksport ---------- *\/\n  function save(blob,name){\n    var u=URL.createObjectURL(blob),a=document.createElement('a');\n    a.href=u;a.download=name;document.body.appendChild(a);a.click();document.body.removeChild(a);\n    setTimeout(function(){URL.revokeObjectURL(u);},4000);\n  }\n  function save(blob,name){\n    var u=URL.createObjectURL(blob),a=document.createElement('a');\n    a.href=u;a.download=name;document.body.appendChild(a);a.click();document.body.removeChild(a);\n    setTimeout(function(){URL.revokeObjectURL(u);},4000);\n  }\n  \/* sample rate-konvertering (Blackman-Harris-vinduet sinc, anti-alias ved nedsampling) *\/\n  var RS_L=16,RS_Q=256;\n  function sincTab(fc){\n    var L=Math.ceil(RS_L\/fc),n=2*L*RS_Q+2,t=new Float32Array(n),i;\n    for(i=0;i<n;i++){\n      var d=i\/RS_Q-L,x=Math.PI*fc*d,s=Math.abs(x)<1e-9?1:Math.sin(x)\/x,u=(d+L)\/(2*L);\n      var w=0.35875-0.48829*Math.cos(2*Math.PI*u)+0.14128*Math.cos(4*Math.PI*u)-0.01168*Math.cos(6*Math.PI*u);\n      t[i]=fc*s*w;\n    }\n    return {t:t,L:L};\n  }\n  async function resampleSinc(chs,srcRate,dstRate){\n    var ratio=srcRate\/dstRate,fc=Math.min(1,dstRate\/srcRate)*0.97,tb=sincTab(fc),L=tb.L,tab=tb.t;\n    var nIn=chs[0].length,nOut=Math.max(1,Math.floor(nIn\/ratio)),out=[],c,j,k;\n    for(c=0;c<chs.length;c++){\n      var a=chs[c],o=new Float32Array(nOut);\n      for(j=0;j<nOut;j++){\n        var pos=j*ratio,i0=Math.floor(pos),fr=pos-i0,acc=0,wsum=0;\n        for(k=-L+1;k<=L;k++){\n          var idx=i0+k,tp=(fr-k+L)*RS_Q,ti=Math.floor(tp),w=tab[ti]+(tab[ti+1]-tab[ti])*(tp-ti);\n          wsum+=w;\n          if(idx>=0&&idx<nIn)acc+=a[idx]*w;\n        }\n        o[j]=wsum>1e-9?acc\/wsum:0;\n        if((j&262143)===0)await tick();\n      }\n      out.push(o);\n      await tick();\n    }\n    return out;\n  }\n  function makeRenderer(idx,mix){\n    var s0=expRange?expRange[0]:Math.max(0,Math.round(trimS*sr)),s1=expRange?expRange[1]:Math.min(buf.length,Math.round(trimE*sr)),n=s1-s0;\n    if(n<1)throw new Error('The selected region is empty.');\n    idx=idx||(chN>1?[0,1]:[0]);\n    var chs=[],c,ng=gainInfo.g,gfs=[];\n    for(c=0;c<idx.length;c++){chs.push(buf.getChannelData(idx[c]));gfs.push(mkGain(s0\/sr,n\/sr,idx[c]));}\n    var ni=chs.length,no=mix?1:ni,lcp=null;\n    if(lcOn){lcp=[];for(c=0;c<ni;c++)lcp.push(lcProcessor(lcOrd,lcHz));}\n    return {n:n,nc:no,sr:sr,chunk:function(i0,m){\n      var out=[],i,x,cc;\n      for(cc=0;cc<no;cc++)out.push(new Float32Array(m));\n      for(i=0;i<m;i++){\n        var si=s0+i0+i,tt=si\/sr,acc=0;\n        for(cc=0;cc<ni;cc++){\n          x=chs[cc][si]*ng*gfs[cc](tt);\n          if(lcp)x=lcp[cc](x);\n          if(mix)acc+=x;else out[cc][i]=x>1?1:(x<-1?-1:x);\n        }\n        if(mix){acc\/=ni;out[0][i]=acc>1?1:(acc<-1?-1:acc);}\n      }\n      return out;\n    }};\n  }\n  async function prepRender(idx,mix,dst){\n    var R=makeRenderer(idx,mix);\n    if(dst===sr)return R;\n    var n=R.n,nc=R.nc,chs=[],c,i,STEP=1048576;\n    for(c=0;c<nc;c++)chs.push(new Float32Array(n));\n    for(i=0;i<n;i+=STEP){\n      var m=Math.min(STEP,n-i),ck=R.chunk(i,m);\n      for(c=0;c<nc;c++)chs[c].set(ck[c],i);\n      await tick();\n    }\n    say('Rendering \u2026');\n    var rs=await resampleSinc(chs,sr,dst);\n    return {n:rs[0].length,nc:nc,sr:dst,chunk:function(i0,m){\n      var res=[],cc,k;\n      for(cc=0;cc<nc;cc++){\n        var s=rs[cc],o=new Float32Array(m);\n        for(k=0;k<m;k++){var v=s[i0+k];o[k]=v>1?1:(v<-1?-1:v);}\n        res.push(o);\n      }\n      return res;\n    }};\n  }\n  \/* ---------- Metadata (tags): ID3v2.3 til MP3, RIFF INFO til WAV\/AVI, standard tekst-chunks til AIFF ---------- *\/\n  var META={title:'',artist:'',album:'',albumArtist:'',year:'',track:'',trackTotal:'',disc:'',genre:'',composer:'',publisher:'',copyright:'',bpm:'',isrc:'',comment:'',cover:null,coverUrl:''};\n  var MT_FMT={title:'wav aiff avi mp3',artist:'wav aiff avi mp3',album:'wav avi mp3',albumArtist:'mp3',year:'wav avi mp3',track:'mp3',disc:'mp3',genre:'wav avi mp3',composer:'mp3',publisher:'mp3',copyright:'wav aiff avi mp3',bpm:'mp3',isrc:'mp3',comment:'wav aiff avi mp3'};\n  var MT_LBL={title:'Title',artist:'Artist',album:'Album',albumArtist:'Album artist',year:'Year',track:'Track',disc:'Disc',genre:'Genre',composer:'Composer',publisher:'Publisher',copyright:'Copyright',bpm:'BPM',isrc:'ISRC',comment:'Comment'};\n  var MT_NOTE={wav:'WAV: the essential tags, stored as standard RIFF INFO tags (title, artist, album, year, genre, comment, copyright).',avi:'AVI: the essential tags, stored as standard RIFF INFO tags (title, artist, album, year, genre, comment, copyright).',aiff:'AIFF: the standard AIFF text tags (title, artist, copyright, comment).',mp3:'MP3: ID3v2.3 tags, plus a JPG cover (front cover). ID3v2.3 is read by virtually every player.'};\n  function mtFmt(){return el.fmt.value||'wav';}\n  function mtOn(k,f){return (' '+MT_FMT[k]+' ').indexOf(' '+f+' ')>=0;}\n  function mtFor(f){\n    var o={},k,v;\n    for(k in MT_FMT){if(!mtOn(k,f))continue;v=String(META[k]==null?'':META[k]).trim();if(v)o[k]=v;}\n    if(f==='mp3'){\n      var tt=String(META.trackTotal||'').trim();\n      if(o.track&&tt)o.track=o.track+'\/'+tt;\n      if(META.cover)o.cover=META.cover;\n    }\n    return o;\n  }\n  function mtSummary(f){\n    var m=mtFor(f),a=[],k;\n    for(k in MT_LBL)if(m[k])a.push(MT_LBL[k]);\n    if(m.cover)a.push('cover');\n    return a.length?a.join(', '):'None';\n  }\n  function dmSum(){el.dmsum.textContent=mtSummary(mtFmt());el.dmsum.title=el.dmsum.textContent;}\n  function mtCoverUI(){\n    el.mtimg.style.backgroundImage=META.coverUrl?'url(\"'+META.coverUrl+'\")':'none';\n    el.mtrm.disabled=!META.cover||mtFmt()!=='mp3';\n  }\n  function mtFill(){\n    Array.prototype.forEach.call($$('.aew-mti'),function(i){i.value=META[i.getAttribute('data-k')]||'';});\n  }\n  function mtRead(){\n    Array.prototype.forEach.call($$('.aew-mti'),function(i){META[i.getAttribute('data-k')]=i.value;});\n  }\n  function mtShow(){\n    var f=mtFmt();\n    el.mtfmt.textContent=MT_NOTE[f]||'';\n    Array.prototype.forEach.call($$('.aew-mtf'),function(l){l.hidden=!mtOn(l.getAttribute('data-k'),f);});\n    var mp=(f==='mp3');\n    el.mtcov.hidden=false;el.mtcov.classList.toggle('aew-dis',!mp);\n    el.mtpick.disabled=!mp;\n    el.mtcn.textContent=mp?'JPG, PNG or WebP. It is cropped to a square and saved as a JPG of up to 1000 \\u00d7 1000 px.':'Cover images are saved in MP3 files. Set Format to MP3 (in Export audio) to add a cover.';\n  }\n  function mtOpen(){\n    mtFill();mtShow();mtCoverUI();el.mtm.hidden=false;\n    setTimeout(function(){var i=el.mtm.querySelector('.aew-mtf:not([hidden]) input');if(i){try{i.focus();}catch(_){}}},30);\n  }\n  function mtClose(apply){\n    if(apply)mtRead();\n    el.mtm.hidden=true;dmSum();\n  }\n  async function mtCover(file){\n    var bmp=null;\n    try{bmp=await createImageBitmap(file);}catch(e){\n      bmp=await new Promise(function(res,rej){var im=new Image(),u=URL.createObjectURL(file);im.onload=function(){URL.revokeObjectURL(u);res(im);};im.onerror=function(){URL.revokeObjectURL(u);rej(new Error('Could not read that image.'));};im.src=u;});\n    }\n    var w=bmp.width||bmp.naturalWidth,hh=bmp.height||bmp.naturalHeight,s=Math.min(w,hh),out=Math.min(s,1000),cv=document.createElement('canvas');\n    cv.width=cv.height=out;\n    var g=cv.getContext('2d');g.fillStyle='#ffffff';g.fillRect(0,0,out,out);g.drawImage(bmp,(w-s)\/2,(hh-s)\/2,s,s,0,0,out,out);\n    var blob=await new Promise(function(r){cv.toBlob(r,'image\/jpeg',0.9);});\n    if(!blob)throw new Error('Could not convert that image to JPG.');\n    var bytes=new Uint8Array(await blob.arrayBuffer());\n    if(META.coverUrl){try{URL.revokeObjectURL(META.coverUrl);}catch(_){}}\n    META.cover=bytes;META.coverUrl=URL.createObjectURL(blob);\n  }\n  function u8cat(a){var n=0,i,o,p=0;for(i=0;i<a.length;i++)n+=a[i].length;o=new Uint8Array(n);for(i=0;i<a.length;i++){o.set(a[i],p);p+=a[i].length;}return o;}\n  function mUtf8(s){return new TextEncoder().encode(s);}\n  function mLatin(s){var o=new Uint8Array(s.length),i,c;for(i=0;i<s.length;i++){c=s.charCodeAt(i);o[i]=c<256?c:63;}return o;}\n  function mIsLatin(s){return \/^[\\u0000-\\u00ff]*$\/.test(s);}\n  function mChunk(id,data,be){var n=data.length,o=new Uint8Array(8+n+(n&1)),dv=new DataView(o.buffer);o.set(bstr(id),0);dv.setUint32(4,n,!be);o.set(data,8);return o;}\n  function infoList(m){\n    var map=[['title','INAM'],['artist','IART'],['album','IPRD'],['year','ICRD'],['genre','IGNR'],['comment','ICMT'],['copyright','ICOP']],subs=[];\n    map.forEach(function(p){if(m[p[0]]){var b=mUtf8(m[p[0]]),z=new Uint8Array(b.length+1);z.set(b);subs.push(mChunk(p[1],z,false));}});\n    if(!subs.length)return new Uint8Array(0);\n    return mChunk('LIST',u8cat([bstr('INFO')].concat(subs)),false);\n  }\n  function aiffText(m){\n    var map=[['title','NAME'],['artist','AUTH'],['copyright','(c) '],['comment','ANNO']],subs=[];\n    map.forEach(function(p){if(m[p[0]]){var s=m[p[0]];subs.push(mChunk(p[1],mIsLatin(s)?mLatin(s):mUtf8(s),true));}});\n    return u8cat(subs);\n  }\n  function id3Frame(id,data){var n=data.length,o=new Uint8Array(10+n),dv=new DataView(o.buffer);o.set(bstr(id),0);dv.setUint32(4,n,false);o.set(data,10);return o;}\n  function id3Enc(s){\n    if(mIsLatin(s))return {e:0,b:mLatin(s)};\n    var b=new Uint8Array(2+s.length*2),i,c;b[0]=0xFF;b[1]=0xFE;\n    for(i=0;i<s.length;i++){c=s.charCodeAt(i);b[2+2*i]=c&255;b[3+2*i]=c>>8;}\n    return {e:1,b:b};\n  }\n  function id3Text(id,s){var t=id3Enc(s);return id3Frame(id,u8cat([new Uint8Array([t.e]),t.b]));}\n  function id3Tag(m){\n    var fr=[],yr=m.year?m.year.replace(\/\\D\/g,'').slice(0,4):'',bp=m.bpm?m.bpm.replace(\/\\D\/g,''):'';\n    if(m.title)fr.push(id3Text('TIT2',m.title));\n    if(m.artist)fr.push(id3Text('TPE1',m.artist));\n    if(m.album)fr.push(id3Text('TALB',m.album));\n    if(m.albumArtist)fr.push(id3Text('TPE2',m.albumArtist));\n    if(yr.length===4)fr.push(id3Text('TYER',yr));\n    if(m.track)fr.push(id3Text('TRCK',m.track));\n    if(m.disc)fr.push(id3Text('TPOS',m.disc));\n    if(m.genre)fr.push(id3Text('TCON',m.genre));\n    if(m.composer)fr.push(id3Text('TCOM',m.composer));\n    if(m.publisher)fr.push(id3Text('TPUB',m.publisher));\n    if(m.copyright)fr.push(id3Text('TCOP',m.copyright));\n    if(bp)fr.push(id3Text('TBPM',bp));\n    if(m.isrc)fr.push(id3Text('TSRC',m.isrc));\n    if(m.comment){var t=id3Enc(m.comment),d=t.e===1?new Uint8Array([0xFF,0xFE,0,0]):new Uint8Array([0]);fr.push(id3Frame('COMM',u8cat([new Uint8Array([t.e]),bstr('eng'),d,t.b])));}\n    if(m.cover)fr.push(id3Frame('APIC',u8cat([new Uint8Array([0]),bstr('image\/jpeg'),new Uint8Array([0,3,0]),m.cover])));\n    if(!fr.length)return null;\n    var body=u8cat(fr),n=body.length,hd=new Uint8Array(10);\n    hd.set(bstr('ID3'),0);hd[3]=3;hd[4]=0;hd[5]=0;hd[6]=(n>>21)&127;hd[7]=(n>>14)&127;hd[8]=(n>>7)&127;hd[9]=n&127;\n    return u8cat([hd,body]);\n  }\n  async function encWav(R,bits,meta){\n    var n=R.n,nc=R.nc,bps=bits\/8,dl=n*nc*bps,info=infoList(meta||{}),padd=dl&1,ab=new ArrayBuffer(44+dl+padd+info.length),dv=new DataView(ab);\n    function ws(o,s){for(var i=0;i<s.length;i++)dv.setUint8(o+i,s.charCodeAt(i));}\n    ws(0,'RIFF');dv.setUint32(4,36+dl+padd+info.length,true);ws(8,'WAVE');ws(12,'fmt ');dv.setUint32(16,16,true);dv.setUint16(20,1,true);dv.setUint16(22,nc,true);\n    var rate=R.sr||sr;dv.setUint32(24,rate,true);dv.setUint32(28,rate*nc*bps,true);dv.setUint16(32,nc*bps,true);dv.setUint16(34,bits,true);ws(36,'data');dv.setUint32(40,dl,true);\n    var o=44,CH=131072;\n    for(var i0=0;i0<n;i0+=CH){\n      var m=Math.min(CH,n-i0),ck=R.chunk(i0,m),i,c;\n      for(i=0;i<m;i++){\n        for(c=0;c<nc;c++){\n          var x=ck[c][i];x=x>1?1:(x<-1?-1:x);\n          if(bits===16){dv.setInt16(o,Math.round(x<0?x*32768:x*32767),true);o+=2;}\n          else{var v=Math.round(x<0?x*8388608:x*8388607);dv.setUint8(o,v&255);dv.setUint8(o+1,(v>>8)&255);dv.setUint8(o+2,(v>>16)&255);o+=3;}\n        }\n      }\n      say('Exporting WAV \u2026 '+Math.round((i0+m)\/n*100)+'%');\n      await tick();\n    }\n    if(info.length)new Uint8Array(ab).set(info,44+dl+padd);\n    return new Blob([ab],{type:'audio\/wav'});\n  }\n  async function encAiff(R,bits,meta){\n    var n=R.n,nc=R.nc,bps=bits\/8,dl=n*nc*bps,pad=dl&1,txt=aiffText(meta||{}),ab=new ArrayBuffer(12+26+16+dl+pad+txt.length),dv=new DataView(ab),u8=new Uint8Array(ab);\n    u8.set(bstr('FORM'),0);dv.setUint32(4,ab.byteLength-8,false);u8.set(bstr('AIFF'),8);\n    u8.set(bstr('COMM'),12);dv.setUint32(16,18,false);dv.setUint16(20,nc,false);dv.setUint32(22,n,false);dv.setUint16(26,bits,false);u8.set(aiffRate(R.sr||sr),28);\n    u8.set(bstr('SSND'),38);dv.setUint32(42,8+dl,false);dv.setUint32(46,0,false);dv.setUint32(50,0,false);\n    var o=54,CHK=131072;\n    for(var i0=0;i0<n;i0+=CHK){\n      var m=Math.min(CHK,n-i0),ck=R.chunk(i0,m),i,c;\n      for(i=0;i<m;i++){\n        for(c=0;c<nc;c++){\n          var x=ck[c][i];x=x>1?1:(x<-1?-1:x);\n          if(bits===16){dv.setInt16(o,Math.round(x<0?x*32768:x*32767),false);o+=2;}\n          else{var v=Math.round(x<0?x*8388608:x*8388607);dv.setUint8(o,(v>>16)&255);dv.setUint8(o+1,(v>>8)&255);dv.setUint8(o+2,v&255);o+=3;}\n        }\n      }\n      await tick();\n    }\n    if(txt.length)u8.set(txt,12+26+16+dl+pad);\n    return new Blob([ab],{type:'audio\/aiff'});\n  }\n  \/* AVI (kun lyd): ukomprimeret PCM i en RIFF\/AVI-container, som afspillere og redigeringsprogrammer kan \u00e5bne *\/\n  async function encAvi(R,bits,meta){\n    var n=R.n,nc=R.nc,bps=bits\/8,ba=nc*bps,rate=Math.round(R.sr||sr),CH=Math.max(1,Math.round(rate\/25)),nch=Math.ceil(n\/CH),i,c;\n    var sizes=[],sum=0;\n    for(i=0;i<nch;i++){var m0=Math.min(CH,n-i*CH),sz=m0*ba;sizes.push(sz);sum+=8+sz+(sz&1);}\n    var hdrlLen=4+(8+56)+(8+4+(8+56)+(8+16)),moviLen=4+sum,idxLen=16*nch,info=infoList(meta||{});\n    var total=12+(8+hdrlLen)+info.length+(8+moviLen)+(8+idxLen);\n    if(total>4000000000)throw new Error('AVI files are limited to 4 GB. Export a shorter selection or use WAV.');\n    var ab=new ArrayBuffer(total),dv=new DataView(ab),u8=new Uint8Array(ab),p=0;\n    function w32(v){dv.setUint32(p,v>>>0,true);p+=4;}\n    function w16(v){dv.setUint16(p,v&65535,true);p+=2;}\n    function wid(s){u8.set(bstr(s),p);p+=4;}\n    wid('RIFF');w32(total-8);wid('AVI ');\n    wid('LIST');w32(hdrlLen);wid('hdrl');\n    wid('avih');w32(56);w32(Math.round(CH\/rate*1e6));w32(rate*ba);w32(0);w32(0x10);w32(nch);w32(0);w32(1);w32(Math.max.apply(null,sizes));w32(0);w32(0);for(i=0;i<4;i++)w32(0);\n    wid('LIST');w32(4+(8+56)+(8+16));wid('strl');\n    wid('strh');w32(56);wid('auds');w32(0);w32(0);w16(0);w16(0);w32(0);w32(ba);w32(rate*ba);w32(0);w32(n);w32(Math.max.apply(null,sizes));w32(0xFFFFFFFF);w32(ba);w16(0);w16(0);w16(0);w16(0);\n    wid('strf');w32(16);w16(1);w16(nc);w32(rate);w32(rate*ba);w16(ba);w16(bits);\n    if(info.length){u8.set(info,p);p+=info.length;}\n    wid('LIST');w32(moviLen);wid('movi');\n    var moviStart=p-4,offs=[];\n    for(i=0;i<nch;i++){\n      var i0=i*CH,m=Math.min(CH,n-i0),ck=R.chunk(i0,m),sz2=sizes[i];\n      offs.push(p-moviStart);\n      wid('00wb');w32(sz2);\n      var k;\n      for(k=0;k<m;k++){\n        for(c=0;c<nc;c++){\n          var x=ck[c][k];x=x>1?1:(x<-1?-1:x);\n          if(bits===16){dv.setInt16(p,Math.round(x<0?x*32768:x*32767),true);p+=2;}\n          else{var v=Math.round(x<0?x*8388608:x*8388607);dv.setUint8(p,v&255);dv.setUint8(p+1,(v>>8)&255);dv.setUint8(p+2,(v>>16)&255);p+=3;}\n        }\n      }\n      if(sz2&1)p+=1;\n      if((i&63)===63){say('Exporting AVI \u2026 '+Math.round((i+1)\/nch*100)+'%');await tick();}\n    }\n    wid('idx1');w32(idxLen);\n    for(i=0;i<nch;i++){wid('00wb');w32(0x10);w32(offs[i]);w32(sizes[i]);}\n    return new Blob([ab],{type:'video\/x-msvideo'});\n  }\n  async function encMp3(Lm,R,kbps,meta){\n    var rate=R.sr||sr;\n    if([32000,44100,48000].indexOf(rate)<0)throw new Error('MP3 does not support '+Math.round(rate)+' Hz here \u2013 use WAV.');\n    var n=R.n,nc=R.nc,enc=new Lm.Mp3Encoder(nc,rate,kbps),out=[],BL=1152*32;\n    function toI(a){var o=new Int16Array(a.length),i,x;for(i=0;i<a.length;i++){x=a[i];o[i]=Math.round(x<0?x*32768:x*32767);}return o;}\n    for(var i0=0;i0<n;i0+=BL){\n      var m=Math.min(BL,n-i0),ck=R.chunk(i0,m),l=toI(ck[0]),r=nc>1?toI(ck[1]):null,b=nc>1?enc.encodeBuffer(l,r):enc.encodeBuffer(l);\n      if(b&&b.length)out.push(new Int8Array(b));\n      say('Exporting MP3 \u2026 '+Math.round((i0+m)\/n*100)+'%');\n      await tick();\n    }\n    var f=enc.flush();if(f&&f.length)out.push(new Int8Array(f));\n    var tag=id3Tag(meta||{});\n    return new Blob(tag?[tag].concat(out):out,{type:'audio\/mpeg'});\n  }\n  \/* \"Gem som\": rigtig arkivdialog hvor browseren kan (Chrome\/Edge\/Opera), ellers en navne-dialog i widgetten *\/\n  function cleanName(v,ext){\n    v=String(v||'').replace(\/[\\\\\\\/:*?\"<>|\\u0000-\\u001f]\/g,'').trim().replace(\/[. ]+$\/,'');\n    v=v.replace(new RegExp('\\\\.'+ext+'$','i'),'');\n    if(!v)v=fileName+'-edit';\n    return v+'.'+ext;\n  }\n  function closeDlg(r){el.dlg.hidden=true;var f=dlgRes;dlgRes=null;if(f)f(r);}\n  var expSel='w',expRange=null,dlgOpts=null;\n  function sectionRanges(){\n    if(!buf||!cuts.length)return [];\n    var b=[0],i,out=[];\n    for(i=0;i<cuts.length;i++)b.push(Math.round(cuts[i]*sr));\n    b.push(buf.length);\n    for(i=0;i<b.length-1;i++)if(b[i+1]-b[i]>=1)out.push([b[i],b[i+1]]);\n    return out;\n  }\n  function exportSelSamples(){\n    if(!buf)return null;\n    var a,b;\n    if(segSel){a=segSel.a;b=segSel.b;}\n    else if(!linkOn&&selR){a=selR.a;b=selR.b;}\n    else if(trimS>0.0005||trimE<dur-0.0005){a=trimS;b=trimE;}\n    else return null;\n    var s0=Math.max(0,Math.round(a*sr)),s1=Math.min(buf.length,Math.round(b*sr));\n    return s1-s0>=1?[s0,s1]:null;\n  }\n  function rgUI(){\n    var sel=exportSelSamples(),secs=sectionRanges();\n    if(!sel&&expSel==='s')expSel='w';\n    if(secs.length<2&&expSel==='a')expSel='w';\n    Array.prototype.forEach.call($$('.aew-rg'),function(b){var on=b.getAttribute('data-r')===expSel;b.classList.toggle('aew-on',on);b.setAttribute('aria-pressed',on?'true':'false');});\n    el.rgs.classList.toggle('aew-blocked',!sel);el.rgs.setAttribute('aria-disabled',sel?'false':'true');\n    el.rga.classList.toggle('aew-blocked',secs.length<2);el.rga.setAttribute('aria-disabled',secs.length<2?'true':'false');\n    var s0=(expSel==='s'&&sel)?sel[0]:0,s1=(expSel==='s'&&sel)?sel[1]:(buf?buf.length:0),len=(s1-s0)\/sr;\n    var lt=unit==='s'?fN(s1-s0)+' samples':fmtP(len,3);\n    if(expSel==='a'){\n      var nf=secs.length*((el.chm.value==='split'&&chN>1)?2:1);\n      el.drsum.textContent=secs.length+' sections  \\u00b7  '+nf+' files  \\u00b7  '+(fsPick('showDirectoryPicker')?'saved into a folder you choose':'downloaded as one ZIP');\n    }else el.drsum.textContent=expSel==='s'?(lt+'  \\u00b7  '+fU(s0\/sr)+' \\u2013 '+fU(s1\/sr)):('Entire file  \\u00b7  '+lt+(sel?'':'  \\u00b7  no selection'));\n    if(dlgOpts&&dlgOpts.range){\n      var batch=expSel==='a';\n      el.dlgNf.hidden=!(dlgOpts.showName||batch);\n      if(!el.dlgNf.hidden)el.dlgExt.textContent=batch?(dlgOpts.batchExt||''):(dlgOpts.extLabel||'');\n    }\n  }\n  function openDlg(o){\n    return new Promise(function(res){\n      if(dlgRes)closeDlg(null);\n      dlgRes=res;dlgOpts=o;if(o.fm)dlgFm=o.fm;\n      el.dlgT.textContent=o.title;el.dlgNote.textContent=o.note||'';el.dlgNote.hidden=!o.note;el.dlgOk.textContent=o.ok;\n      el.dlgNf.hidden=!o.showName;el.dmeta.hidden=!o.meta;if(o.meta)dmSum();\n      el.drng.hidden=!o.range;if(o.range)rgUI();\n      if(o.name!=null){el.dlgName.value=o.name;}\n      if(o.showName){el.dlgExt.textContent=o.extLabel;}\n      el.dlg.hidden=false;\n      setTimeout(function(){if(o.showName){el.dlgName.focus();el.dlgName.select();}else el.dlgOk.focus();},30);\n    });\n  }\n  function askName(sugg,fm,label){\n    return openDlg({title:'Save as',note:'',ok:'Save',name:sugg.replace(\/\\.[^.]+$\/,''),extLabel:label||('.'+fm.ext),showName:true,fm:fm});\n  }\n  function askConfirm(title,note,ok){\n    return openDlg({title:title,note:note,ok:ok,showName:false}).then(function(r){return !!r;});\n  }\n  function chooseTarget(sugg,fm){\n    if(fsPick('showSaveFilePicker')){\n      var acc={},pr;acc[fm.mime]=['.'+fm.ext];\n      try{pr=window.showSaveFilePicker({suggestedName:sugg,types:[{description:fm.desc,accept:acc}]});}\n      catch(e){return askName(sugg,fm);}\n      return pr.then(function(h){return {handle:h};},function(e){if(e&&e.name==='AbortError')return null;return askName(sugg,fm);});\n    }\n    return askName(sugg,fm);\n  }\n  function rName(n,ext){\n    var m=n.replace(new RegExp('\\\\.'+ext+'$','i'),'');\n    if(\/L$\/i.test(m))m=m.replace(\/L$\/i,'R');else m+='-R';\n    return m+'.'+ext;\n  }\n  async function writeTarget(tg,blob){\n    if(tg.handle){var w=await tg.handle.createWritable();await w.write(blob);await w.close();return tg.handle.name||'fil';}\n    save(blob,tg.name);return tg.name;\n  }\n  \/* ---------- Batch: alle sektioner (mellem splits) som egne filer ---------- *\/\n  var CRC_T=null;\n  function crc32(u8){\n    if(!CRC_T){CRC_T=new Uint32Array(256);for(var n=0;n<256;n++){var c=n;for(var k=0;k<8;k++)c=(c&1)?(0xEDB88320^(c>>>1)):(c>>>1);CRC_T[n]=c>>>0;}}\n    var crc=0xFFFFFFFF;for(var i=0;i<u8.length;i++)crc=CRC_T[(crc^u8[i])&255]^(crc>>>8);return (crc^0xFFFFFFFF)>>>0;\n  }\n  async function makeZip(files){\n    var enc=new TextEncoder(),parts=[],cen=[],off=0,d=new Date();\n    var dt=((d.getHours()<<11)|(d.getMinutes()<<5)|(d.getSeconds()>>1))&0xFFFF,dd=(((d.getFullYear()-1980)<<9)|((d.getMonth()+1)<<5)|d.getDate())&0xFFFF;\n    for(var i=0;i<files.length;i++){\n      var nm=enc.encode(files[i].name),data=new Uint8Array(await files[i].blob.arrayBuffer()),crc=crc32(data);\n      var lh=new DataView(new ArrayBuffer(30));\n      lh.setUint32(0,0x04034b50,true);lh.setUint16(4,20,true);lh.setUint16(6,0x0800,true);lh.setUint16(8,0,true);lh.setUint16(10,dt,true);lh.setUint16(12,dd,true);\n      lh.setUint32(14,crc,true);lh.setUint32(18,data.length,true);lh.setUint32(22,data.length,true);lh.setUint16(26,nm.length,true);lh.setUint16(28,0,true);\n      parts.push(lh.buffer,nm,data);\n      var ch=new DataView(new ArrayBuffer(46));\n      ch.setUint32(0,0x02014b50,true);ch.setUint16(4,20,true);ch.setUint16(6,20,true);ch.setUint16(8,0x0800,true);ch.setUint16(10,0,true);ch.setUint16(12,dt,true);ch.setUint16(14,dd,true);\n      ch.setUint32(16,crc,true);ch.setUint32(20,data.length,true);ch.setUint32(24,data.length,true);ch.setUint16(28,nm.length,true);ch.setUint32(42,off,true);\n      cen.push(ch.buffer,nm);\n      off+=30+nm.length+data.length;\n    }\n    var cl=0;for(i=0;i<cen.length;i++)cl+=cen[i].byteLength;\n    var eo=new DataView(new ArrayBuffer(22));\n    eo.setUint32(0,0x06054b50,true);eo.setUint16(8,files.length,true);eo.setUint16(10,files.length,true);eo.setUint32(12,cl,true);eo.setUint32(16,off,true);\n    return new Blob(parts.concat(cen,[eo.buffer]),{type:'application\/zip'});\n  }\n  async function exportSections(dres,o){\n    var secs=sectionRanges();\n    if(secs.length<2)throw new Error('There are no sections to export. Add at least one split first.');\n    var stem=String(dres.name||o.base).replace(new RegExp('\\\\.'+o.fm.ext+'$','i'),'').replace(\/\\.zip$\/i,'');\n    var pad=Math.max(2,String(secs.length).length),files=[],k,dirH=null;\n    if(o.isMp3&&!lameReady()){await loadLame();}\n    if(fsPick('showDirectoryPicker')){\n      try{dirH=await window.showDirectoryPicker({mode:'readwrite'});}\n      catch(e){if(e&&e.name==='AbortError'){say('Export cancelled.');return;}dirH=null;}\n    }\n    var label=el.exp.textContent;\n    try{\n      for(k=0;k<secs.length;k++){\n        el.exp.textContent='EXPORTING '+(k+1)+' \/ '+secs.length+' \u2026';await tick();\n        expRange=secs[k];\n        var num=String(k+1);while(num.length<pad)num='0'+num;\n        var nm=stem+'-'+num;\n        if(!o.split){\n          var RA=await prepRender(o.mode==='mono'?(o.two?[0,1]:[0]):(o.two?[0,1]:[0,0]),o.mode==='mono',o.dst);\n          files.push({name:nm+'.'+o.fm.ext,blob:await o.enc(RA)});\n        }else{\n          files.push({name:nm+'-L.'+o.fm.ext,blob:await o.enc(await prepRender([0],false,o.dst))});\n          files.push({name:nm+'-R.'+o.fm.ext,blob:await o.enc(await prepRender([1],false,o.dst))});\n        }\n      }\n    }finally{el.exp.textContent=label;}\n    if(dirH){\n      for(k=0;k<files.length;k++){\n        var fh=await dirH.getFileHandle(files[k].name,{create:true}),w=await fh.createWritable();\n        await w.write(files[k].blob);await w.close();\n      }\n      say('Saved '+files.length+' files into the chosen folder.');\n    }else{\n      save(await makeZip(files),stem+'.zip');\n      say('Exported '+files.length+' files as '+stem+'.zip (saved to your downloads folder).');\n    }\n  }\n  async function exportAudio(){\n    if(!buf||busy)return;\n    busy=true;el.exp.disabled=true;\n    try{\n      var f=el.fmt.value,isMp3=f==='mp3',bits=+el.bits.value||16,mode=el.chm.value,two=chN>1,kb=+el.kbps.value||192;\n      if(mode==='split'&&!two)mode='mono';\n      var split=mode==='split',dst=+el.srt.value||sr;\n      if(isMp3&&[32000,44100,48000].indexOf(dst)<0)dst=48000;\n      var FMT={wav:{ext:'wav',mime:'audio\/wav',desc:'WAV audio'},aiff:{ext:'aiff',mime:'audio\/aiff',desc:'AIFF audio'},mp3:{ext:'mp3',mime:'audio\/mpeg',desc:'MP3 audio'},avi:{ext:'avi',mime:'video\/x-msvideo',desc:'AVI (audio only)'}};\n      var fm=FMT[f]||FMT.wav;\n      var meta=null;\n      var enc=async function(R){\n        if(f==='mp3')return await encMp3(await loadLame(),R,kb,meta);\n        if(f==='aiff')return await encAiff(R,bits,meta);\n        if(f==='avi')return await encAvi(R,bits,meta);\n        return await encWav(R,bits,meta);\n      };\n      var base=fileName+'-edit',canPick=fsPick('showSaveFilePicker'),tp;\n      var dres=await openDlg(canPick?{title:'Export audio',note:'',ok:'Save',showName:false,name:base,batchExt:'-01.'+fm.ext,extLabel:'.'+fm.ext,fm:fm,meta:true,range:true}:{title:'Export audio',note:'',ok:'Save',name:base,extLabel:split?('-L.'+fm.ext+' + -R.'+fm.ext):('.'+fm.ext),showName:true,batchExt:'-01.'+fm.ext,fm:fm,meta:true,range:true});\n      if(!dres){say('Export cancelled.');return;}\n      var rgSel=(dres.range==='s')?exportSelSamples():null;\n      if(dres.range==='s'&&!rgSel)throw new Error('There is no selection to export.');\n      expRange=rgSel||[0,buf.length];\n      meta=mtFor(f);\n      if(dres.range==='a'){await exportSections(dres,{fm:fm,enc:enc,mode:mode,two:two,split:split,dst:dst,isMp3:isMp3,base:base});return;}\n      if(canPick)tp=chooseTarget(split?base+'-L.'+fm.ext:base+'.'+fm.ext,fm);\n      else tp=Promise.resolve({name:dres.name});\n      if(isMp3&&!lameReady()){say('Fetching MP3 encoder \u2026');await loadLame();}\n      var tg=await tp;\n      if(!tg){say('Export cancelled.');return;}\n      if(!split){\n        var RA=await prepRender(mode==='mono'?(two?[0,1]:[0]):(two?[0,1]:[0,0]),mode==='mono',dst);\n        var nm=await writeTarget(tg,await enc(RA));\n        say(tg.handle?'Saved: '+nm:'Exported: '+nm+' (saved to your downloads folder)');\n        return;\n      }\n      if(!tg.handle){\n        var stem=tg.name.replace(new RegExp('\\\\.'+fm.ext+'$','i'),'').replace(\/-L$\/,'');\n        save(await enc(await prepRender([0],false,dst)),stem+'-L.'+fm.ext);\n        await new Promise(function(r){setTimeout(r,500);});\n        save(await enc(await prepRender([1],false,dst)),stem+'-R.'+fm.ext);\n        say('Exported: '+stem+'-L.'+fm.ext+' and '+stem+'-R.'+fm.ext+' (saved to your downloads folder)');\n        return;\n      }\n      var n1=await writeTarget(tg,await enc(await prepRender([0],false,dst)));\n      say('Left channel saved: '+n1);\n      var go=await askConfirm('Save right channel','','Save right channel');\n      if(!go){say('Only the left channel was saved: '+n1);return;}\n      var tg2=await chooseTarget(rName(n1,fm.ext),fm);\n      if(!tg2){say('Only the left channel was saved: '+n1);return;}\n      var n2=await writeTarget(tg2,await enc(await prepRender([1],false,dst)));\n      say('Saved: '+n1+' (L) and '+n2+' (R)');\n    }catch(e){say('Export failed: '+(e&&e.message?e.message:'unknown error'),true);}\n    finally{expRange=null;busy=false;el.exp.disabled=false;}\n  }\n  \/* ---------- Events ---------- *\/\n  \/* ---------- Tooltips: sl\u00e5s til med ?-knappen og vises, n\u00e5r musen hviler over en knap med data-tip ---------- *\/\n  var tipsOn=false,tipEl=null,tipTimer=0,tip=document.createElement('div');\n  tip.className='aew-tip';tip.setAttribute('role','tooltip');tip.hidden=true;root.appendChild(tip);\n  function tipHide(){\n    clearTimeout(tipTimer);tipTimer=0;tipEl=null;\n    tip.classList.remove('aew-show');tip.hidden=true;\n  }\n  function tipShow(t){\n    var txt=t.getAttribute('data-tip');\n    if(!txt||(!tipsOn&&t!==el.tipb))return;\n    var ttl=t.getAttribute('data-tip-title'),ar=document.createElement('i');\n    tip.textContent='';\n    if(ttl){var b=document.createElement('b');b.textContent=ttl;tip.appendChild(b);}\n    tip.appendChild(document.createTextNode(txt));tip.appendChild(ar);\n    tip.hidden=false;tip.classList.remove('aew-show','aew-below');\n    var rr=root.getBoundingClientRect(),tr=t.getBoundingClientRect(),w=tip.offsetWidth,hh=tip.offsetHeight;\n    var cx=tr.left+tr.width\/2-rr.left,x=clamp(cx-w\/2,8,Math.max(8,rr.width-w-8));\n    var above=(tr.top-rr.top-hh-12)>8,y=above?(tr.top-rr.top-hh-10):(tr.bottom-rr.top+10);\n    tip.style.left=x+'px';tip.style.top=y+'px';\n    ar.style.left=clamp(cx-x-5,10,Math.max(10,w-22))+'px';\n    tip.classList.toggle('aew-below',!above);\n    requestAnimationFrame(function(){if(tipEl===t)tip.classList.add('aew-show');});\n  }\n  var tipList=null,tipListT=0,tipRaf=0,tipX=0,tipY=0,tipBlocked=null;\n  function tipTargets(){var n=Date.now();if(!tipList||n-tipListT>1500){tipList=Array.prototype.slice.call(root.querySelectorAll('[data-tip]'));tipListT=n;}return tipList;}\n  function tipAt(x,y){\n    var a=tipTargets(),i,r;\n    for(i=0;i<a.length;i++){r=a[i].getBoundingClientRect();if(r.width>0&&r.height>0&&x>=r.left&&x<=r.right&&y>=r.top&&y<=r.bottom)return a[i];}\n    return null;\n  }\n  root.addEventListener('mousemove',function(e){\n    tipX=e.clientX;tipY=e.clientY;\n    if(tipRaf)return;\n    tipRaf=requestAnimationFrame(function(){\n      tipRaf=0;\n      var t=(root._ae&&root._ae.modal&&root._ae.modal())?null:tipAt(tipX,tipY);\n      if(t&&!tipsOn&&t!==el.tipb)t=null;\n      if(t!==tipBlocked)tipBlocked=null;\n      if(t===tipBlocked&&t)return;\n      if(t===tipEl)return;\n      tipHide();\n      if(t){tipEl=t;tipTimer=setTimeout(function(){if(tipEl===t)tipShow(t);},450);}\n    });\n  });\n  root.addEventListener('mouseleave',function(){tipHide();tipBlocked=null;});\n  root.addEventListener('pointerdown',function(e){tipBlocked=tipAt(e.clientX,e.clientY);if(tipEl||!tip.hidden)tipHide();},true);\n  document.addEventListener('keydown',function(){if(!tip.hidden)tipHide();},true);\n  window.addEventListener('scroll',function(){if(!tip.hidden)tipHide();},true);\n  el.tipb.addEventListener('click',function(e){\n    e.stopPropagation();\n    tipsOn=!tipsOn;el.tipb.setAttribute('aria-pressed',tipsOn?'true':'false');\n    el.tipb.setAttribute('aria-label',tipsOn?'Hide tooltips':'Show tooltips');\n    el.tipb.setAttribute('data-tip',tipsOn?'Tooltips on \\u2013 hover over a button to learn what it does':'Tooltips off \\u2013 turn on to see hints');\n    tipHide();\n  });\n  var demoBusy=false;\n  async function loadDemo(){\n    if(demoBusy)return;\n    demoBusy=true;el.demo.disabled=true;var lab=el.demo.textContent;el.demo.textContent='Loading \\u2026';\n    try{\n      var r=await fetch(DEMO_URL,{mode:'cors'});\n      if(!r.ok)throw new Error('the server answered '+r.status);\n      var b=await r.blob(),nm=decodeURIComponent((DEMO_URL.split('?')[0].split('\/').pop())||'demo.mp3');\n      await importFiles([new File([b],nm,{type:b.type&&\/^audio\\\/\/.test(b.type)?b.type:'audio\/mpeg'})]);\n    }catch(e){\n      say('Could not load the demo audio'+(e&&e.message&&!\/Failed to fetch|NetworkError|Load failed\/i.test(e.message)?': '+e.message:' (the file could not be reached, or the server does not allow it to be used here).'),true);\n    }finally{demoBusy=false;el.demo.disabled=false;el.demo.textContent=lab;}\n  }\n  el.demo.addEventListener('click',loadDemo);\n  el.file.addEventListener('change',function(){var fs=Array.prototype.slice.call(el.file.files||[]);if(fs.length)importSafe(fs);try{el.file.value='';}catch(_){}});\n  (function(){\n    if(!window.MutationObserver)return;\n    var mo=new MutationObserver(function(list){\n      list.forEach(function(m){\n        var t=m.target;\n        if(t&&t.classList&&t.classList.contains('aew-nmod')&&!t.hidden){\n          var bx=t.querySelector('.aew-nmbox');\n          if(bx&&bx.scrollIntoView)setTimeout(function(){try{bx.scrollIntoView({block:'center',behavior:'smooth'});}catch(_){}},30);\n        }\n      });\n    });\n    $$('.aew-nmod').forEach?$$('.aew-nmod').forEach(function(n){mo.observe(n,{attributes:true,attributeFilter:['hidden']});}):Array.prototype.forEach.call($$('.aew-nmod'),function(n){mo.observe(n,{attributes:true,attributeFilter:['hidden']});});\n  })();\n  el.imadd.addEventListener('click',function(){closeImp('add');});\n  el.imrep.addEventListener('click',function(){closeImp('replace');});\n  el.imcancel.addEventListener('click',function(){closeImp(null);});\n  document.addEventListener('keydown',function(e){if(!el.imm.hidden&&e.key==='Escape'){e.preventDefault();closeImp(null);}},true);\n  function hasFiles(e){var t=e.dataTransfer&&e.dataTransfer.types;return !!t&&Array.prototype.indexOf.call(t,'Files')>=0;}\n  ['dragenter','dragover'].forEach(function(t){root.addEventListener(t,function(e){if(!hasFiles(e))return;e.preventDefault();el.drop.classList.add('aew-over');});});\n  root.addEventListener('dragleave',function(e){if(e.target===el.drop||e.target===root)el.drop.classList.remove('aew-over');});\n  root.addEventListener('drop',function(e){\n    if(!hasFiles(e))return;\n    e.preventDefault();el.drop.classList.remove('aew-over');\n    var fs=Array.prototype.slice.call((e.dataTransfer&&e.dataTransfer.files)||[]);if(fs.length)importSafe(fs);\n  });\n  el.play.addEventListener('click',toggle);\n  el.home.addEventListener('click',toStart);\n  el.lps.addEventListener('click',function(){toLoopPoint(trimS);});\n  el.lpe.addEventListener('click',function(){toLoopPoint(trimE);});\n  el.reset.addEventListener('click',function(){if(!buf)return;edit(function(){trimS=0;trimE=dur;});selActive=false;onTrim(true);});\n  el.fs.addEventListener('change',function(){commitField('s');});\n  el.fe.addEventListener('change',function(){commitField('e');});\n  [el.fs,el.fe].forEach(function(i){i.addEventListener('keydown',function(e){if(e.key==='Enter'){e.preventDefault();i.blur();}});});\n  el.zin.addEventListener('click',function(){var p=getPos();zoomAt(1\/ZSTEP,(p>=view.s&&p<=view.s+view.sp)?p:view.s+view.sp\/2);});\n  el.zout.addEventListener('click',function(){zoomAt(ZSTEP,view.s+view.sp\/2);});\n  el.zfit.addEventListener('click',function(){setView(0,dur);});\n  el.zsel.addEventListener('click',function(){var q=selSec(),pad=(q[1]-q[0])*0.05+4\/sr;setView(q[0]-pad,q[1]-q[0]+2*pad);});\n  el.scroll.addEventListener('input',function(){setView(el.scroll.value\/1000*(dur-view.sp),view.sp);});\n  el.toolEnv.addEventListener('click',function(){setTool(tool==='env'?'sel':'env');});\n  el.envdel.addEventListener('click',delSel);\n  el.envclr.addEventListener('click',function(){if(!envCount())return;edit(function(){CH[0].env=[];CH[1].env=[];selPt=null;});envChanged();});\n  function flash(b){b.classList.add('aew-on');setTimeout(function(){b.classList.remove('aew-on');},220);}\n  el.rev.addEventListener('click',function(){flash(el.rev);doReverse();});\n  [$('.aew-zh'),$('.aew-zv')].forEach(function(c){\n    ['pointerdown','pointerup','dblclick'].forEach(function(t){c.addEventListener(t,function(e){e.stopPropagation();});});\n  });\n  el.rtn.addEventListener('click',function(){rtnMode=(rtnMode==='rtn')?'off':'rtn';rtnUI();});\n  el.lastb.addEventListener('click',function(){rtnMode=(rtnMode==='last')?'off':'last';rtnUI();});\n  el.link.addEventListener('click',function(){linkOn=!linkOn;if(linkOn)selR=null;layout();linkUI();});\n  el.gin.addEventListener('keydown',function(e){\n    e.stopPropagation();\n    if(e.key==='Enter'){\n      e.preventDefault();\n      var v=parseU(el.gin.value),ed=el.gin.getAttribute('data-e');\n      if(v!=null&&isFinite(v)&&selEdges())edit(function(){setEdge(ed,clamp(v,0,dur));});\n      if(linkOn&&selActive)onTrim(true);\n      closeGripInput();invalidate(true,true);\n      try{el.wave.focus({preventScroll:true});}catch(_){}\n    }else if(e.key==='Escape'){e.preventDefault();closeGripInput();try{el.wave.focus({preventScroll:true});}catch(_){}}\n  });\n  el.gin.addEventListener('pointerdown',function(e){e.stopPropagation();});\n  el.gin.addEventListener('dblclick',function(e){e.stopPropagation();});\n  el.gin.addEventListener('blur',closeGripInput);\n  Array.prototype.forEach.call($$('.aew-un'),function(b){b.addEventListener('click',function(){unit=b.getAttribute('data-u');unitUI();});});\n  \/* envelope-punkt: skriv tid og niveau pr\u00e6cist (Enter med et valgt punkt) *\/\n  function epClose(){el.ptp.hidden=true;try{el.wave.focus({preventScroll:true});}catch(_){}}\n  function epOpen(){\n    if(!selPt||tool!=='env'||!buf)return;\n    var z=zoneOf(selCh),x=X(selPt.t),y=dbToY(selPt.db,z),w=W();\n    el.ptt.value=fU(selPt.t);el.ptd.value=numTxt(selPt.db,2);\n    el.ptp.hidden=false;\n    var pw=el.ptp.offsetWidth||220;\n    el.ptp.style.left=clamp(x-pw\/2,4,w-pw-4)+'px';el.ptp.style.top=Math.max(RUL+6,y-64)+'px';\n    setTimeout(function(){try{el.ptd.focus();el.ptd.select();}catch(_){}},0);\n  }\n  function epCommit(){\n    var t=parseU(el.ptt.value),d=parseNum(el.ptd.value),p=selPt,c=selCh;\n    if(!p||t==null||!isFinite(t)||!isFinite(d)){epClose();say('Type numbers for time and level.',true);return;}\n    t=rs(clamp(t,0,dur));d=clamp(Math.round(d*100)\/100,DBMIN,DBMAX);\n    edit(function(){p.t=t;p.db=d;ED(c).env.sort(function(a,b){return a.t-b.t;});});\n    envChanged();epClose();\n  }\n  [el.ptt,el.ptd].forEach(function(i){\n    i.addEventListener('keydown',function(e){\n      e.stopPropagation();\n      if(e.key==='Enter'){e.preventDefault();epCommit();}\n      else if(e.key==='Escape'){e.preventDefault();epClose();}\n    });\n    i.addEventListener('focus',function(){try{i.select();}catch(_){}});\n    i.addEventListener('pointerdown',function(e){e.stopPropagation();});\n  });\n  el.ptp.addEventListener('pointerdown',function(e){e.stopPropagation();});\n  \/* mark\u00f8rens position: klik p\u00e5 linjen i infofeltet og skriv en pr\u00e6cis v\u00e6rdi *\/\n  el.mki.addEventListener('click',function(e){\n    if(!buf||!selMk||mkEditing||(e.target&&e.target.tagName==='INPUT'))return;\n    e.preventDefault();e.stopPropagation();\n    mkEditing=true;var m=selMk;\n    el.mki.textContent='Marker '+m.n+'  \\u00b7  ';\n    var inp=document.createElement('input');inp.type='text';inp.className='aew-ti aew-nin aew-mkin';inp.value=fU(m.t);inp.setAttribute('aria-label','Marker position. Type an exact value');inp.spellcheck=false;\n    el.mki.appendChild(inp);\n    function done(commit){\n      if(!mkEditing)return;mkEditing=false;\n      if(commit){var t=parseU(inp.value);if(t!=null&&isFinite(t)){t=rs(clamp(t,0,dur));edit(function(){m.t=t;});}}\n      mkInfoUI();mkUI();\n    }\n    inp.addEventListener('keydown',function(ev){ev.stopPropagation();if(ev.key==='Enter'){ev.preventDefault();done(true);}else if(ev.key==='Escape'){ev.preventDefault();done(false);}});\n    inp.addEventListener('blur',function(){done(false);});\n    inp.addEventListener('pointerdown',function(ev){ev.stopPropagation();});\n    inp.focus();inp.select();\n  });\n  el.undo.addEventListener('click',function(e){if(e.altKey||e.ctrlKey)redo();else undo();});\n  el.pi.addEventListener('click',function(){pmodeSet('insert');});\n  el.po.addEventListener('click',function(){pmodeSet('over');});\n  el.clipl.addEventListener('click',clipLocators);\n  el.tcut.addEventListener('click',function(){if(tool==='cut'&&!drag&&!playing)setTool('sel');else cutHere();});\n  el.tsel.addEventListener('click',function(){pickTool('sel');});\n  el.tmv.addEventListener('click',function(){pickTool('mv');});\n  el.tscr.addEventListener('click',function(){pickTool('scrub');});\n  Array.prototype.forEach.call($$('.aew-pmb'),function(b){b.addEventListener('click',function(){pmSet(b.getAttribute('data-m'));});});\n  el.xfms.addEventListener('change',xfCommit);\n  el.xfms.addEventListener('blur',xfCommit);\n  el.xfms.addEventListener('keydown',function(e){\n    if(e.key==='Enter'){e.preventDefault();xfCommit();el.xfms.blur();}\n    else if(e.key==='ArrowUp'||e.key==='ArrowDown'){e.preventDefault();xfCommit();xfMs=clamp(xfMs+(e.key==='ArrowUp'?1:-1)*(e.shiftKey?10:1),1,500);el.xfms.value=String(xfMs);}\n  });\n  Array.prototype.forEach.call($$('.aew-mkb'),function(b){\n    b.addEventListener('click',function(e){\n      var n=+b.getAttribute('data-n'),m=mkFind(n);\n      if(m&&e.altKey)mkDel(m);\n      else if(m)toLoopPoint(m.t);\n      else mkAssign(n);\n    });\n  });\n  el.mkp.addEventListener('click',mkPrev);\n  el.mkn.addEventListener('click',mkNext);\n  el.lrs.addEventListener('click',function(){\n    if(chN<2)return;\n    edit(function(){setSplitRaw(!splitCh);});\n    scheduleFx();invalidate(true,true);\n    if(playing)restart();\n  });\n  el.vzo.addEventListener('click',function(){zoomV(1\/ZSTEP);});\n  el.vzi.addEventListener('click',function(){zoomV(ZSTEP);});\n  el.vz1.addEventListener('click',function(){vz=1;invalidate(true,true);});\n  el.lcon.addEventListener('click',function(){lcPower(!lcOn);lcUI();});\n  el.lcm.addEventListener('click',lcOpen);\n  el.smb.addEventListener('click',monoOpen);\n  el.smcancel.addEventListener('click',function(){el.smm.hidden=true;});\n  el.smok.addEventListener('click',monoApply);\n  if(DONATE_URL){el.abdon.setAttribute('href',DONATE_URL);el.abdon.setAttribute('target','_blank');el.abdon.setAttribute('rel','noopener noreferrer');}\n  el.abb.addEventListener('click',function(){if(playing)pause();el.abm.hidden=false;setTimeout(function(){try{el.abok.focus();}catch(_){}},30);});\n  el.abok.addEventListener('click',function(){el.abm.hidden=true;});\n  el.abm.addEventListener('keydown',function(e){if(e.key==='Escape'){e.preventDefault();el.abm.hidden=true;}});\n  el.smm.addEventListener('keydown',function(e){if(e.key==='Escape'){e.preventDefault();el.smm.hidden=true;}});\n  Array.prototype.forEach.call($$('.aew-smk'),function(b){b.addEventListener('click',function(){smKeep=+b.getAttribute('data-k');monoKeepUI();});});\n  el.ttb.addEventListener('click',ttOpen);\n  el.ttc.addEventListener('click',ttClose);\n  el.ttok.addEventListener('click',ttApply);\n  el.ttpl.addEventListener('click',ttPlay);\n  el.ttm.addEventListener('keydown',function(e){if(e.key==='Escape'){e.preventDefault();ttClose();}});\n  Array.prototype.forEach.call($$('.aew-tty'),function(b){b.addEventListener('click',function(){ttSetType(b.getAttribute('data-t'));});});\n  el.ttfs.addEventListener('input',function(){\n    ttHz=Math.round(ttHzFromSlider(+el.ttfs.value)*10)\/10;\n    if(ttOsc&&ctx)ttOsc.frequency.setTargetAtTime(ttHz,ctx.currentTime,0.01);\n    ttUI(true);\n  });\n  function ttHzCommit(){\n    var v=String(el.tthz.value).trim().toLowerCase().replace(',','.'),m=1;\n    if(\/k$\/.test(v)){m=1000;v=v.slice(0,-1);}\n    var x=parseFloat(v)*m;\n    if(isFinite(x))ttHz=clamp(Math.round(x*10)\/10,20,ttHzMax());\n    if(ttOsc&&ctx)ttOsc.frequency.setTargetAtTime(ttHz,ctx.currentTime,0.01);\n    ttUI();\n  }\n  el.tthz.addEventListener('change',ttHzCommit);\n  function ttDurCommit(){\n    var x=parseT(el.ttd.value);\n    if(x!=null&&isFinite(x))ttDur=clamp(x,0.01,TT_MAXDUR);\n    ttUI();\n  }\n  el.ttd.addEventListener('change',ttDurCommit);\n  [el.tthz,el.ttd].forEach(function(i){i.addEventListener('keydown',function(e){if(e.key==='Enter'){e.preventDefault();i.blur();}});});\n  wireNum(el.ttlin,function(){\n    var v=parseNum(el.ttlin.value);\n    if(!isFinite(v)){ttUI();return;}\n    ttDb=clamp(Math.round(v*10)\/10,-60,0);\n    if(ttG&&ctx)ttG.gain.setTargetAtTime(ttLvl(),ctx.currentTime,0.01);\n    ttUI();\n  });\n  el.ttl.addEventListener('input',function(){\n    ttDb=+el.ttl.value;\n    if(ttG&&ctx)ttG.gain.setTargetAtTime(ttLvl(),ctx.currentTime,0.01);\n    ttUI(true);\n  });\n  el.lcc.addEventListener('click',lcClose);\n  el.lpl.addEventListener('click',lcPlay);\n  el.lcmod.addEventListener('keydown',function(e){if(e.key==='Escape'){e.preventDefault();lcClose();}});\n  el.lcs.addEventListener('input',function(){lcHz=20*Math.pow(25,(+el.lcs.value)\/1000);lcUI();lcFreq(lcHz);});\n  wireNum(el.lcin,function(){\n    var v=parseNum(el.lcin.value);\n    if(!isFinite(v)){lcUI();return;}\n    v=clamp(v,20,500);\n    el.lcs.value=String(Math.round(1000*Math.log(v\/20)\/Math.log(25)));\n    lcFreq(v);lcUI();\n  });\n  el.lcord.addEventListener('click',function(){lcOrder(LCORD[(LCORD.indexOf(lcOrd)+1)%LCORD.length]);lcUI();});\n  el.live.addEventListener('click',function(){envLive=!envLive;el.live.classList.toggle('aew-on',envLive);el.live.setAttribute('aria-pressed',envLive?'true':'false');invalidate(true,true);});\n  el.sil.addEventListener('click',function(){flash(el.sil);silenceSel();});\n  el.nrm.addEventListener('click',nmOpen);\n  el.rsb.addEventListener('click',rsOpen);\n  el.ptb.addEventListener('click',ptOpen);\n  el.rssel.addEventListener('change',rsRefresh);\n  el.rsbit.addEventListener('change',rsRefresh);\n  el.rsdi.addEventListener('click',function(){rsDither=!rsDither;rsRefresh();});\n  el.rspl.addEventListener('click',rsPlay);\n  el.rsc.addEventListener('click',rsClose);\n  el.rsok.addEventListener('click',rsApply);\n  el.rsm.addEventListener('keydown',function(e){if(e.key==='Escape'){e.preventDefault();rsClose();}});\n  el.ptc.addEventListener('click',ptClose);\n  el.ptok.addEventListener('click',ptApply);\n  el.ptm.addEventListener('keydown',function(e){if(e.key==='Escape'){e.preventDefault();ptClose();}});\n  el.pplay.addEventListener('click',pitchPlay);\n  el.ps.addEventListener('input',function(){pitchSemi=parseFloat(el.ps.value)||0;pitchUI();pitchLive();});\n  wireNum(el.pin,function(){\n    var v=parseNum(el.pin.value);\n    if(!isFinite(v)){pitchUI();return;}\n    v=clamp(v,-12,12);\n    if(Math.abs(v-Math.round(v))>1e-9&&!pitchFree){pitchFree=true;el.ps.step='0.01';}\n    v=pitchFree?Math.round(v*100)\/100:Math.round(v);\n    pitchSemi=v;el.ps.value=String(v);pitchUI();pitchLive();\n  });\n  el.ps.addEventListener('dblclick',function(){pitchSemi=0;el.ps.value='0';pitchUI();pitchLive();});\n  el.pfree.addEventListener('click',function(){\n    pitchFree=!pitchFree;\n    if(pitchFree)el.ps.step='0.01';\n    else{el.ps.step='1';pitchSemi=Math.round(pitchSemi);el.ps.value=String(pitchSemi);}\n    pitchUI();pitchLive();\n  });\n  function pitchModeSet(m){\n    if(pitchMode===m)return;\n    pitchMode=m;pitchUI();\n    if(playing&&playMode!=='norm'){var p=getPos();pause();pos=p;pitchPlay();}\n  }\n  el.pmv.addEventListener('click',function(){pitchModeSet('vari');});\n  el.pml.addEventListener('click',function(){pitchModeSet('lock');});\n  function nmCustomRead(){\n    var l=String(el.nlu.value).trim(),lv=l===''?null:parseNum(l),tv=parseNum(el.ntp.value);\n    NP[11].lufs=(lv==null||!isFinite(lv))?(l===''?null:NP[11].lufs):clamp(lv,-70,0);\n    if(isFinite(tv))NP[11].tp=clamp(tv,-30,0);\n    el.nlu.value=NP[11].lufs==null?'':numTxt(NP[11].lufs,1);el.ntp.value=numTxt(NP[11].tp,1);\n    nmUpd();\n  }\n  wireNum(el.nlu,nmCustomRead);wireNum(el.ntp,nmCustomRead);\n  el.nmsel.addEventListener('change',function(){el.nmcu.hidden=(+el.nmsel.value!==11);nmUpd();});\n  el.nmc.addEventListener('click',nmClose);\n  el.nmok.addEventListener('click',nmApply);\n  el.nm.addEventListener('keydown',function(e){if(e.key==='Escape'){e.preventDefault();nmClose();}});\n  el.inv.addEventListener('click',function(){flash(el.inv);invertSel();});\n  el.snap.addEventListener('click',function(){snapOn=!snapOn;el.snap.classList.toggle('aew-on',snapOn);el.snap.setAttribute('aria-pressed',snapOn?'true':'false');invalidate(false,true);});\n  el.ovl.addEventListener('click',resetMeter);\n  el.cpy.addEventListener('click',copySel);\n  el.cut.addEventListener('click',function(){removeSel(true);});\n  el.del.addEventListener('click',function(){removeSel(false);});\n  el.pst.addEventListener('click',pasteClip);\n  el.all.addEventListener('click',selectAll);\n  el.crop.addEventListener('click',cropSel);\n  el.loop.addEventListener('click',function(){loopOn=!loopOn;el.loop.classList.toggle('aew-on',loopOn);el.loop.setAttribute('aria-pressed',loopOn?'true':'false');root.classList.toggle('aew-looping',loopOn);invalidate(false,true);if(playing)restart();});\n  el.fol.addEventListener('click',function(){followOn=!followOn;el.fol.classList.toggle('aew-on',followOn);el.fol.setAttribute('aria-pressed',followOn?'true':'false');if(followOn)frameOnce();});\n  el.mcv.addEventListener('pointermove',function(e){mHover=e.clientX-el.mcv.getBoundingClientRect().left;drawMeter();});\n  el.mcv.addEventListener('pointerleave',function(){mHover=-1;drawMeter();});\n  el.fmt.addEventListener('change',function(){sync();if(el.fmt.value==='mp3')loadLame().catch(function(){});});\n  el.exp.addEventListener('click',exportAudio);\n  el.dlgOk.addEventListener('click',function(){closeDlg(el.dlgNf.hidden?{ok:true,range:expSel}:{name:cleanName(el.dlgName.value,dlgFm?dlgFm.ext:'wav'),range:expSel});});\n  el.rgw.addEventListener('click',function(){expSel='w';rgUI();});\n  el.rga.addEventListener('click',function(){if(sectionRanges().length<2)return;expSel='a';rgUI();});\n  el.rgs.addEventListener('click',function(){if(!exportSelSamples())return;expSel='s';rgUI();});\n  el.dlgCancel.addEventListener('click',function(){closeDlg(null);});\n  el.dmbtn.addEventListener('click',mtOpen);\n  el.mtok.addEventListener('click',function(){mtClose(true);});\n  el.mtcancel.addEventListener('click',function(){mtClose(false);});\n  el.mtclear.addEventListener('click',function(){\n    Array.prototype.forEach.call($$('.aew-mti'),function(i){i.value='';});\n    if(META.coverUrl){try{URL.revokeObjectURL(META.coverUrl);}catch(_){}}\n    META.cover=null;META.coverUrl='';mtCoverUI();\n  });\n  el.mtpick.addEventListener('click',function(){el.mtfile.click();});\n  el.mtrm.addEventListener('click',function(){if(META.coverUrl){try{URL.revokeObjectURL(META.coverUrl);}catch(_){}}META.cover=null;META.coverUrl='';mtCoverUI();});\n  el.mtfile.addEventListener('change',function(){\n    var f=el.mtfile.files&&el.mtfile.files[0];try{el.mtfile.value='';}catch(_){}\n    if(!f)return;\n    el.mtcn.textContent='Converting \u2026';\n    mtCover(f).then(function(){mtCoverUI();el.mtcn.textContent='Cover set: '+Math.round(META.cover.length\/1024)+' KB JPG.';},function(e){el.mtcn.textContent=(e&&e.message)||'Could not use that image.';});\n  });\n  el.mtm.addEventListener('keydown',function(e){\n    if(e.key==='Escape'){e.preventDefault();e.stopPropagation();mtClose(false);}\n    else if(e.key==='Enter'&&e.target&&e.target.tagName==='INPUT'&&e.target.type==='text'){e.preventDefault();mtClose(true);}\n  });\n  el.fmt.addEventListener('change',dmSum);\n  el.dlgName.addEventListener('keydown',function(e){\n    if(e.key==='Enter'){e.preventDefault();el.dlgOk.click();}\n    else if(e.key==='Escape'){e.preventDefault();closeDlg(null);}\n  });\n  if(window.ResizeObserver){var ro=new ResizeObserver(function(){invalidate(true,true);drawMeter();});ro.observe(el.wave);ro.observe(el.mwrap);}\n  else window.addEventListener('resize',function(){invalidate(true,true);drawMeter();});\n  root._ae={srcOk:function(){return !!buf&&srcTotal()===buf.length;},srcLabel:function(a,b){return srcLabel(a,b);},srcRuns:function(){return srcRuns.map(function(r){return [r.n,srcNames[r.id]||null];});},impNames:function(){return impNames.slice();},sections:function(){return sectionRanges();},ctDel:function(){return ctDel;},hitCut:function(x,y){return hitCutHandle(x,y);},expSel:function(){return exportSelSamples();},touchDbg:function(){return {td:touchDown,tp:tapPend};},tipsOn:function(){return tipsOn;},demoUrl:function(){return DEMO_URL;},lcHz:function(){return lcHz;},ttDbv:function(){return ttDb;},np:function(){return NP[11];},setPitch:function(v){el.pin.value=String(v);el.pin.dispatchEvent(new Event('change'));},epOpen:function(){epOpen();},selPt:function(){return selPt;},meta:function(){return META;},setMeta:function(o){for(var k in o)META[k]=o[k];},mtFor:function(f){return mtFor(f);},nLoop:function(){return nLoop;},playing:function(){return playing;},setView:function(s,sp){setView(s,sp);},unit:function(){return unit;},view:function(){return {s:view.s,sp:view.sp};},sr:function(){return sr;},snapT:function(t){return snapT(t);},snapOn:function(){return snapOn;},pos:function(){return getPos();},chN:function(){return chN;},edges:function(){return selEdges();},grips:function(){var s=selEdges();if(!s||tool!=='sel')return null;var gy=gripY();return {a:{x:X(s.a),y:gy},b:{x:X(s.b),y:gy},act:gripAct};},ginVisible:function(){return !el.gin.hidden;},midPos:function(i){var z=zones()[0],m=segMid(0,i,z);return {x:m.x,y:m.y};},shBar:function(){return shBar;},envPts:function(){return ED(0).env.map(function(p){return {t:p.t,db:p.db,k:p.k,sc:p.sc,n:p.n};});},envShape:function(){if(tool!=='env'||!selSeg)return false;applyShape(3);return true;},link:function(){return linkOn;},selR:function(){return selR;},marks:function(){return {hl:hl,hlx:hlx};},crop:cropSel,adopt:adopt,redo:redo,redoMod:function(v){v=!!v;if(redoMode!==v){redoMode=v;histUI();}},redoCount:function(){return redoStack.length;},peak:function(){if(!anL)return 0;var b=bufs[0],m=0,i,x;anL.getFloatTimeDomainData(b);for(i=0;i<b.length;i++){x=b[i]<0?-b[i]:b[i];if(x>m)m=x;}return m;},demux:function(f){var e=((\/\\.([^.]+)$\/.exec(f.name)||[])[1]||'').toLowerCase();return (e==='avi'?demuxAvi(f):demuxMp4(f)).then(function(r){return {codec:r.codec,sr:r.sr,ch:r.ch,aot:r.aot,skip:r.skip,limit:r.limit,bytes:Array.from(new Uint8Array(r.bytes))};});},decodeMedia:function(f){return decodeMedia(f).then(function(b){var o=[];for(var c=0;c<b.numberOfChannels;c++)o.push(Array.from(b.getChannelData(c)));return {sr:b.sampleRate,ch:b.numberOfChannels,len:b.length,data:o};});},vz:function(){return vz;},view:function(){return {s:view.s,sp:view.sp};},hl:function(){return hl;},pasteMode:function(){return pasteMode;},cuts:function(){return cuts;},tool:function(){return tool;},toolCut:function(){cutHere();},toolSel:function(){if(tool!=='env')setTool('sel');},toolMv:function(){pickTool('mv');},toolScrub:function(){pickTool('scrub');},rtnMode:function(){return rtnMode;},guide:function(){return sgDrag;},segSel:function(){return segSel;},esc:function(){if(!el.gin.hidden){closeGripInput();return;}if(gripAct){gripAct=null;invalidate(false,true);return;}if(selSeg){selSeg=null;invalidate(false,true);return;}if(!linkOn&&selR){selR=null;layout();invalidate(true,true);return;}if(segSel){segSel=null;invalidate(true,true);}else if(tool==='cut'||tool==='mv'||tool==='scrub')setTool('sel');},pcm:function(c){return buf.getChannelData(c);},clip:function(){return CLIP;},pmode:function(){return pmode;},xfms:function(){return xfMs;},mark:function(){markHere();},prevMk:function(){mkPrev();},nextMk:function(){mkNext();},markers:function(){return markers;},seek:function(t){seekTo(t);},env:function(){return CH[0].env;},ch:function(){return CH;},split:function(){return splitCh;},alt:function(v){if(altPrev!==v){altPrev=v;invalidate(false,true);}},snapPts:function(){return snapPts;},clearHL:function(){if(hl){hl=null;invalidate(true,false);}},ready:function(){return !!buf;},toggle:toggle,undo:undo,copy:copySel,cut:function(){removeSel(true);},paste:pasteClip,all:selectAll,modal:function(){return !el.dlg.hidden||!el.nm.hidden||!el.rsm.hidden||!el.ptm.hidden||!el.lcmod.hidden||!el.ttm.hidden||!el.smm.hidden||!el.abm.hidden||!el.mtm.hidden||!el.imm.hidden;}};\n  sync();setStats();fadeUI();envUI();helpTxt();histUI();clipUI();pitchUI();lcUI();splitUI();mkUI();drawMeter();updRead();\n  root.classList.add('aew-ready');\n  var nj=$('.aew-nojs');if(nj){nj.hidden=true;nj.setAttribute('aria-hidden','true');}\n}\nfunction fail(root,e){\n  var s=root.querySelector('.aew-derr');\n  if(s){s.textContent='Startup error: '+(e&&e.message?e.message:e);s.hidden=false;}\n  showFatal('Startup error: '+(e&&e.message?e.message:e)+(e&&e.stack?'\\n'+String(e.stack).split('\\n').slice(0,3).join('\\n'):''));\n  if(window.console&&console.error)console.error(e);\n}\nfunction boot(){bindKeys();var n=document.querySelectorAll('.audio-editor-widget');for(var i=0;i<n.length;i++){try{init(n[i]);}catch(e){fail(n[i],e);}}\n  \/* ligger widgetten i en iframe, fort\u00e6ller den sidens h\u00f8jde til for\u00e6ldresiden (valgfrit) *\/\n  try{\n    if(window.parent&&window.parent!==window&&window.ResizeObserver){\n      var sendH=function(){try{window.parent.postMessage({wavesoniqHeight:Math.ceil(Math.max(document.documentElement.scrollHeight,document.body?document.body.scrollHeight:0))},'*');}catch(_){}};\n      new ResizeObserver(sendH).observe(document.documentElement);sendH();\n    }\n  }catch(_){}\n}\nif(document.readyState==='loading')document.addEventListener('DOMContentLoaded',boot);else boot();\n})();\n<\/script>\n<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>wydgy Wavesoniq has not started yet. If this message stays visible on a WordPress page, a cache or optimization plugin (or the page builder) is delaying or blocking the widget&#8217;s script. Exclude the script from minify \/ defer \/ delay, or embed the widget in an iframe. Drop an audio or video file here Use&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"inline_featured_image":false,"_kad_post_transparent":"","_kad_post_title":"hide","_kad_post_layout":"fullwidth","_kad_post_sidebar_id":"","_kad_post_content_style":"unboxed","_kad_post_vertical_padding":"hide","_kad_post_feature":"hide","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"footnotes":""},"class_list":["post-1863","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages\/1863","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/comments?post=1863"}],"version-history":[{"count":16,"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages\/1863\/revisions"}],"predecessor-version":[{"id":6412,"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/pages\/1863\/revisions\/6412"}],"wp:attachment":[{"href":"https:\/\/landing.anderskisling.dk\/index.php\/wp-json\/wp\/v2\/media?parent=1863"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}