<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="description" content="简洁而强大的ChatGPT应用">
    <meta name="theme-color" content="#edeff2">
    <meta name="apple-mobile-web-app-status-bar-style" content="#edeff2">
    <meta name="msapplication-TileColor" content="#edeff2">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="msapplication-TileImage" content="icon.png">
    <link rel="manifest" crossorigin="use-credentials" href="manifest.json">
    <link rel="icon" type="image/png" href="icon.png">
    <link rel="apple-touch-icon" href="icon.png" sizes="512x512">
    <title>RadeMark</title>
    <style>
        .requestBody,
        .response .markdown-body {
            max-width: calc(100% - 84px);
        }

        .bottom_wrapper {
            max-width: 100%;
        }

        * {
            box-sizing: border-box;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
        }

        html {
            width: 100%;
            height: 100%;
        }

        :root {
            /* Modern ve ferah beyaz tema */
            --background: #f8fafc;
            /* Çok hafif gri-mavi tonu */
            --chat-back: #ffffff;
            /* Saf beyaz */
            --main-back: #ffffff;
            /* Saf beyaz */
            --active-btn: #f1f5f9;
            /* Hafif gri */
            --lighter-active: #e2e8f0;
            --sel-btn: #e2e8f0;
            --btn-color: #334155;
            /* Koyu slate */
            --text-color: #64748b;
            /* Orta slate */
            --chat-text-color: #1e293b;
            /* Çok koyu slate */
            --response-color: #f8fafc;
            /* Çok hafif gri-mavi */
            --lighter-active-color: #f1f5f9;
            --lighter-text-color: #475569;
            --svg-color: #64748b;
            --lighter-svg-color: #94a3b8;
            --code-color: #f1f5f9;
            --black-color: #0f172a;
            --gpt-icon-color: #10b981;
            /* Modern yeşil */
            --border-color: #e2e8f0;
        }

        [data-theme="dark"] {
            /* Zifiri karanlık tema */
            --background: #000000;
            /* Saf siyah */
            --chat-back: #0a0a0a;
            /* Çok koyu siyah */
            --main-back: #000000;
            /* Saf siyah */
            --active-btn: #171717;
            /* Biraz daha açık siyah */
            --lighter-active: #1a1a1a;
            --sel-btn: #1a1a1a;
            --btn-color: #fafafa;
            /* Çok açık gri */
            --text-color: #a3a3a3;
            /* Orta gri */
            --chat-text-color: #fafafa;
            /* Çok açık gri */
            --response-color: #0a0a0a;
            /* Çok koyu siyah */
            --lighter-active-color: #171717;
            --lighter-text-color: #d4d4d4;
            --svg-color: #a3a3a3;
            --lighter-svg-color: #525252;
            --code-color: #171717;
            --black-color: #ffffff;
            --gpt-icon-color: #10b981;
            /* Aynı modern yeşil */
            --border-color: #262626;
        }

        body {
            background-color: var(--background);
            width: 100%;
            height: 100%;
            margin: 0;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .chat_window {
            position: absolute;
            width: 100%;
            max-width: 1188px;
            height: 100%;
            max-height: 888px;
            border-radius: 8px;
            background-color: var(--chat-back);
            overflow: hidden;
            box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15);
        }

        .chat_window>.overlay {
            width: 100%;
            height: 100%;
            position: absolute;
            left: 0;
            top: 0;
            background-color: rgba(0, 0, 0, .3);
            z-index: 90;
            cursor: pointer;
            visibility: hidden;
            opacity: 0;
            -webkit-tap-highlight-color: transparent;
            transition: all 250ms;
            transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
        }

        @media screen and (max-width: 1188px) and (max-height: 888px) {
            #toggleFull {
                display: none;
            }
        }

        @media screen and (min-width: 800px) {
            .chat_window {
                display: flex;
            }

            .mainContent {
                width: calc(100% - 250px);
            }

            .chat_window>.nav {
                position: relative;
                margin-left: -250px;
                transition: margin-left 250ms;
                transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
            }

            .show-nav .nav {
                margin-left: 0;
            }

            #sysDialog {
                max-width: 600px;
            }

            .sysContent {
                display: flex;
            }

            .sysSwitch {
                flex-shrink: 0;
                width: 160px;
            }

            .sysSwitch>div {
                padding-left: 6px;
            }

            .sysDetail {
                margin-left: 12px;
                margin-top: 5px;
            }
        }

        @media screen and (max-width: 800px) {
            .chat_window {
                display: block;
            }

            .mainContent {
                width: 100%;
            }

            .chat_window>.nav {
                position: absolute !important;
                left: -250px;
                transition: left 250ms;
                transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
            }

            .show-nav .nav {
                left: 0;
                box-shadow: rgba(0, 0, 0, 0.2) 0px 8px 10px -5px, rgba(0, 0, 0, 0.14) 0px 16px 24px 2px, rgba(0, 0, 0, 0.12) 0px 6px 30px 5px;
            }

            .show-nav .overlay {
                visibility: visible;
                opacity: 1;
            }


            #sysDialog {
                max-width: 400px;
            }

            .sysSwitch {
                display: flex;
            }

            .sysSwitch>div {
                width: 50%;
                justify-content: center;
            }

            .sysDetail {
                margin-top: 8px;
            }
        }

        .full_window {
            max-width: none;
            max-height: none;
        }

        .chat_window>.nav {
            width: 250px;
            height: 100%;
            border-right: 1px solid var(--active-btn);
            background-color: var(--main-back);
            top: 0;
            z-index: 99;
            flex-shrink: 0;
            display: flex;
            flex-direction: column;
        }

        .mainContent {
            height: 100%;
            position: relative;
            display: flex;
            flex-direction: column;
            flex: 1;
        }

        .top_menu {
            background-color: var(--main-back);
            width: 100%;
            height: 46px;
            padding: 3px 0;
        }

        .top_menu .toggler {
            margin-left: 8px;
            width: 40px;
            height: 40px;
            float: left;
            padding: 5px 7px;
            border-radius: 4px;
            cursor: pointer;
            -webkit-tap-highlight-color: transparent;
        }

        .top_menu .toggler:hover {
            background: var(--active-btn);
        }

        .top_menu .toggler .button {
            width: 26px;
            height: 4px;
            border-radius: 4px;
            position: absolute;
            pointer-events: none;
        }

        .top_menu .toggler .button.close {
            margin-top: 3px;
            background-color: var(--btn-color);
            /* Tema rengini kullan */
        }

        .top_menu .toggler .button.minimize {
            margin-top: 13px;
            background-color: var(--btn-color);
            /* Tema rengini kullan */
        }

        .top_menu .toggler .button.maximize {
            margin-top: 23px;
            background-color: var(--btn-color);
            /* Tema rengini kullan */
        }

        .top_menu .title {
            color: var(--text-color);
            height: 40px;
            position: relative;
            pointer-events: none;
        }

        #selector {
            position: absolute;
            top: 50%;
            left: 50%;
            padding: 0 4px 0 10px;
            cursor: pointer;
            font-size: 20px;
            line-height: 40px;
            transform: translate(-50%, -50%);
            pointer-events: auto;
            border-radius: 4px;
            -webkit-user-select: none;
            user-select: none;
            display: flex;
            align-items: center;
        }

        #selector:hover {
            background-color: var(--active-btn);
        }

        #modelVer {
            margin-left: 4px;
            margin-right: 2px;
        }

        .messages {
            position: relative;
            flex: 1;
            overflow-x: hidden;
            overflow-y: auto;
            font-size: 16px;
            color: var(--chat-text-color);
            text-align: center;
        }

        .messages::-webkit-scrollbar,
        #chatlog .markdown-body pre>code::-webkit-scrollbar,
        #setDialog::-webkit-scrollbar,
        .allList::-webkit-scrollbar,
        .sysDetail::-webkit-scrollbar,
        #apiSelect::-webkit-scrollbar {
            width: 10px;
            height: 10px;
        }

        .messages::-webkit-scrollbar-track,
        #chatlog .markdown-body pre>code::-webkit-scrollbar-track,
        #setDialog::-webkit-scrollbar-track,
        .allList::-webkit-scrollbar-track,
        .sysDetail::-webkit-scrollbar-track,
        #apiSelect::-webkit-scrollbar-track {
            background-clip: padding-box;
            background: transparent;
            border: none;
        }

        .messages::-webkit-scrollbar-corner,
        #chatlog .markdown-body pre>code::-webkit-scrollbar-corner,
        #setDialog::-webkit-scrollbar-corner,
        .allList::-webkit-scrollbar-corner,
        .sysDetail::-webkit-scrollbar-corner,
        #apiSelect::-webkit-scrollbar-corner {
            background-color: transparent;
        }

        .messages::-webkit-scrollbar-thumb,
        #chatlog .markdown-body pre>code::-webkit-scrollbar-thumb,
        #setDialog::-webkit-scrollbar-thumb,
        .allList::-webkit-scrollbar-thumb,
        .sysDetail::-webkit-scrollbar-thumb,
        #apiSelect::-webkit-scrollbar-thumb {
            background-color: rgba(0, 0, 0, 0.1);
            background-clip: padding-box;
            border: solid transparent;
            border-radius: 10px;
        }

        .messages::-webkit-scrollbar-thumb:hover,
        #chatlog .markdown-body pre>code::-webkit-scrollbar-thumb:hover,
        #setDialog::-webkit-scrollbar-thumb:hover,
        .allList::-webkit-scrollbar-thumb:hover,
        .sysDetail::-webkit-scrollbar-thumb:hover,
        #apiSelect::-webkit-scrollbar-thumb:hover {
            background-color: rgba(0, 0, 0, 0.4);
        }

        #chatlog {
            word-wrap: break-word;
            text-align: start;
        }

        .chatAvatar {
            margin: 14px 12px 13px 12px;
            width: 30px;
            height: 30px;
            flex-shrink: 0;
            border-radius: 2px;
        }

        .response>.chatAvatar {
            margin-top: 15px;
            margin-bottom: 15px;
        }

        .gptAvatar>svg {
            margin-top: 3px;
            margin-left: 3px;
            fill: var(--gpt-icon-color);
        }

        .chatAvatar>img {
            display: block;
            width: 100%;
            height: 100%;
            border-radius: 2px;
        }

        .modelAvatar>svg,
        .chatAvatar>svg {
            display: block;
        }

        #chatlog .request {
            position: relative;
            display: flex;
            justify-content: center;
        }

        .requestBody {
            white-space: pre-wrap;
            margin: 18px 0;
            flex: 1;
        }

        #chatlog .response {
            background: var(--response-color);
            position: relative;
            display: flex;
            justify-content: center;
        }

        .response .markdown-body {
            margin: 18px 0;
            flex: 1;
            background: var(--response-color) !important;
        }

        #chatlog .markdown-body a {
            padding: 0 1px 0 2px;
        }

        #chatlog .markdown-body pre {
            padding: 10px 10px 5px 10px;
            position: relative;
            background: var(--code-color);
        }

        #chatlog .markdown-body .mermaid {
            margin-bottom: 8px;
            padding: 0 10px 0 10px;
            position: relative;
            background: var(--code-color);
            border-radius: 6px;
        }

        .mermaid>svg {
            cursor: pointer;
            max-height: 600px;
            display: block;
        }

        #chatlog .markdown-body pre>code {
            overflow-x: auto;
            display: block;
        }

        #chatlog .markdown-body ul {
            list-style-type: disc;
        }

        .m-mdic-copy-wrapper {
            position: absolute;
            top: 5px;
            right: 16px;
            z-index: 1;
            -webkit-user-select: none;
            user-select: none;
        }

        .m-mdic-copy-wrapper span.u-mdic-copy-code_lang {
            position: absolute;
            top: 3px;
            right: calc(100% + 4px);
            font-family: system-ui;
            font-size: 12px;
            line-height: 18px;
            color: #bbb;
        }

        .m-mdic-copy-wrapper div.u-mdic-copy-notify {
            position: absolute;
            top: 0;
            right: 0;
            padding: 3px 6px;
            border: 0;
            border-radius: 3px;
            background: none;
            font-family: system-ui;
            font-size: 12px;
            line-height: 18px;
            color: var(--lighter-text-color);
            outline: none;
            right: 100%;
            padding-right: 4px;
        }

        .m-mdic-copy-wrapper button.u-mdic-copy-btn {
            position: relative;
            top: 0;
            right: 0;
            padding: 3px 6px;
            border: 0;
            border-radius: 3px;
            background: none;
            font-family: system-ui;
            font-size: 12px;
            line-height: 18px;
            color: #bbb;
            outline: none;
            cursor: pointer;
            transition: color 250ms;
        }

        .m-mdic-copy-wrapper span.u-mdic-copy-code_lang::before,
        .m-mdic-copy-wrapper div.u-mdic-copy-notify::before,
        .m-mdic-copy-wrapper button.u-mdic-copy-btn::before {
            content: attr(text);
        }

        .m-mdic-copy-wrapper button.u-mdic-copy-btn:hover {
            color: var(--lighter-text-color);
        }

        #stopChat {
            display: none;
            margin: 0 auto;
            margin-top: 3px;
            width: 80px;
            height: 32px;
            text-align: center;
            line-height: 32px;
            color: white;
            background: #f8b26a;
            cursor: pointer;
            border-radius: 3px;
            position: sticky;
            bottom: 2px;
            justify-content: center;
            align-items: center;
        }

        #stopChat>svg {
            margin-right: 8px;
        }

        #stopChat:hover {
            background: #f0aa60;
        }

        .bottom_wrapper {
            position: relative;
            width: 100%;
            padding: 10px 10px;
            margin: 0 auto;
        }

        .bottom_wrapper .message_input_wrapper {
            border: none;
            width: calc(100% - 139px);
            position: relative;
            text-align: left;
        }

        .bottom_wrapper .message_input_wrapper .message_input_text {
            border-radius: 4px;
            border: none;
            outline: none;
            resize: none;
            background-color: var(--main-back);
            color: var(--chat-text-color);
            height: 47px;
            font-size: 16px;
            max-height: 200px;
            padding: 13px 0 13px 13px;
            width: 100%;
            display: block;
            transition: background-color 250ms;
        }

        .bottom_wrapper .message_input_wrapper .message_input_text:focus {
            background-color: var(--code-color);
        }

        .bottom_wrapper .message_input_wrapper .message_input_text::-webkit-scrollbar {
            display: none;
            width: 0;
            height: 0;
        }

        #sendbutton {
            width: 80px;
            height: 47px;
            font-size: 18px;
            font-weight: bold;
            border-radius: 3px;
            background-color: #b8da8b;
            border: none;
            padding: 0;
            color: #fff;
            cursor: pointer;
            transition: all 250ms;
            text-align: center;
            float: right;
            position: absolute;
            right: 63px;
            bottom: 10px;
            cursor: not-allowed;
        }

        .activeSendBtn {
            background-color: #99c959 !important;
            cursor: pointer !important;
        }

        .activeSendBtn:hover {
            background-color: #90c050 !important;
        }

        .clearConv {
            position: absolute;
            right: 10px;
            bottom: 10px;
            width: 47px;
            height: 47px;
            border-radius: 3px;
            background: var(--text-color);
            border: none;
            color: #fff;
            cursor: pointer;
        }

        .clearConv>svg {
            margin: 0 auto;
        }

        .clearConv:hover {
            background: var(--svg-color);
        }

        .clearConv svg:first-child {
            display: none;
        }

        .clearConv svg:nth-child(2) {
            display: block;
        }

        .closeConv {
            background: var(--active-btn);
        }

        .closeConv:hover {
            background: var(--lighter-active-color);
        }

        .closeConv svg:first-child {
            display: block;
        }

        .closeConv svg:nth-child(2) {
            display: none;
        }

        .loaded>span {
            display: inline-block;
        }

        .loaded>svg {
            display: none;
        }

        .loading {
            background: var(--active-btn) !important;
        }

        .loading>span {
            display: none;
        }

        .loading>svg {
            display: block;
        }

        .switch-slide {
            display: inline-block;
            vertical-align: middle;
        }

        .switch-slide-label {
            display: block;
            width: 38px;
            height: 18px;
            background: var(--text-color);
            border-radius: 30px;
            cursor: pointer;
            position: relative;
            -webkit-transition: all 250ms;
            transition: all 250ms;
        }

        .switch-slide-label:after {
            content: "";
            display: block;
            width: 16px;
            height: 16px;
            border-radius: 100%;
            background: #fff;
            box-shadow: 0 1px 1px rgba(0, 0, 0, .1);
            position: absolute;
            left: 1px;
            top: 1px;
            -webkit-transform: translateZ(0);
            transform: translateZ(0);
            -webkit-transition: all 250ms;
            transition: all 250ms;
        }

        .switch-slide input:checked+label {
            background: #99c959;
            -webkit-transition: all 250ms;
            transition: all 250ms;
        }

        .switch-slide input:checked+label:after {
            left: 21px;
        }

        .settings {
            margin-right: 10px;
            display: flex;
            position: absolute;
            right: 0;
            top: 3px;
        }

        .setBtn {
            margin-left: 2px;
            cursor: pointer;
            padding: 5px;
            border: none;
            background-color: transparent;
            border-radius: 4px;
        }

        .setBtn>svg {
            display: block;
            color: var(--text-color);
        }

        .setBtn svg circle {
            fill: var(--btn-color);
            /* Tema rengini kullan */
        }

        .setBtn:hover {
            background: var(--active-btn);
        }

        #setting {
            right: 15px;
        }

        #toggleFull {
            right: 56px;
        }

        #toggleLight *,
        #toggleFull * {
            pointer-events: none;
        }

        .showSetting {
            background: var(--lighter-svg-color) !important;
        }

        .showModels {
            background: var(--active-btn) !important;
        }

        #modelDialog {
            color: var(--btn-color);
            position: absolute;
            z-index: 2;
            background: var(--main-back);
            width: 240px;
            left: 50%;
            transform: translateX(-50%);
            top: 46px;
            overflow-y: auto;
            max-height: calc(100% - 55px);
            -webkit-user-select: none;
            user-select: none;
            border-radius: 4px;
            padding: 8px 5px 8px 5px;
            box-shadow: 0 0 6px rgba(0, 0, 0, 0.15);
        }

        .modelSingle {
            height: 40px;
            border-radius: 3px;
            cursor: pointer;
            line-height: 40px;
            display: flex;
            align-items: center;
            position: relative;
        }

        .modelSingle * {
            pointer-events: none;
        }

        .modelSingle:hover {
            background-color: var(--active-btn);
        }

        .activeModel::before {
            content: "";
            position: absolute;
            right: 15px;
            top: 7px;
            width: 8px;
            height: 16px;
            border-color: #99c959;
            border-style: solid;
            border-width: 0 4px 4px 0;
            transform: rotate(45deg);
        }

        .modelAvatar {
            margin-left: 6px;
            margin-right: 10px;
            width: 30px;
            flex-shrink: 0;
            border-radius: 2px;
            height: 30px;
        }

        #setDialog {
            color: var(--btn-color);
            position: absolute;
            z-index: 2;
            background: var(--main-back);
            width: 320px;
            right: 6px;
            top: 46px;
            overflow-y: auto;
            max-height: calc(100% - 55px);
            -webkit-user-select: none;
            user-select: none;
            border-radius: 5px;
            padding: 8px 12px 8px 12px;
            box-shadow: 0 0 6px rgba(0, 0, 0, 0.15);
        }

        #setDialog input {
            width: 100%;
        }

        #setDialog .inlineTitle {
            display: inline-block;
            width: 88px;
            line-height: 16px;
            vertical-align: middle;
        }

        #convOption,
        #speechOption,
        #speechDetail,
        #recOption {
            margin-bottom: 6px;
        }

        #convOption>div,
        #speechOption>div,
        #speechDetail>div,
        #recOption div {
            margin-top: 7px;
        }

        #voiceRecSetting select,
        #speechDetail select {
            background: var(--chat-back);
            color: var(--chat-text-color);
        }

        .inputTextClass {
            outline: none;
            border-radius: 2px;
            margin-top: 3px;
            height: 32px;
            font-size: 15px;
            padding-left: 6px;
            background: var(--chat-back);
            color: var(--chat-text-color);
            border: none;
        }

        .areaTextClass {
            width: 100%;
            height: 80px;
            display: block;
            resize: none;
            padding: 6px;
        }

        input[type="range"] {
            -webkit-appearance: none;
            appearance: none;
            display: block;
            margin: 4px 0 3px 0;
            height: 8px;
            background: var(--text-color);
            border-radius: 5px;
            background-image: linear-gradient(#99c959, #99c959);
            background-size: 100% 100%;
            background-repeat: no-repeat;
        }

        input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            height: 15px;
            width: 15px;
            border-radius: 50%;
            background: #99c959;
            cursor: ew-resize;
        }

        input[type=range]::-webkit-slider-runnable-track {
            -webkit-appearance: none;
            box-shadow: none;
            border: none;
            background: transparent;
        }

        .justSetLine {
            display: flex;
            justify-content: space-between;
        }

        .justSetBtn {
            height: 32px;
            border-radius: 3px;
            line-height: 32px;
            background: var(--lighter-active);
            text-align: center;
            padding: 0px 8px;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
        }

        .justSetBtn:hover {
            background-color: var(--sel-btn);
        }

        .justSetBtn>svg {
            margin-right: 3px;
        }

        .readyTestVoice>div:not(:first-child) {
            display: none;
        }

        .pauseTestVoice>div:nth-child(1),
        .pauseTestVoice>div:nth-child(3) {
            display: none;
        }

        .resumeTestVoice>div:nth-child(1),
        .resumeTestVoice>div:nth-child(2) {
            display: none;
        }

        .presetSelect>div {
            display: inline-block;
        }

        .presetSelect select {
            outline: none;
            border-radius: 3px;
            width: 128px;
            border-color: rgba(0, 0, 0, .3);
            background: var(--chat-back);
            color: var(--chat-text-color);
        }

        .selectDef {
            display: flex;
            justify-content: space-between;
            font-size: 13px;
            color: var(--text-color);
        }

        #preSetSpeech {
            width: 100%;
            outline: none;
            height: 30px;
            font-size: 14px;
            margin-top: 5px;
            border-radius: 3px;
            border-color: rgba(0, 0, 0, .3);
        }

        .mdOption {
            flex-shrink: 0;
            position: relative;
            width: 30px;
            pointer-events: none;
        }

        .mdOption>div {
            pointer-events: auto;
            cursor: pointer;
        }

        .mdOption svg * {
            pointer-events: none;
        }

        .refreshReq svg:not(:first-child) {
            display: none;
        }

        .halfRefReq svg:not(:nth-child(2)) {
            display: none;
        }

        .optionItems {
            position: absolute;
            bottom: -12px;
            display: flex;
            justify-content: space-between;
            visibility: hidden;
            z-index: 1;
            color: var(--svg-color);
        }

        .optionItems:hover {
            visibility: visible;
        }

        .request:hover .optionItems,
        .request:hover .voiceCls,
        .response:hover .optionItems,
        .response:hover .voiceCls {
            visibility: visible;
        }

        .optionItem {
            border-radius: 9px;
            height: 24px;
            width: 32px;
            border: 1px solid var(--active-btn);
            background-color: var(--response-color);
            display: flex !important;
            justify-content: center;
            align-items: center;
        }

        .optionItem * {
            pointer-events: none;
        }

        .optionItem:hover {
            background: var(--active-btn);
        }

        .voiceCls {
            position: relative;
            height: 100%;
            visibility: hidden;
            display: flex;
            align-items: center;
        }

        .voiceCls>svg {
            color: var(--lighter-svg-color);
            display: block;
            margin-left: 5px;
            position: relative;
        }

        .voiceCls:hover>svg {
            color: var(--svg-color);
        }

        .showVoiceCls,
        .showVoiceCls .markdown-body {
            background: var(--active-btn) !important;
        }

        .showVoiceCls .voiceCls {
            visibility: visible !important;
        }

        .showEditReq {
            position: sticky !important;
            top: 0;
            bottom: 0;
            z-index: 1;
        }

        .showEditReq,
        .showEditReq .markdown-body {
            background: var(--active-btn) !important;
        }

        .readyVoice svg:not(:first-child) {
            display: none;
        }

        .pauseVoice svg:not(:nth-child(2)) {
            display: none;
        }

        .resumeVoice svg:not(:nth-child(3)) {
            display: none;
        }

        #voiceTypes>span {
            border-radius: 3px;
            margin-left: 4px;
            height: 28px;
            line-height: 26px;
            display: inline-block;
            cursor: pointer;
            padding: 1px 5px;
        }

        #voiceTypes>span:hover {
            background: var(--active-btn);
        }

        .selVoiceType {
            background: var(--sel-btn) !important;
        }

        .navHeader {
            width: 100%;
            padding: 5px 10px;
            display: flex;
            justify-content: space-between;
        }

        #newChat {
            text-align: center;
            width: 80%;
            height: 40px;
            border-radius: 3px;
            background: var(--lighter-active-color);
            color: var(--btn-color);
            display: flex;
            align-items: center;
            justify-content: center;
            -webkit-user-select: none;
            user-select: none;
            cursor: pointer;
            flex: 1;
        }

        .navHeader>div:hover {
            background: var(--active-btn) !important;
        }

        #newChat>svg {
            margin-right: 2px;
        }

        #newFolder {
            height: 40px;
            width: 40px;
            margin-left: 10px;
            border-radius: 3px;
            color: var(--btn-color);
            cursor: pointer;
            position: relative;
            background: var(--lighter-active-color);
            -webkit-user-select: none;
            user-select: none;
        }

        #newFolder>svg {
            display: block;
            margin: 8px auto;
        }

        .extraChat {
            padding: 2px 10px 6px 10px;
            position: relative;
        }

        #searchChat {
            width: 100%;
            height: 36px;
            padding-left: 10px;
            padding-right: 45px;
            font-size: 16px;
            outline: none;
            border: none;
            color: var(--chat-text-color);
            background: var(--lighter-active-color);
            border-radius: 3px;
            -webkit-user-select: none;
            user-select: none;
        }

        #searchChat:focus {
            background: var(--active-btn)
        }

        #searchChat:placeholder-shown+#clearSearch {
            display: none;
        }

        #clearSearch {
            position: absolute;
            right: 34px;
            top: 8px;
            cursor: pointer;
            color: var(--btn-color);
        }

        #clearSearch:hover {
            color: var(--black-color);
        }

        #clearSearch>svg {
            display: block;
        }

        .seledSearch {
            background: var(--lighter-svg-color) !important;
        }

        #matchCaseSearch {
            position: absolute;
            right: 12px;
            top: 8px;
            cursor: pointer;
            border-radius: 3px;
            color: var(--btn-color);
        }

        #matchCaseSearch:hover {
            background: var(--sel-btn);
        }

        #matchCaseSearch>svg {
            display: block;
        }

        .navFooter {
            padding-bottom: 8px;
        }

        .navFooter .divider {
            width: 100%;
            border-top: 1px solid var(--active-btn);
            margin: 4px 0;
        }

        .navFunc {
            padding-top: 5px;
            display: flex;
            justify-content: space-around;
        }

        .navFunc svg {
            display: block;
        }

        .navFunc>div,
        .navFunc>label {
            border-radius: 20px;
            text-align: center;
            padding: 8px 8px;
            color: var(--btn-color);
            font-size: 14px;
            cursor: pointer;
        }

        .navFunc>div:hover,
        .navFunc>label:hover {
            background: var(--active-btn);
        }

        .navFooter .links {
            text-align: center;
            -webkit-user-select: none;
            user-select: none;
        }

        .navFooter .links a {
            color: var(--btn-color);
            text-decoration: none;
        }

        .navFooter .links a:hover {
            color: var(--chat-text-color) !important;
        }

        .navFooter .links a:visited {
            color: var(--btn-color);
        }

        .allList {
            width: 100%;
            position: relative;
            flex: 1;
            overflow-y: auto;
        }

        #chatList {
            min-height: 50px;
        }

        .dragingLi {
            filter: brightness(90%);
        }

        .dragingChat {
            background: var(--lighter-active-color);
        }

        .expandFolder>.headLi>svg {
            transform: rotate(90deg);
        }

        .expandFolder>.chatsInFolder {
            display: block;
        }

        .chatsInFolder {
            display: none;
            margin-left: 22px;
            padding-left: 2px;
            border-left: 1px solid var(--text-color);
        }

        .headLi,
        .chatLi {
            cursor: pointer;
            width: 100%;
            height: 50px;
            color: var(--text-color);
            display: flex;
            justify-content: space-between;
            align-items: center;
            position: relative;
        }

        .headLi *,
        .chatLi * {
            pointer-events: none;
        }

        .headLi>svg,
        .chatLi>svg {
            margin-left: 10px;
            color: var(--btn-color);
            pointer-events: none;
        }

        .folderOption svg,
        .chatOption svg {
            pointer-events: auto;
        }

        .headLi svg *,
        .chatLi svg * {
            pointer-events: none;
        }

        .headLi .folderInfo {
            position: absolute;
            left: 40px;
            height: 40px;
            max-width: calc(100% - 115px);
        }

        .chatLi .chatInfo {
            position: absolute;
            left: 40px;
            height: 40px;
            max-width: calc(100% - 90px);
        }

        .folderInfo *,
        .chatInfo * {
            -webkit-user-select: none;
            user-select: none;
        }

        .chatInfo span {
            background: #f8b26a;
        }

        .headLi .folderName,
        .chatLi .chatName {
            color: var(--btn-color);
            text-overflow: ellipsis;
            white-space: nowrap;
            overflow: hidden;
            line-height: 20px;
            height: 20px;
        }

        .headLi .folderNum,
        .chatLi .chatPre {
            color: var(--btn-color);
            text-overflow: ellipsis;
            white-space: nowrap;
            overflow: hidden;
            font-size: 12px;
            line-height: 20px;
            height: 20px;
        }

        .headLi .folderOption,
        .chatLi .chatOption {
            visibility: hidden;
            display: flex;
            color: #777;
            margin-right: 2px;
        }

        .folderLi .chatLi>svg {
            margin-left: 5px;
        }

        .folderLi .chatLi .chatInfo {
            left: 35px;
            max-width: calc(100% - 85px);
        }

        .folderLi .chatLi #activeChatEdit {
            left: 32px;
            width: calc(100% - 60px)
        }

        .folderLi:hover {
            background: var(--lighter-active);
        }

        .chatLi:hover {
            background: var(--active-btn);
        }

        .headLi:hover .folderOption,
        .chatLi:hover .chatOption {
            visibility: visible !important;
        }

        .activeFolder,
        .activeChatLi {
            background: var(--sel-btn) !important;
        }

        .activeChatLi .chatOption {
            visibility: visible !important;
        }

        .folderOption>svg:hover,
        .chatOption>svg:hover {
            color: #444;
        }

        #activeChatEdit {
            position: absolute;
            left: 37px;
            font-size: 16px;
            border-radius: 2px;
            color: var(--chat-text-color);
            background: var(--chat-back);
            outline: none;
            border: none;
            pointer-events: auto;
            height: 24px;
            line-height: 24px;
            width: calc(100% - 65px);
            padding: 20px 3px;
            z-index: 1;
        }

        #loadMask {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            z-index: 100;
            background-color: var(--background);
        }

        #loadMask>div {
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            text-align: center;
        }

        @keyframes loading {

            0%,
            100% {
                transform: scale(0);
            }

            50% {
                transform: scale(1);
            }
        }

        .loadingCSSIcon {
            position: relative;
            display: flex;
            align-items: center;
            justify-content: space-evenly;
        }

        .loadingCSSIcon div {
            width: 15%;
            height: 0;
            padding-bottom: 15%;
            border-radius: 50%;
            animation: loading 1s cubic-bezier(0.3, 0, 0.7, 1) infinite;
        }

        .loadingCSSIcon div:nth-child(1) {
            background: #e15b64;
            animation-delay: -0.4s
        }

        .loadingCSSIcon div:nth-child(2) {
            background: #f8b26a;
            animation-delay: -0.2s
        }

        .loadingCSSIcon div:nth-child(3) {
            background: #99c959;
            animation-delay: 0s;
        }

        #loadMask>div>:first-child {
            font-size: 40px;
            color: var(--text-color);
        }

        #loadMask>div>:last-child {
            width: 140px;
            height: 70px;
            margin: 0 auto;
        }

        #voiceRec {
            position: absolute;
            right: 0;
            top: 0;
            width: 47px;
            height: 100%;
        }

        .message_if_voice {
            padding-right: 47px !important;
        }

        #voiceRecIcon {
            width: 100%;
            height: 100%;
            text-align: center;
            cursor: pointer;
            position: relative;
        }

        #voiceRecIcon:hover>svg {
            color: var(--svg-color);
        }

        #voiceRecIcon>svg {
            width: 25px;
            height: 25px;
            color: #b0b0b0;
            position: absolute;
            top: 50%;
            left: 50%;
            margin-top: -12px;
            margin-left: -13px;
        }

        #voiceRecIcon>svg .animVoice {
            display: none;
        }

        .voiceRecing>svg {
            color: #99c959 !important;
        }

        .voiceRecing .animVoice {
            display: inline !important;
            transform-origin: 0 64%;
            animation-duration: 1.5s;
            animation-name: scaleVoice;
            animation-timing-function: ease;
            animation-iteration-count: infinite;
        }

        .voiceLong .animVoice {
            display: inline !important;
            transform-origin: 0 64%;
            animation-duration: 0.3s;
            animation-name: longVoice;
            animation-timing-function: ease-in-out;
            animation-iteration-count: 1;
        }

        @keyframes longVoice {
            0% {
                transform: scaleY(0);
            }

            100% {
                transform: scaleY(1);
            }
        }

        @keyframes scaleVoice {
            0% {
                transform: scaleY(0.28);
            }

            20% {
                transform: scaleY(0.60);
            }

            28% {
                transform: scaleY(0.28);
            }

            36% {
                transform: scaleY(0.45);
            }

            44% {
                transform: scaleY(0.28);
            }

            52% {
                transform: scaleY(0.45);
            }

            62% {
                transform: scaleY(0.80);
            }

            72% {
                transform: scaleY(0.80);
            }

            90% {
                transform: scaleY(0.28);
            }

            100% {
                transform: scaleY(0.28);
            }
        }

        #voiceRecSetting {
            display: none;
            position: absolute;
            top: -70px;
            left: -26px;
            z-index: 1;
            padding: 4px 4px;
            -webkit-user-select: none;
            user-select: none;
            border-radius: 3px;
            background-color: var(--main-back);
            box-shadow: 0 0 6px rgba(0, 0, 0, 0.15);
        }

        #voiceRecSetting select {
            width: 102px;
            outline: none;
            height: 28px;
            border-radius: 3px;
            border-color: rgba(0, 0, 0, .3);
        }

        .presetModelCls label {
            margin-right: 8px;
        }

        .presetModelCls select {
            height: 30px;
            margin-top: 2px;
            font-size: 15px;
        }

        .modelSwitch,
        .setSwitch {
            display: flex;
        }

        .modelSwitch {
            margin-bottom: 10px;
            -webkit-user-select: none;
            user-select: none;
        }

        .modelSwitch>div,
        .setSwitch>div {
            border-radius: 3px;
            width: calc(100% / 3);
            height: 32px;
            line-height: 32px;
            text-align: center;
            cursor: pointer;
        }

        .modelSwitch>div:hover,
        .setSwitch>div:hover {
            background-color: var(--active-btn);
        }

        .activeSwitch {
            background-color: var(--sel-btn) !important;
        }

        .checkLoad {
            height: 32px;
            border-radius: 3px;
            line-height: 32px;
            background: var(--sel-btn);
            text-align: center;
            display: flex;
            justify-content: center;
            cursor: pointer;
        }

        .checkLoad:hover {
            background: var(--lighter-svg-color);
        }

        .voiceChecking {
            background-color: var(--lighter-svg-color) !important;
        }

        .voiceChecking>svg {
            display: inline !important;
        }

        .checkLoad>svg {
            display: none;
            margin-right: 8px;
            height: 32px;
            width: 64px;
        }

        #preSetSystem {
            height: 20px;
            line-height: 20px;
            vertical-align: top;
        }

        #sysMask {
            display: none;
            position: fixed;
            z-index: 200;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            cursor: pointer;
            justify-content: center;
            align-items: center;
            background: rgba(0, 0, 0, .4);
            -webkit-tap-highlight-color: transparent;
        }

        #sysDialog {
            position: relative;
            background: var(--chat-back);
            color: var(--btn-color);
            cursor: auto;
            max-height: 100%;
            width: 88%;
            display: flex;
            flex-direction: column;
            border-radius: 4px;
            padding: 12px 20px 12px 20px;
        }

        .sysTitle {
            font-size: 20px;
            font-weight: bold;
            margin-bottom: 8px;
            -webkit-user-select: none;
            user-select: none;
        }

        .sysSwitch,
        .sysSwitch>div * {
            pointer-events: none;
        }

        .sysSwitch>div {
            border-radius: 3px;
            height: 32px;
            line-height: 32px;
            text-align: center;
            cursor: pointer;
            pointer-events: auto;
            font-weight: bold;
            display: flex;
            align-items: center;
            -webkit-user-select: none;
            user-select: none;
        }

        .sysSwitch>div>svg {
            margin-right: 4px;
        }

        .sysSwitch>div:hover {
            background-color: var(--active-btn);
        }

        .sysDetail {
            flex: 1;
        }

        #closeSet {
            position: absolute;
            right: 0px;
            top: 0px;
            cursor: pointer;
            padding: 10px 14px;
        }

        #closeSet:hover {
            color: var(--black-color);
        }

        .setContent {
            margin-bottom: 10px;
        }

        .setNotNormalFlow {
            position: relative;
        }

        .setTitle {
            margin-bottom: 6px;
            font-weight: bold;
            -webkit-user-select: none;
            user-select: none;
        }

        .setDetail {
            margin: 0 10px;
            -webkit-user-select: none;
            user-select: none;
        }

        .autoSelect>label,
        .autoSelect>input {
            cursor: pointer;
        }

        .dataDetail {
            display: flex;
        }

        .dataDetail svg {
            margin-right: 4px;
        }

        .dataDetail>div,
        .dataDetail>label {
            border-radius: 3px;
            text-align: center;
            padding: 6px 8px;
            margin-right: 12px;
            color: var(--btn-color);
            font-size: 15px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: space-between;
        }

        .dataDetail>div:hover,
        .dataDetail>label:hover {
            background: var(--lighter-active-color);
        }

        .keyOptionDetail {
            display: flex;
            margin-top: 10px;
        }

        #resetHotKey {
            display: flex;
            align-items: center;
            justify-content: space-between;
            cursor: pointer;
            font-size: 15px;
            color: var(--btn-color);
            border-radius: 3px;
            padding: 6px 8px;
            margin-left: 90px;
        }

        #resetHotKey>svg {
            margin-right: 4px;
        }

        #resetHotKey:hover {
            background: var(--lighter-active-color);
        }

        .hotKeyDetail>div {
            position: relative;
            height: 30px;
            margin-bottom: 2px;
        }

        .hotKeyDetail label {
            line-height: 30px;
        }

        .hotKeyDetail select {
            position: absolute;
            left: 110px;
            outline: none;
            border-radius: 3px;
            width: 120px;
            border-color: rgba(0, 0, 0, .3);
            background: var(--chat-back);
            color: var(--chat-text-color);
            height: 30px;
            font-size: 15px;
        }

        .avatarDetail {
            display: flex;
            margin-top: 2px;
        }

        .avatarDetail img {
            border-radius: 2px;
            width: 32px;
            height: 32px;
            flex-shrink: 0;
            margin-right: 8px;
            margin-top: 2px;
        }

        .inputDetail input {
            outline: none;
            border-radius: 3px;
            padding-left: 8px;
            font-size: 15px;
            width: 100%;
            height: 34px;
            border: 1px solid rgba(0, 0, 0, .3);
            background: var(--chat-back);
            color: var(--chat-text-color);
        }

        .themeDetail {
            display: flex;
            width: 180px;
            justify-content: space-between;
            pointer-events: none;
        }

        .themeDetail svg {
            display: block;
        }

        .themeDetail>div {
            pointer-events: auto;
            border-radius: 20px;
            text-align: center;
            padding: 8px 8px;
            color: var(--btn-color);
            font-size: 14px;
            cursor: pointer;
        }

        .themeDetail>div * {
            pointer-events: none;
        }

        .themeDetail>div:hover {
            background: var(--lighter-active-color);
        }

        .darkTheme>div:first-child {
            background: var(--sel-btn);
        }

        .lightTheme>div:nth-child(2) {
            background: var(--sel-btn);
        }

        .autoTheme>div:nth-child(3) {
            background: var(--sel-btn);
        }

        .langDetail {
            width: 110px;
        }

        .enLang>div:first-child {
            background: var(--sel-btn);
        }

        .zhLang>div:nth-child(2) {
            background: var(--sel-btn);
        }

        #customAutoSet input {
            width: 100px;
            height: 30px;
            line-height: 30px;
            font-size: 15px;
            outline: none;
            border: 1px solid rgba(0, 0, 0, .3);
            text-align: center;
            border-radius: 3px;
            background: var(--chat-back);
            color: var(--chat-text-color);
        }

        #customAutoSet label {
            margin-right: 8px;
        }

        .progressBar {
            position: relative;
            width: 100%;
            height: 12px;
            border-radius: 6px;
            background: var(--active-btn);
            overflow: hidden;
        }

        .nowProgress {
            position: absolute;
            left: 0;
            top: 0;
            height: 12px;
            min-width: 1px;
            border-radius: 6px;
            background: #99c959;
        }

        .progressDetail {
            display: flex;
            justify-content: space-between;
            font-size: 15px;
        }

        .cursorCls {
            background: var(--chat-text-color);
            width: 4px;
            animation: 1s cursor-blinker infinite step-start;
        }

        @keyframes cursor-blinker {
            0% {
                opacity: 0;
            }

            50% {
                opacity: 1;
            }

            100% {
                opacity: 0;
            }
        }

        .apiSelsContainer {
            position: relative;
            z-index: 1;
        }

        #apiSelect {
            position: absolute;
            top: 64px;
            padding: 4px 0;
            background: var(--chat-back);
            width: calc(100% - 20px);
            left: 10px;
            box-shadow: 0 0 6px rgba(0, 0, 0, 0.15);
            max-height: 180px;
            overflow-y: auto;
            -webkit-user-select: none;
            user-select: none;
        }

        #apiSelect>div {
            pointer-events: auto;
            cursor: pointer;
            font-size: 15px;
            padding: 6px 0 6px 8px;
            height: 36px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        #apiSelect>div:hover {
            background: var(--lighter-active-color);
        }

        #apiSelect>div>span {
            height: 100%;
            line-height: 23px;
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
        }

        #apiSelect>div * {
            pointer-events: none;
        }

        .delApiOption:hover {
            background: var(--lighter-svg-color);
        }

        .delApiOption {
            width: 36px;
            height: 36px;
            flex-shrink: 0;
            pointer-events: auto !important;
        }

        .delApiOption>svg {
            margin: 6px;
            display: block;
        }

        @keyframes textInOut {
            from {
                opacity: 0;
            }

            to {
                opacity: 1;
            }
        }

        .response[data-loading="true"]>.markdown-body>*:not(.cursorCls) {
            animation: textInOut 0.48s ease-in-out forwards;
        }
    </style>
    <style>
        /* for katex */
        .katex {
            font-size: 1em !important;
        }

        eq {
            display: inline-block;
        }

        eqn {
            display: block
        }

        section.eqno {
            display: flex;
            flex-direction: row;
            align-content: space-between;
            align-items: center;
        }

        section.eqno>eqn {
            width: 100%;
            margin-left: 3em;
        }

        section.eqno>span {
            width: 3em;
            text-align: right;
        }
    </style>
    <script>
        let themeMode; // 2: 自动， 1: 浅色，0: 深色
        let autoThemeMode; // 1: 跟随系统，0:自定义时间
        let customDarkTime; // 开始，结束时间
        let isFull = false; // 是否全屏
        const darkMedia = window.matchMedia("(prefers-color-scheme: dark)");
        const justDarkTheme = (is) => {
            if (is) document.documentElement.setAttribute("data-theme", "dark");
            else document.documentElement.removeAttribute("data-theme");
            document.head.children[4].content = document.head.children[5].content = document.head.children[6].content = getComputedStyle(document.documentElement).getPropertyValue("--background");
        }
        const checkDark = () => {
            const checkCustomTheme = () => {
                let date = new Date();
                let nowTime = date.getTime();
                let start = customDarkTime[0].split(":");
                let startTime = new Date().setHours(start[0], start[1], 0, 0);
                let end = customDarkTime[1].split(":");
                let endTime = new Date().setHours(end[0], end[1], 0, 0);
                let order = endTime > startTime;
                let isDark = order ? (nowTime > startTime && endTime > nowTime) : !(nowTime > endTime && startTime > nowTime);
                justDarkTheme(isDark);
            }
            const setDarkMode = () => {
                if (themeMode === 2) {
                    if (autoThemeMode) {
                        justDarkTheme(darkMedia.matches);
                    } else {
                        checkCustomTheme();
                    }
                } else if (themeMode === 1) {
                    justDarkTheme(false);
                } else {
                    justDarkTheme(true);
                }
                localStorage.setItem("themeMode", themeMode);
            }
            let localTheme = localStorage.getItem("themeMode");
            themeMode = parseInt(localTheme || "0");
            let localAutoTheme = localStorage.getItem("autoThemeMode");
            autoThemeMode = parseInt(localAutoTheme || "1");
            let localCustomDark = localStorage.getItem("customDarkTime");
            customDarkTime = JSON.parse(localCustomDark || '["21:00", "07:00"]');
            setDarkMode();
        }
        checkDark();
    </script>
</head>

<body>
    <svg style="transform: translate(-1000px, -1000px);">
        <defs>
            <radialGradient id="paint0_radial_16771_53212" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse"
                gradientTransform="translate(2.77876 11.3795) rotate(18.6832) scale(29.8025 238.737)">
                <stop offset="0.0671246" stop-color="#9168C0" />
                <stop offset="0.342551" stop-color="#5684D1" />
                <stop offset="0.672076" stop-color="#1BA1E3" />
            </radialGradient>
        </defs>
    </svg>
    <div style="display: none">
        <svg>
            <symbol viewBox="0 0 28 28" id="geminiIcon">
                <path
                    d="M14 28C14 26.0633 13.6267 24.2433 12.88 22.54C12.1567 20.8367 11.165 19.355 9.905 18.095C8.645 16.835 7.16333 15.8433 5.46 15.12C3.75667 14.3733 1.93667 14 0 14C1.93667 14 3.75667 13.6383 5.46 12.915C7.16333 12.1683 8.645 11.165 9.905 9.905C11.165 8.645 12.1567 7.16333 12.88 5.46C13.6267 3.75667 14 1.93667 14 0C14 1.93667 14.3617 3.75667 15.085 5.46C15.8317 7.16333 16.835 8.645 18.095 9.905C19.355 11.165 20.8367 12.1683 22.54 12.915C24.2433 13.6383 26.0633 14 28 14C26.0633 14 24.2433 14.3733 22.54 15.12C20.8367 15.8433 19.355 16.835 18.095 18.095C16.835 19.355 15.8317 20.8367 15.085 22.54C14.3617 24.2433 14 26.0633 14 28Z"
                    fill="url(#paint0_radial_16771_53212)" />
            </symbol>
            <symbol viewBox="0 0 40 40" id="claudeIcon">
                <path shape-rendering="optimizeQuality" fill="#D97757"
                    d="m7.75 26.27 7.77-4.36.13-.38-.13-.21h-.38l-1.3-.08-4.44-.12-3.85-.16-3.73-.2-.94-.2L0 19.4l.09-.58.79-.53 1.13.1 2.5.17 3.75.26 2.72.16 4.03.42h.64l.09-.26-.22-.16-.17-.16-3.88-2.63-4.2-2.78-2.2-1.6L3.88 11l-.6-.76-.26-1.66L4.1 7.39l1.45.1.37.1 1.47 1.13 3.14 2.43 4.1 3.02.6.5.24-.17.03-.12-.27-.45L13 9.9l-2.38-4.1-1.06-1.7-.28-1.02c-.1-.42-.17-.77-.17-1.2L10.34.21l.68-.22 1.64.22.69.6 1.02 2.33 1.65 3.67 2.56 4.99.75 1.48.4 1.37.15.42h.26v-.24l.21-2.81.39-3.45.38-4.44.13-1.25.62-1.5L23.1.57l.96.46.79 1.13-.11.73-.47 3.05-.92 4.78-.6 3.2h.35l.4-.4 1.62-2.15 2.72-3.4 1.2-1.35 1.4-1.49.9-.71h1.7l1.25 1.86-.56 1.92-1.75 2.22-1.45 1.88-2.08 2.8-1.3 2.24.12.18.31-.03 4.7-1 2.54-.46 3.03-.52 1.37.64.15.65-.54 1.33-3.24.8-3.8.76-5.66 1.34-.07.05.08.1 2.55.24 1.09.06h2.67l4.97.37 1.3.86.78 1.05-.13.8-2 1.02-2.7-.64-6.3-1.5-2.16-.54h-.3v.18l1.8 1.76 3.3 2.98 4.13 3.84.21.95-.53.75-.56-.08-3.63-2.73-1.4-1.23-3.17-2.67h-.21v.28l.73 1.07 3.86 5.8.2 1.78-.28.58-1 .35-1.1-.2L26 33.14l-2.33-3.57-1.88-3.2-.23.13-1.11 11.95-.52.61-1.2.46-1-.76-.53-1.23.53-2.43.64-3.17.52-2.52.47-3.13.28-1.04-.02-.07-.23.03-2.36 3.24-3.59 4.85-2.84 3.04-.68.27-1.18-.61.11-1.09.66-.97 3.93-5 2.37-3.1 1.53-1.79-.01-.26h-.09L6.8 30.56l-1.86.24-.8-.75.1-1.23.38-.4 3.14-2.16Z">
                </path>
            </symbol>
            <symbol viewBox="0 0 16 16" id="expandIcon">
                <path fill="currentColor"
                    d="M12.78 5.22a.749.749 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.06 0L3.22 6.28a.749.749 0 1 1 1.06-1.06L8 8.939l3.72-3.719a.749.749 0 0 1 1.06 0Z">
                </path>
            </symbol>
            <symbol viewBox="0 0 24 24" id="refreshIcon">
                <path fill="currentColor"
                    d="M3.07 10.876C3.623 6.436 7.41 3 12 3a9.15 9.15 0 0 1 6.012 2.254V4a1 1 0 1 1 2 0v4a1 1 0 0 1-1 1H15a1 1 0 1 1 0-2h1.957A7.15 7.15 0 0 0 12 5a7 7 0 0 0-6.946 6.124 1 1 0 1 1-1.984-.248m16.992 1.132a1 1 0 0 1 .868 1.116C20.377 17.564 16.59 21 12 21a9.15 9.15 0 0 1-6-2.244V20a1 1 0 1 1-2 0v-4a1 1 0 0 1 1-1h4a1 1 0 1 1 0 2H7.043A7.15 7.15 0 0 0 12 19a7 7 0 0 0 6.946-6.124 1 1 0 0 1 1.116-.868">
                </path>
            </symbol>
            <symbol viewBox="0 0 24 24" id="halfRefIcon">
                <path fill="currentColor"
                    d="M3.07 10.876C3.623 6.436 7.41 3 12 3a9.15 9.15 0 0 1 6.012 2.254V4a1 1 0 1 1 2 0v4a1 1 0 0 1-1 1H15a1 1 0 1 1 0-2h1.957A7.15 7.15 0 0 0 12 5a7 7 0 0 0-6.946 6.124 1 1 0 1 1-1.984-.248" />
            </symbol>
            <symbol viewBox="-2 -2 20 20" id="copyIcon">
                <path fill="currentColor"
                    d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z">
                </path>
                <path fill="currentColor"
                    d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z">
                </path>
            </symbol>
            <symbol viewBox="0 0 24 24" id="delIcon">
                <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                    d="M9 7v0a3 3 0 0 1 3-3v0a3 3 0 0 1 3 3v0M9 7h6M9 7H6m9 0h3m2 0h-2M4 7h2m0 0v11a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7">
                </path>
            </symbol>
            <symbol viewBox="0 0 24 24" id="readyVoiceIcon">
                <path fill="currentColor"
                    d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z">
                </path>
            </symbol>
            <symbol viewBox="0 0 20 20" id="pauseVoiceIcon">
                <path stroke="currentColor" stroke-width="2.4" d="M6 3v14M14 3v14"></path>
            </symbol>
            <symbol viewBox="0 0 16 16" id="resumeVoiceIcon">
                <path fill="currentColor" d="M4 3L4 13L12 8Z"></path>
            </symbol>
            <symbol viewBox="0 0 24 24" id="stopResIcon">
                <path fill="currentColor"
                    d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10s-4.477 10-10 10zm0-2a8 8 0 1 0 0-16a8 8 0 0 0 0 16zM9 9h6v6H9V9z">
                </path>
            </symbol>
            <symbol viewBox="0 0 128 128" id="downAudioIcon">
                <path
                    d="M 64.662 1.549 C 56.549 4.524, 46.998 14.179, 45.523 20.895 C 45.041 23.089, 44.073 23.833, 40.433 24.807 C 34.752 26.326, 27.956 32.929, 25.527 39.289 C 24.273 42.574, 23.884 45.715, 24.196 50.034 C 24.620 55.897, 24.528 56.193, 21.836 57.585 C 17.142 60.012, 16 63.617, 16 76 C 16 88.463, 17.137 91.985, 21.967 94.483 C 28.244 97.729, 36.120 95.350, 38.579 89.466 C 39.387 87.532, 40 82.764, 40 78.415 C 40 70.971, 40.060 70.783, 42.250 71.370 C 43.487 71.701, 48.888 71.979, 54.250 71.986 L 64 72 64 76 L 64 80 57.122 80 C 49.420 80, 48.614 80.543, 47.547 86.453 C 46.552 91.964, 43.550 97.473, 40.273 99.803 C 33 104.974, 23.120 105.042, 16.118 99.971 C 11.407 96.558, 9.048 92.484, 8.145 86.205 C 6.963 77.979, 0.794 77.729, 0.191 85.883 C -0.196 91.111, 3.323 99.170, 8.062 103.908 C 11.290 107.136, 20.073 111.969, 22.750 111.990 C 23.540 111.996, 24 113.472, 24 116 C 24 119.740, 23.813 120, 21.122 120 C 17.674 120, 15.727 122.044, 16.173 125.195 C 16.492 127.441, 16.781 127.500, 27.391 127.500 C 36.676 127.500, 38.445 127.242, 39.386 125.750 C 40.993 123.203, 38.986 120.568, 35.149 120.187 C 32.206 119.894, 32 119.617, 32 115.956 C 32 112.509, 32.330 111.959, 34.750 111.377 C 42.181 109.591, 52.157 101.208, 53.575 95.559 C 53.928 94.152, 54.514 93, 54.878 93 C 55.242 93, 59.797 97.275, 65 102.500 C 70.762 108.286, 75.256 112, 76.495 112 C 77.769 112, 83.287 107.231, 91.264 99.236 C 101.113 89.366, 104 85.876, 104 83.843 C 104 80.580, 102.553 80, 94.418 80 L 88 80 88 76.105 L 88 72.211 99.750 71.815 C 113.117 71.364, 117.595 69.741, 122.762 63.473 C 128.159 56.925, 129.673 45.269, 126.134 37.500 C 123.787 32.346, 117.218 26.445, 112.132 24.921 C 108.617 23.868, 107.767 22.968, 105.028 17.405 C 99.364 5.901, 89.280 -0.062, 75.712 0.070 C 71.746 0.109, 66.773 0.774, 64.662 1.549 M 67.885 9.380 C 60.093 12.164, 55.057 17.704, 52.527 26.276 C 51.174 30.856, 50.220 31.617, 44.729 32.496 C 37.017 33.729, 30.917 42.446, 32.374 50.154 C 34.239 60.026, 40.582 63.944, 54.750 63.978 L 64 64 64 57.122 C 64 52.457, 64.449 49.872, 65.396 49.086 C 66.310 48.328, 70.370 48.027, 77.146 48.214 L 87.500 48.500 87.794 56.359 L 88.088 64.218 98.989 63.845 C 108.043 63.535, 110.356 63.125, 112.634 61.424 C 119.736 56.122, 121.911 47.667, 118.097 40.190 C 115.870 35.824, 110.154 32.014, 105.790 31.985 C 102.250 31.961, 101.126 30.787, 99.532 25.443 C 95.580 12.197, 80.880 4.736, 67.885 9.380 M 72 70.800 C 72 80.978, 71.625 85.975, 70.800 86.800 C 70.140 87.460, 67.781 88, 65.559 88 L 61.517 88 68.759 95.241 L 76 102.483 83.241 95.241 L 90.483 88 86.441 88 C 84.219 88, 81.860 87.460, 81.200 86.800 C 80.375 85.975, 80 80.978, 80 70.800 L 80 56 76 56 L 72 56 72 70.800 M 25.200 65.200 C 23.566 66.834, 23.566 85.166, 25.200 86.800 C 27.002 88.602, 29.798 88.246, 30.965 86.066 C 31.534 85.002, 32 80.472, 32 76 C 32 71.528, 31.534 66.998, 30.965 65.934 C 29.798 63.754, 27.002 63.398, 25.200 65.200"
                    stroke="none" fill="currentColor" fill-rule="evenodd" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="chatIcon">
                <path fill="currentColor"
                    d="m18 21l-1.4-1.4l1.575-1.6H14v-2h4.175L16.6 14.4L18 13l4 4l-4 4ZM3 21V6q0-.825.588-1.413T5 4h12q.825 0 1.413.588T19 6v5.075q-.25-.05-.5-.063T18 11q-.25 0-.5.013t-.5.062V6H5v10h7.075q-.05.25-.063.5T12 17q0 .25.013.5t.062.5H6l-3 3Zm4-11h8V8H7v2Zm0 4h5v-2H7v2Zm-2 2V6v10Z" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="chatEditIcon">
                <path fill="currentColor"
                    d="M5 19h1.4l8.625-8.625l-1.4-1.4L5 17.6V19ZM19.3 8.925l-4.25-4.2l1.4-1.4q.575-.575 1.413-.575t1.412.575l1.4 1.4q.575.575.6 1.388t-.55 1.387L19.3 8.925ZM17.85 10.4L7.25 21H3v-4.25l10.6-10.6l4.25 4.25Zm-3.525-.725l-.7-.7l1.4 1.4l-.7-.7Z">
                </path>
            </symbol>
            <symbol viewBox="0 0 24 24" id="deleteIcon">
                <path fill="currentColor"
                    d="M8 20v-5h2v5h9v-7H5v7h3zm-4-9h16V8h-6V4h-4v4H4v3zM3 21v-8H2V7a1 1 0 0 1 1-1h5V3a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v3h5a1 1 0 0 1 1 1v6h-1v8a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1z">
                </path>
            </symbol>
            <symbol viewBox="0 0 24 24" id="addIcon" stroke="currentColor" fill="none" stroke-width="2"
                stroke-linecap="round" stroke-linejoin="round">
                <line x1="12" y1="5" x2="12" y2="19"></line>
                <line x1="5" y1="12" x2="19" y2="12"></line>
            </symbol>
            <symbol viewBox="0 0 200 100" preserveAspectRatio="xMidYMid" id="loadingIcon">
                <g transform="translate(50 50)">
                    <circle cx="0" cy="0" r="15" fill="#e15b64">
                        <animateTransform attributeName="transform" type="scale" begin="-0.4s" calcMode="spline"
                            keySplines="0.3 0 0.7 1;0.3 0 0.7 1" values="0;1;0" keyTimes="0;0.5;1" dur="1s"
                            repeatCount="indefinite"></animateTransform>
                    </circle>
                </g>
                <g transform="translate(100 50)">
                    <circle cx="0" cy="0" r="15" fill="#f8b26a">
                        <animateTransform attributeName="transform" type="scale" begin="-0.2s" calcMode="spline"
                            keySplines="0.3 0 0.7 1;0.3 0 0.7 1" values="0;1;0" keyTimes="0;0.5;1" dur="1s"
                            repeatCount="indefinite"></animateTransform>
                    </circle>
                </g>
                <g transform="translate(150 50)">
                    <circle cx="0" cy="0" r="15" fill="#99c959">
                        <animateTransform attributeName="transform" type="scale" begin="0s" calcMode="spline"
                            keySplines="0.3 0 0.7 1;0.3 0 0.7 1" values="0;1;0" keyTimes="0;0.5;1" dur="1s"
                            repeatCount="indefinite"></animateTransform>
                    </circle>
                </g>
            </symbol>
            <symbol viewBox="0 0 24 24" id="exportIcon">
                <path fill="currentColor"
                    d="m17.86 18l1.04 1c-1.4 1.2-3.96 2-6.9 2c-4.41 0-8-1.79-8-4V7c0-2.21 3.58-4 8-4c2.95 0 5.5.8 6.9 2l-1.04 1l-.36.4C16.65 5.77 14.78 5 12 5C8.13 5 6 6.5 6 7s2.13 2 6 2c1.37 0 2.5-.19 3.42-.46l.96.96H13.5v1.42c-.5.05-1 .08-1.5.08c-2.39 0-4.53-.53-6-1.36v2.81C7.3 13.4 9.58 14 12 14c.5 0 1-.03 1.5-.08v.58h2.88l-1 1l.12.11c-1.09.25-2.26.39-3.5.39c-2.28 0-4.39-.45-6-1.23V17c0 .5 2.13 2 6 2c2.78 0 4.65-.77 5.5-1.39l.36.39m1.06-10.92L17.5 8.5L20 11h-5v2h5l-2.5 2.5l1.42 1.42L23.84 12l-4.92-4.92Z" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="importIcon">
                <path fill="currentColor"
                    d="m8.84 12l-4.92 4.92L2.5 15.5L5 13H0v-2h5L2.5 8.5l1.42-1.42L8.84 12M12 3C8.59 3 5.68 4.07 4.53 5.57L5 6l1.03 1.07C6 7.05 6 7 6 7c0-.5 2.13-2 6-2s6 1.5 6 2s-2.13 2-6 2c-2.62 0-4.42-.69-5.32-1.28l3.12 3.12c.7.1 1.44.16 2.2.16c2.39 0 4.53-.53 6-1.36v2.81c-1.3.95-3.58 1.55-6 1.55c-.96 0-1.9-.1-2.76-.27l-1.65 1.64c1.32.4 2.82.63 4.41.63c2.28 0 4.39-.45 6-1.23V17c0 .5-2.13 2-6 2s-6-1.5-6-2v-.04L5 18l-.46.43C5.69 19.93 8.6 21 12 21c4.41 0 8-1.79 8-4V7c0-2.21-3.58-4-8-4Z" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="clearAllIcon">
                <path fill="currentColor"
                    d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10s-4.477 10-10 10zm0-2a8 8 0 1 0 0-16a8 8 0 0 0 0 16zm0-9.414l2.828-2.829l1.415 1.415L13.414 12l2.829 2.828l-1.415 1.415L12 13.414l-2.828 2.829l-1.415-1.415L10.586 12L7.757 9.172l1.415-1.415L12 10.586z">
                </path>
            </symbol>
            <symbol viewBox="0 0 24 24" id="collapseFullIcon">
                <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
                    stroke-width="1.5"
                    d="m20 20l-5-5m0 0v4m0-4h4M4 20l5-5m0 0v4m0-4H5M20 4l-5 5m0 0V5m0 4h4M4 4l5 5m0 0V5m0 4H5" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="expandFullIcon">
                <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
                    stroke-width="1.5"
                    d="M9 9L4 4m0 0v4m0-4h4m7 5l5-5m0 0v4m0-4h-4M9 15l-5 5m0 0v-4m0 4h4m7-5l5 5m0 0v-4m0 4h-4" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="darkThemeIcon">
                <path fill="currentColor"
                    d="M20.742 13.045a8.088 8.088 0 0 1-2.077.271c-2.135 0-4.14-.83-5.646-2.336a8.025 8.025 0 0 1-2.064-7.723A1 1 0 0 0 9.73 2.034a10.014 10.014 0 0 0-4.489 2.582c-3.898 3.898-3.898 10.243 0 14.143a9.937 9.937 0 0 0 7.072 2.93 9.93 9.93 0 0 0 7.07-2.929 10.007 10.007 0 0 0 2.583-4.491 1.001 1.001 0 0 0-1.224-1.224zm-2.772 4.301a7.947 7.947 0 0 1-5.656 2.343 7.953 7.953 0 0 1-5.658-2.344c-3.118-3.119-3.118-8.195 0-11.314a7.923 7.923 0 0 1 2.06-1.483 10.027 10.027 0 0 0 2.89 7.848 9.972 9.972 0 0 0 7.848 2.891 8.036 8.036 0 0 1-1.484 2.059z">
                </path>
            </symbol>
            <symbol viewBox="0 0 24 24" id="lightThemeIcon">
                <path fill="currentColor"
                    d="M6.993 12c0 2.761 2.246 5.007 5.007 5.007s5.007-2.246 5.007-5.007S14.761 6.993 12 6.993 6.993 9.239 6.993 12zM12 8.993c1.658 0 3.007 1.349 3.007 3.007S13.658 15.007 12 15.007 8.993 13.658 8.993 12 10.342 8.993 12 8.993zM10.998 19h2v3h-2zm0-17h2v3h-2zm-9 9h3v2h-3zm17 0h3v2h-3zM4.219 18.363l2.12-2.122 1.415 1.414-2.12 2.122zM16.24 6.344l2.122-2.122 1.414 1.414-2.122 2.122zM6.342 7.759 4.22 5.637l1.415-1.414 2.12 2.122zm13.434 10.605-1.414 1.414-2.122-2.122 1.414-1.414z">
                </path>
            </symbol>
            <symbol viewBox="0 0 24 24" id="autoThemeIcon">
                <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
                    <path d="M9.173 14.83a4 4 0 1 1 5.657-5.657" />
                    <path
                        d="m11.294 12.707l.174.247a7.5 7.5 0 0 0 8.845 2.492A9 9 0 0 1 5.642 18.36M3 12h1m8-9v1M5.6 5.6l.7.7M3 21L21 3" />
                </g>
            </symbol>
            <symbol viewBox="0 0 24 24" id="newFolderIcon">
                <path fill="currentColor"
                    d="M14 16h2v-2h2v-2h-2v-2h-2v2h-2v2h2v2ZM2 20V4h8l2 2h10v14H2Zm2-2h16V8h-8.825l-2-2H4v12Zm0 0V6v12Z" />
            </symbol>
            <symbol viewBox="0 0 20 20" id="expandFolderIcon">
                <path fill="currentColor"
                    d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z">
                </path>
            </symbol>
            <symbol viewBox="0 0 24 24" id="closeIcon">
                <path fill="currentColor"
                    d="M6.4 19L5 17.6l5.6-5.6L5 6.4L6.4 5l5.6 5.6L17.6 5L19 6.4L13.4 12l5.6 5.6l-1.4 1.4l-5.6-5.6L6.4 19Z" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="settingIcon">
                <path fill="currentColor"
                    d="M13.85 22.25h-3.7c-.74 0-1.36-.54-1.45-1.27l-.27-1.89c-.27-.14-.53-.29-.79-.46l-1.8.72c-.7.26-1.47-.03-1.81-.65L2.2 15.53c-.35-.66-.2-1.44.36-1.88l1.53-1.19c-.01-.15-.02-.3-.02-.46 0-.15.01-.31.02-.46l-1.52-1.19c-.59-.45-.74-1.26-.37-1.88l1.85-3.19c.34-.62 1.11-.9 1.79-.63l1.81.73c.26-.17.52-.32.78-.46l.27-1.91c.09-.7.71-1.25 1.44-1.25h3.7c.74 0 1.36.54 1.45 1.27l.27 1.89c.27.14.53.29.79.46l1.8-.72c.71-.26 1.48.03 1.82.65l1.84 3.18c.36.66.2 1.44-.36 1.88l-1.52 1.19c.01.15.02.3.02.46s-.01.31-.02.46l1.52 1.19c.56.45.72 1.23.37 1.86l-1.86 3.22c-.34.62-1.11.9-1.8.63l-1.8-.72c-.26.17-.52.32-.78.46l-.27 1.91c-.1.68-.72 1.22-1.46 1.22zm-3.23-2h2.76l.37-2.55.53-.22c.44-.18.88-.44 1.34-.78l.45-.34 2.38.96 1.38-2.4-2.03-1.58.07-.56c.03-.26.06-.51.06-.78s-.03-.53-.06-.78l-.07-.56 2.03-1.58-1.39-2.4-2.39.96-.45-.35c-.42-.32-.87-.58-1.33-.77l-.52-.22-.37-2.55h-2.76l-.37 2.55-.53.21c-.44.19-.88.44-1.34.79l-.45.33-2.38-.95-1.39 2.39 2.03 1.58-.07.56a7 7 0 0 0-.06.79c0 .26.02.53.06.78l.07.56-2.03 1.58 1.38 2.4 2.39-.96.45.35c.43.33.86.58 1.33.77l.53.22.38 2.55z">
                </path>
                <circle fill="currentColor" cx="12" cy="12" r="3.5"></circle>
            </symbol>
            <symbol viewBox="299 299 1808 1808" id="aiIcon">
                <path fill="currentColor"
                    d="M1107.3 299.1c-198 0-373.9 127.3-435.2 315.3C544.8 640.6 434.9 720.2 370.5 833c-99.3 171.4-76.6 386.9 56.4 533.8-41.1 123.1-27 257.7 38.6 369.2 98.7 172 297.3 260.2 491.6 219.2 86.1 97 209.8 152.3 339.6 151.8 198 0 373.9-127.3 435.3-315.3 127.5-26.3 237.2-105.9 301-218.5 99.9-171.4 77.2-386.9-55.8-533.9v-.6c41.1-123.1 27-257.8-38.6-369.8-98.7-171.4-297.3-259.6-491-218.6-86.6-96.8-210.5-151.8-340.3-151.2zm0 117.5-.6.6c79.7 0 156.3 27.5 217.6 78.4-2.5 1.2-7.4 4.3-11 6.1L952.8 709.3c-18.4 10.4-29.4 30-29.4 51.4V1248l-155.1-89.4V755.8c-.1-187.1 151.6-338.9 339-339.2zm434.2 141.9c121.6-.2 234 64.5 294.7 169.8 39.2 68.6 53.9 148.8 40.4 226.5-2.5-1.8-7.3-4.3-10.4-6.1l-360.4-208.2c-18.4-10.4-41-10.4-59.4 0L1024 984.2V805.4L1372.7 604c51.3-29.7 109.5-45.4 168.8-45.5zM650 743.5v427.9c0 21.4 11 40.4 29.4 51.4l421.7 243-155.7 90L597.2 1355c-162-93.8-217.4-300.9-123.8-462.8C513.1 823.6 575.5 771 650 743.5zm807.9 106 348.8 200.8c162.5 93.7 217.6 300.6 123.8 462.8l.6.6c-39.8 68.6-102.4 121.2-176.5 148.2v-428c0-21.4-11-41-29.4-51.4l-422.3-243.7 155-89.3zM1201.7 997l177.8 102.8v205.1l-177.8 102.8-177.8-102.8v-205.1L1201.7 997zm279.5 161.6 155.1 89.4v402.2c0 187.3-152 339.2-339 339.2v-.6c-79.1 0-156.3-27.6-217-78.4 2.5-1.2 8-4.3 11-6.1l360.4-207.5c18.4-10.4 30-30 29.4-51.4l.1-486.8zM1380 1421.9v178.8l-348.8 200.8c-162.5 93.1-369.6 38-463.4-123.7h.6c-39.8-68-54-148.8-40.5-226.5 2.5 1.8 7.4 4.3 10.4 6.1l360.4 208.2c18.4 10.4 41 10.4 59.4 0l421.9-243.7z" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="importSetIcon">
                <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                    d="m12 21l-8-4.5v-9L12 3l8 4.5V12m-8 0l8-4.5M12 12v9m0-9L4 7.5M22 18h-7m3-3l-3 3l3 3" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="exportSetIcon">
                <path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                    d="m12 21l-8-4.5v-9L12 3l8 4.5V12m-8 0l8-4.5M12 12v9m0-9L4 7.5M15 18h7m-3-3l3 3l-3 3" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="databaseIcon">
                <path fill="currentColor"
                    d="M12 3C7.58 3 4 4.79 4 7v10c0 2.21 3.59 4 8 4s8-1.79 8-4V7c0-2.21-3.58-4-8-4m6 14c0 .5-2.13 2-6 2s-6-1.5-6-2v-2.23c1.61.78 3.72 1.23 6 1.23s4.39-.45 6-1.23V17m0-4.55c-1.3.95-3.58 1.55-6 1.55s-4.7-.6-6-1.55V9.64c1.47.83 3.61 1.36 6 1.36s4.53-.53 6-1.36v2.81M12 9C8.13 9 6 7.5 6 7s2.13-2 6-2s6 1.5 6 2s-2.13 2-6 2Z" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="stopIcon">
                <path fill="currentColor" d="M6 5h12a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1Z" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="forceRefreshIcon">
                <path fill="currentColor"
                    d="M13.82 14H9.66c-.1-.66-.16-1.32-.16-2s.06-1.35.16-2h4.68c.09.65.16 1.32.16 2c0 .5-.04 1-.1 1.46c.6-.5 1.32-.89 2.1-1.14V12c0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2v.18c.7.17 1.35.45 1.95.82c.05-.32.05-.66.05-1c0-5.5-4.5-10-10-10C6.47 2 2 6.5 2 12s4.5 10 10 10c.34 0 .68 0 1-.05c-.41-.66-.71-1.4-.87-2.2c-.04.07-.08.14-.13.21c-.83-1.2-1.5-2.53-1.91-3.96h2.41c.31-.75.76-1.42 1.32-2m5.1-6h-2.95a15.65 15.65 0 0 0-1.38-3.56c1.84.63 3.37 1.9 4.33 3.56M12 4.03c.83 1.2 1.5 2.54 1.91 3.97h-3.82c.41-1.43 1.08-2.77 1.91-3.97M4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2s.06 1.34.14 2H4.26m.82 2H8c.35 1.25.8 2.45 1.4 3.56A8.008 8.008 0 0 1 5.08 16M8 8H5.08A7.923 7.923 0 0 1 9.4 4.44C8.8 5.55 8.35 6.75 8 8m12.83 7.67L22 14.5v4h-4l1.77-1.77A2.5 2.5 0 1 0 20 20h1.71A3.991 3.991 0 0 1 18 22.5c-2.21 0-4-1.79-4-4s1.79-4 4-4c1.11 0 2.11.45 2.83 1.17Z" />
            </symbol>
            <symbol viewBox="0 0 24 24" id="hotkeyIcon">
                <g fill="none">
                    <path
                        d="M24 0v24H0V0h24ZM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035c-.01-.004-.019-.001-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427c-.002-.01-.009-.017-.017-.018Zm.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093c.012.004.023 0 .029-.008l.004-.014l-.034-.614c-.003-.012-.01-.02-.02-.022Zm-.715.002a.023.023 0 0 0-.027.006l-.006.014l-.034.614c0 .012.007.02.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01l-.184-.092Z" />
                    <path fill="currentColor"
                        d="M18 3a3 3 0 0 1 2.995 2.824L21 6v12a3 3 0 0 1-2.824 2.995L18 21H6a3 3 0 0 1-2.995-2.824L3 18V6a3 3 0 0 1 2.824-2.995L6 3h12Zm-2.707 13.708A2.99 2.99 0 0 1 14 17H5v1a1 1 0 0 0 1 1h11.586l-2.293-2.292ZM18 5h-1v9c0 .386-.073.755-.206 1.094l-.086.2L19 17.585V6a1 1 0 0 0-.883-.993L18 5Zm-3 0H6a1 1 0 0 0-.993.883L5 6v9h9a1 1 0 0 0 .993-.883L15 14V5ZM9 7a1 1 0 0 1 .993.883L10 8v.631l1.445-.963a1 1 0 0 1 1.203 1.594l-.093.07l-1.377.918l1.377.918a1 1 0 0 1-1.009 1.723l-.1-.059L10 11.868V12a1 1 0 0 1-1.993.117L8 12V8a1 1 0 0 1 1-1Z" />
                </g>
            </symbol>
            <symbol viewBox="0 0 24 24" id="zhIcon">
                <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="2">
                    <path stroke-linejoin="round" d="M5 8h14v7H5z" />
                    <path d="M12 4v17" />
                </g>
            </symbol>
            <symbol viewBox="0 0 24 24" id="enIcon">
                <path fill="currentColor"
                    d="M14 10h2v.757a4.5 4.5 0 0 1 7 3.743V20h-2v-5.5c0-1.43-1.174-2.5-2.5-2.5S16 13.07 16 14.5V20h-2V10Zm-2-6v2H4v5h8v2H4v5h8v2H2V4h10Z" />
            </symbol>

            <symbol viewBox="0 0 24 24" id="trIcon">
                <text x="50%" y="60%" 
                    font-family="sans-serif" 
                    font-size="19"
                    font-weight="bold"
                    fill="currentColor"
                    text-anchor="middle" 
                    dominant-baseline="middle">
                    TR
                </text>
            </symbol>


            
            <symbol viewBox="0 0 24 24" id="caseIcon">
                <path fill="currentColor"
                    d="m3.975 17l3.75-10h1.8l3.75 10H11.55l-.9-2.55H6.6L5.7 17H3.975Zm3.15-4h3l-1.45-4.15h-.1L7.125 13Zm9.225 4.275q-1.225 0-1.925-.638t-.7-1.737q0-1.05.813-1.713t2.087-.662q.575 0 1.063.088t.837.287v-.35q0-.675-.462-1.075t-1.263-.4q-.525 0-.988.225t-.787.65l-1.075-.8q.475-.675 1.2-1.025t1.675-.35q1.55 0 2.375.738t.825 2.137v4.4H18.55v-.85h-.075q-.325.5-.875.788t-1.25.287Zm.25-1.25q.8 0 1.363-.563t.562-1.362q-.35-.2-.8-.3t-.825-.1q-.8 0-1.225.313t-.425.887q0 .5.375.813t.975.312Z" />
            </symbol>
        </svg>
    </div>
    <div id="loadMask">
        <div>
            <div>RadeMark</div>
            <div class="loadingCSSIcon">
                <div></div>
                <div></div>
                <div></div>
            </div>
        </div>
    </div>
    <div class="chat_window">
        <div class="overlay"></div>
        <nav class="nav">
            <div class="navHeader">
                <div id="newChat">
                    <svg width="24" height="24">
                        <use xlink:href="#addIcon" />
                    </svg>
                    <span data-i18n-key="newChat"></span>
                </div>
                <div id="newFolder" data-i18n-title="newFolder" title>
                    <svg width="24" height="24">
                        <use xlink:href="#newFolderIcon" />
                    </svg>
                </div>
            </div>
            <div class="extraChat">
                <input type="text" id="searchChat" autocomplete="off" readonly
                    onfocus="this.removeAttribute('readonly')" data-i18n-place="search" placeholder />
                <div id="clearSearch">
                    <svg width="24" height="24">
                        <use xlink:href="#closeIcon" />
                    </svg>
                </div>
                <div id="matchCaseSearch" data-i18n-title="matchCaseTip" title>
                    <svg width="24" height="24">
                        <use xlink:href="#caseIcon" />
                    </svg>
                </div>
            </div>
            <div class="allList">
                <div id="folderList"></div>
                <div id="chatList"></div>
            </div>
            <div class="navFooter">
                <div class="navFunc">
                    <div id="refreshPage" data-i18n-title="forceRe" title>
                        <svg width="24" height="24">
                            <use xlink:href="#forceRefreshIcon" />
                        </svg>
                    </div>
                    <div id="clearChat" data-i18n-title="clearAll" title>
                        <svg width="24" height="24">
                            <use xlink:href="#clearAllIcon" />
                        </svg>
                    </div>
                    <div id="toggleLight" data-i18n-theme title>
                        <svg width="24" height="24">
                            <use xlink:href="#lightThemeIcon" />
                        </svg>
                    </div>
                    <div id="sysSetting" data-i18n-title="setting" title>
                        <svg width="24" height="24">
                            <use xlink:href="#settingIcon" />
                        </svg>
                    </div>
                </div>
                <div class="divider"></div>
                <div class="links">
                    <a href="https://github.com/owwh" target="_blank" rel="noopener noreferrer">RadeMark</a>
                </div>
            </div>
        </nav>
        <div class="mainContent">
            <div class="top_menu">
                <div class="toggler" data-i18n-title="nav" title>
                    <div class="button close"></div>
                    <div class="button minimize"></div>
                    <div class="button maximize"></div>
                </div>
                <div class="title">
                    <div id="selector"><span id="modelName">ChatGPT</span><span id="modelVer">3.5</span><svg width="16"
                            height="16" style="transform: translateY(1px);">
                            <use xlink:href="#expandIcon" />
                        </svg></div>
                </div>
                <div class="settings">
                    <button class="setBtn" id="toggleFull" data-i18n-window title>
                        <svg width="30" height="30">
                            <use xlink:href="#expandFullIcon" />
                        </svg>
                    </button>
                    <button class="setBtn" id="setting">
                        <svg viewBox="0 0 100 100" width="30" height="30">
                            <title data-i18n-key="quickSet"></title>
                            <circle cx="50" cy="20" r="10" fill="#ffffff" />
                            <circle cx="50" cy="50" r="10" fill="#ffffff" />
                            <circle cx="50" cy="80" r="10" fill="#ffffff" />
                        </svg>
                    </button>
                </div>
                <div id="modelDialog" style="display:none;">
                    <div class="modelSingle" data-value="gpt-3.5-turbo" data-ver="3.5">
                        <div class="modelAvatar gptAvatar">
                            <svg width="24" height="24">
                                <use xlink:href="#aiIcon"></use>
                            </svg>
                        </div>
                        <div>GPT-3.5</div>
                    </div>
                    <div class="modelSingle" data-value="gpt-4" data-ver="4">
                        <div class="modelAvatar gptAvatar">
                            <svg width="24" height="24">
                                <use xlink:href="#aiIcon"></use>
                            </svg>
                        </div>
                        <div>GPT-4</div>
                    </div>
                    <div class="modelSingle" data-value="gpt-4-turbo" data-ver="4 Turbo">
                        <div class="modelAvatar gptAvatar">
                            <svg width="24" height="24">
                                <use xlink:href="#aiIcon"></use>
                            </svg>
                        </div>
                        <div>GPT-4 Turbo</div>
                    </div>
                    <div class="modelSingle" data-value="gpt-4o" data-ver="4o">
                        <div class="modelAvatar gptAvatar">
                            <svg width="24" height="24">
                                <use xlink:href="#aiIcon"></use>
                            </svg>
                        </div>
                        <div>GPT-4o</div>
                    </div>
                    <div class="modelSingle" data-value="claude-3.5-sonnet" data-ver="3.5 Sonnet">
                        <div class="modelAvatar">
                            <svg width="30" height="30">
                                <use xlink:href="#claudeIcon"></use>
                            </svg>
                        </div>
                        <div>Claude 3.5 Sonnet</div>
                    </div>
                    <div class="modelSingle" data-value="claude-3-haiku-20240307" data-ver="3 Haiku">
                        <div class="modelAvatar">
                            <svg width="30" height="30">
                                <use xlink:href="#claudeIcon"></use>
                            </svg>
                        </div>
                        <div>Claude 3 Haiku</div>
                    </div>
                    <div class="modelSingle" data-value="claude-3-opus-20240229" data-ver="3 Opus">
                        <div class="modelAvatar">
                            <svg width="30" height="30">
                                <use xlink:href="#claudeIcon"></use>
                            </svg>
                        </div>
                        <div>Claude 3 Opus</div>
                    </div>
                    <div class="modelSingle" data-value="gemini-1.0-pro" data-ver="1.0">
                        <div class="modelAvatar">
                            <svg width="30" height="30">
                                <use xlink:href="#geminiIcon"></use>
                            </svg>
                        </div>
                        <div>Gemini 1.0 Pro</div>
                    </div>
                    <div class="modelSingle" data-value="gemini-1.5-pro" data-ver="1.5 Pro">
                        <div class="modelAvatar">
                            <svg width="30" height="30">
                                <use xlink:href="#geminiIcon"></use>
                            </svg>
                        </div>
                        <div>Gemini 1.5 Pro</div>
                    </div>
                    <div class="modelSingle" data-value="gemini-1.5-flash" data-ver="1.5 Flash">
                        <div class="modelAvatar">
                            <svg width="30" height="30">
                                <use xlink:href="#geminiIcon"></use>
                            </svg>
                        </div>
                        <div>Gemini 1.5 Flash</div>
                    </div>
                </div>
                <div id="setDialog" style="display:none;">
                    <div class="setSwitch">
                        <div data-id="convOption" data-i18n-key="chat" class="activeSwitch"></div>
                        <div data-id="speechOption" data-i18n-key="tts"></div>
                        <div data-id="recOption" data-i18n-key="stt"></div>
                    </div>
                    <div id="convOption">
                        <div>
                            <div data-i18n-key="avatar"></div>
                            <div class="avatarDetail">
                                <img id="setAvatarPre" src="" />
                                <input class="inputTextClass" autocomplete="off" type="text" id="setAvatar" />
                            </div>
                        </div>
                        <div>
                            <div class="justSetLine presetSelect">
                                <div data-i18n-key="systemRole"></div>
                                <div>
                                    <label for="preSetSystem" data-i18n-key="presetRole"></label>
                                    <select id="preSetSystem">
                                        <option value="default" data-i18n-key="default"></option>
                                        <option value="normal" data-i18n-key="assistant"></option>
                                        <option value="cat" data-i18n-key="cat"></option>
                                        <option value="emoji" data-i18n-key="emoji"></option>
                                        <option value="image" data-i18n-key="withImg"></option>
                                    </select>
                                </div>
                            </div>
                            <textarea class="inputTextClass areaTextClass" autocomplete="off"
                                data-i18n-place="assistantText" placeholder id="systemInput"></textarea>
                        </div>
                        <div>
                            <span data-i18n-key="nature"></span>
                            <input type="range" id="top_p" min="0" max="1" value="1" step="0.05" />
                            <div class="selectDef">
                                <span data-i18n-key="natureNeg"></span>
                                <span data-i18n-key="naturePos"></span>
                            </div>
                        </div>
                        <div>
                            <span data-i18n-key="quality"></span>
                            <input type="range" id="temp" min="0" max="2" value="1" step="0.05" />
                            <div class="selectDef">
                                <span data-i18n-key="qualityNeg"></span>
                                <span data-i18n-key="qualityPos"></span>
                            </div>
                        </div>
                        <div>
                            <span data-i18n-key="chatsWidth"></span>
                            <input type="range" id="convWidth" min="30" max="100" value="100" step="1" />
                            <div class="selectDef">
                                <span>30%</span>
                                <span>100%</span>
                            </div>
                        </div>
                        <div>
                            <span data-i18n-key="typeSpeed"></span>
                            <input type="range" id="textSpeed" min="0" max="100" value="100" step="1" />
                            <div class="selectDef">
                                <span data-i18n-key="slow"></span>
                                <span data-i18n-key="fast"></span>
                            </div>
                        </div>
                        <div>
                            <span><span data-i18n-key="continuousLen"></span>: <span id="contLenWrap"></span><span
                                    data-i18n-key="msgAbbr"></span></span>
                            <input type="range" id="contLength" min="0" max="50" value="25" step="1" />
                            <div class="selectDef">
                                <span>0</span>
                                <span>50</span>
                            </div>
                        </div>
                        <div>
                            <span class="inlineTitle" data-i18n-key="longReply"></span>
                            <label class="switch-slide">
                                <input type="checkbox" id="enableLongReply" hidden />
                                <label for="enableLongReply" class="switch-slide-label"></label>
                            </label>
                        </div>
                    </div>
                    <div id="speechOption" style="display: none;">
                        <div class="presetSelect presetModelCls">
                            <label for="preSetService" data-i18n-key="ttsService"></label>
                            <select id="preSetService">
                                <option value="4" data-i18n-key="openaiTTS"></option>
                                <option value="3" data-i18n-key="azureTTS"></option>
                                <option selected value="2" data-i18n-key="edgeTTS"></option>
                                <option value="1" data-i18n-key="systemTTS"></option>
                            </select>
                        </div>
                        <div class="presetSelect presetModelCls">
                            <label for="preSetAzureRegion" data-i18n-key="azureRegion"></label>
                            <select id="preSetAzureRegion">
                            </select>
                        </div>
                        <div>
                            <div data-i18n-key="azureKey"></div>
                            <input class="inputTextClass" type="password" data-i18n-place="azureKey" id="azureKeyInput"
                                autocomplete="off" />
                        </div>
                        <div id="checkVoiceLoad" class="checkLoad" style="display: none;">
                            <svg>
                                <use xlink:href="#loadingIcon" />
                            </svg>
                            <span data-i18n-key="loadVoice"></span>
                        </div>
                        <div id="speechDetail">
                            <div>
                                <div class="justSetLine">
                                    <div data-i18n-key="voiceName" style="line-height: 28px;"></div>
                                    <div id="voiceTypes">
                                        <span data-type="0" data-i18n-key="userVoice"></span>
                                        <span data-type="1" class="selVoiceType" data-i18n-key="replyVoice"></span>
                                    </div>
                                </div>
                                <select id="preSetSpeech">
                                </select>
                            </div>
                            <div>
                                <div class="justSetLine">
                                    <input class="inputTextClass" id="testVoiceText" data-i18n-value="TTSTest" value />
                                </div>
                                <div class="justSetLine readyTestVoice" id="testVoiceBtn" style="margin-top: 6px;">
                                    <div class="justSetBtn" onclick="startTestVoice()">
                                        <svg width="18" height="18">
                                            <use xlink:href="#readyVoiceIcon" />
                                        </svg>
                                        <span data-i18n-key="play"></span>
                                    </div>
                                    <div class="justSetBtn" onclick="pauseTestVoice()">
                                        <svg width="18" height="18">
                                            <use xlink:href="#pauseVoiceIcon" />
                                        </svg>
                                        <span data-i18n-key="pause"></span>
                                    </div>
                                    <div class="justSetBtn" onclick="resumeTestVoice()">
                                        <svg width="18" height="18">
                                            <use xlink:href="#resumeVoiceIcon" />
                                        </svg>
                                        <span data-i18n-key="resume"></span>
                                    </div>
                                    <div class="justSetBtn" style="margin-right: 130px" onclick="stopTestVoice()">
                                        <svg width="18" height="18">
                                            <use xlink:href="#stopIcon" />
                                        </svg>
                                        <span data-i18n-key="stop"></span>
                                    </div>
                                </div>
                            </div>
                            <div class="justSetLine presetSelect" id="azureExtra" style="display:none;">
                                <div class="presetModelCls">
                                    <label for="preSetVoiceStyle" data-i18n-key="style"></label>
                                    <select id="preSetVoiceStyle">
                                    </select>
                                </div>
                                <div class="presetModelCls">
                                    <label for="preSetVoiceRole" data-i18n-key="role"></label>
                                    <select id="preSetVoiceRole">
                                    </select>
                                </div>
                            </div>
                            <div>
                                <span data-i18n-key="volume"></span>
                                <input type="range" id="voiceVolume" min="0.1" max="1.9" value="1" step="0.1" />
                                <div class="selectDef">
                                    <span data-i18n-key="low"></span>
                                    <span data-i18n-key="high"></span>
                                </div>
                            </div>
                            <div>
                                <span data-i18n-key="rate"></span>
                                <input type="range" id="voiceRate" min="0.1" max="1.9" value="1" step="0.1" />
                                <div class="selectDef">
                                    <span data-i18n-key="slow"></span>
                                    <span data-i18n-key="fast"></span>
                                </div>
                            </div>
                            <div>
                                <span data-i18n-key="pitch"></span>
                                <input type="range" id="voicePitch" min="0.1" max="1.9" value="1" step="0.1" />
                                <div class="selectDef">
                                    <span data-i18n-key="neutral"></span>
                                    <span data-i18n-key="intense"></span>
                                </div>
                            </div>
                            <div>
                                <span class="inlineTitle" data-i18n-key="contSpeech"></span>
                                <label class="switch-slide">
                                    <input type="checkbox" id="enableContVoice" checked="true" hidden />
                                    <label for="enableContVoice" class="switch-slide-label"></label>
                                </label>
                            </div>
                            <div>
                                <span class="inlineTitle" data-i18n-key="autoSpeech"></span>
                                <label class="switch-slide">
                                    <input type="checkbox" id="enableAutoVoice" hidden />
                                    <label for="enableAutoVoice" class="switch-slide-label"></label>
                                </label>
                            </div>
                        </div>
                    </div>
                    <div id="recOption" style="display: none;">
                        <div class="presetSelect presetModelCls">
                            <label for="preRecService" data-i18n-key="sttService"></label>
                            <select id="preRecService">
                                <option value="3" data-i18n-key="openaiTTS"></option>
                                <option value="2" data-i18n-key="azureTTS"></option>
                                <option value="1" data-i18n-key="systemTTS"></option>
                            </select>
                        </div>
                        <div>
                            <div class="presetSelect presetModelCls">
                                <label for="preRecAzureRegion" data-i18n-key="azureRegion"></label>
                                <select id="preRecAzureRegion">
                                </select>
                            </div>
                            <div data-i18n-key="azureKey"></div>
                            <input class="inputTextClass" type="password" data-i18n-place="azureKey"
                                id="azureRecKeyInput" autocomplete="off" />
                        </div>
                        <div id="checkRecLoad" class="checkLoad" style="display: none;">
                            <svg>
                                <use xlink:href="#loadingIcon" />
                            </svg>
                            <span data-i18n-key="loadRecVoice"></span>
                        </div>
                        <div id="noRecTip" style="display: none; margin-top: 15px" data-i18n-key="unsupportRecTip">
                        </div>
                        <div id="recDetail" style="display: none;">
                            <div class="presetSelect presetModelCls">
                                <label for="selectLangOption" data-i18n-key="lang"></label>
                                <select id="selectLangOption">
                                </select>
                            </div>
                            <div class="presetSelect presetModelCls">
                                <label for="selectDiaOption" data-i18n-key="dialect"></label>
                                <select id="selectDiaOption">
                                </select>
                            </div>
                            <div data-feat="forStream">
                                <div data-i18n-key="autoSendKey"></div>
                                <input class="inputTextClass" id="autoSendText" autocomplete="off"
                                    data-i18n-place="send" placeholder />
                            </div>
                            <div data-feat="forStream">
                                <div data-i18n-key="autoStopKey"></div>
                                <input class="inputTextClass" id="autoStopText" autocomplete="off"
                                    data-i18n-place="stop" placeholder />
                            </div>
                            <div data-feat="forStream">
                                <span data-i18n-key="autoSendDelay"></span>
                                <input type="range" id="autoSendTimeout" min="0" max="10" value="0" step="1" />
                                <div class="selectDef">
                                    <span>0<span data-i18n-key="second"></span></span>
                                    <span>10<span data-i18n-key="second"></span></span>
                                </div>
                            </div>
                            <div data-i18n-key="noStreamTip" data-feat="forNoStream"></div>
                            <div>
                                <span class="inlineTitle" data-i18n-key="keepListenMic"></span>
                                <label class="switch-slide">
                                    <input type="checkbox" id="keepListenMic" checked="false" hidden />
                                    <label for="keepListenMic" class="switch-slide-label"></label>
                                </label>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="messages">
                <div id="chatlog"></div>
                <div id="stopChat"><svg width="24" height="24">
                        <use xlink:href="#stopResIcon" />
                    </svg><span data-i18n-key="stop"></span></div>
            </div>
            <div class="bottom_wrapper clearfix">
                <div class="message_input_wrapper">
                    <textarea class="message_input_text" autocomplete="off" spellcheck="false" data-i18n-place="askTip"
                        placeholder id="chatinput"></textarea>
                    <div id="voiceRec" style="display:none;">
                        <div id="voiceRecIcon">
                            <svg viewBox="0 0 48 48" id="voiceInputIcon">
                                <g fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="4">
                                    <rect fill="none" width="14" height="27" x="17" y="4" rx="7" />
                                    <rect class="animVoice" x="18" y="4" width="12" height="27" stroke="none"
                                        fill="currentColor"></rect>
                                    <path stroke-linecap="round"
                                        d="M9 23c0 8.284 6.716 15 15 15c8.284 0 15-6.716 15-15M24 38v6" />
                                </g>
                            </svg>
                        </div>
                        <div id="voiceRecSetting">
                            <select id="select_language" style="margin-bottom: 4px;"></select>
                            <select id="select_dialect"></select>
                        </div>
                    </div>
                </div>
                <button class="loaded" id="sendbutton">
                    <span data-i18n-key="send"></span>
                    <svg style="margin:0 auto;height:40px;width:100%;">
                        <use xlink:href="#loadingIcon" />
                    </svg>
                </button>
                <button class="clearConv" data-i18n-title="clearChat" title>
                    <svg style="color: #e15b64;" width="29" height="29">
                        <use xlink:href="#closeIcon" />
                    </svg>
                    <svg width="21" height="21">
                        <use xlink:href="#deleteIcon" />
                    </svg>
                </button>
            </div>
        </div>
    </div>
    <div id="sysMask">
        <div id="sysDialog">
            <div id="closeSet">
                <svg width="24" height="24">
                    <use xlink:href="#closeIcon" />
                </svg>
            </div>
            <div class="sysTitle" data-i18n-key="setting"></div>
            <div class="sysContent">
                <div class="sysSwitch">
                    <div data-id="generalOption" class="activeSwitch">
                        <svg width="24" height="24">
                            <use xlink:href="#settingIcon" />
                        </svg><span data-i18n-key="general"></span>
                    </div>
                    <div data-id="hotkeyOption">
                        <svg width="24" height="24">
                            <use xlink:href="#hotkeyIcon" />
                        </svg><span data-i18n-key="hotkey"></span>
                    </div>
                    <div data-id="dataOption">
                        <svg width="24" height="24">
                            <use xlink:href="#databaseIcon" />
                        </svg><span data-i18n-key="data"></span>
                    </div>
                </div>
                <div class="sysDetail">
                    <div id="generalOption">
                        <div class="setContent">
                            <div class="setTitle" data-i18n-key="theme"></div>
                            <div class="setDetail themeDetail lightTheme" id="setLight">
                                <div data-i18n-title="darkTheme" title>
                                    <svg width="24" height="24">
                                        <use xlink:href="#darkThemeIcon"></use>
                                    </svg>
                                </div>
                                <div data-i18n-title="lightTheme" title>
                                    <svg width="24" height="24">
                                        <use xlink:href="#lightThemeIcon"></use>
                                    </svg>
                                </div>
                                <div data-i18n-title="autoWord" title>
                                    <svg width="24" height="24">
                                        <use xlink:href="#autoThemeIcon"></use>
                                    </svg>
                                </div>
                            </div>
                        </div>
                        <div class="setContent" id="autoDetail" style="display: none;font-size: 15px;">
                            <div class="setDetail">
                                <div class="autoSelect">
                                    <input type="radio" id="autoTheme1" name="autoLight" value="1" checked />
                                    <label for="autoTheme1" data-i18n-key="systemTheme"></label>
                                </div>
                                <div class="autoSelect" style="margin-top: 8px;">
                                    <input type="radio" id="autoTheme0" name="autoLight" value="0" />
                                    <label for="autoTheme0" data-i18n-key="customDarkTheme"></label>
                                </div>
                                <div id="customAutoSet" style="display: none; margin-top: 10px;">
                                    <div>
                                        <label for="customStart" data-i18n-key="startDark"></label>
                                        <input type="time" id="customStart" required>
                                    </div>
                                    <div style="margin-top: 10px;">
                                        <label for="customEnd" data-i18n-key="endDark"></label>
                                        <input type="time" id="customEnd" required>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="setContent">
                            <div class="setTitle" data-i18n-key="lang"></div>
                            <div class="setDetail themeDetail langDetail" id="setLang">
                                <div title="English">
                                    <svg width="24" height="24">
                                        <use xlink:href="#enIcon"></use>
                                    </svg>
                                </div>
                                
                                <div title="Turkish">
                                    <svg width="24" height="24">
                                        <use xlink:href="#trIcon"></use>
                                    </svg>
                                </div>

                                <div title="中文">
                                    <svg width="24" height="24">
                                        <use xlink:href="#zhIcon"></use>
                                    </svg>
                                </div>
                            </div>
                        </div>
                        <div class="modelSwitch">
                            <div data-id="gptOption" class="activeSwitch">ChatGPT</div>
                            <div data-id="geminiOption">Gemini</div>
                            <div data-id="claudeOption">Claude</div>
                        </div>
                        <div class="apiSelsContainer">
                            <div id="apiSelect" tabindex="-1" style="display: none;"></div>
                        </div>
                        <div id="gptOption">
                            <div class="setContent setNotNormalFlow">
                                <div class="setTitle"><span>ChatGPT</span><span data-i18n-key="aiEndpoint"></span></div>
                                <div class="setDetail inputDetail" style="position: relative;">
                                    <input class="inputTextClass" placeholder="https://api.openai.com/"
                                        autocomplete="off" id="apiHostInput" />
                                </div>
                            </div>
                            <div class="setContent">
                                <div class="setTitle"><span data-i18n-key="aiKey"></span></div>
                                <div class="setDetail inputDetail">
                                    <input class="inputTextClass" type="password" placeholder="sk-xxxxxx" id="keyInput"
                                        autocomplete="off" />
                                </div>
                            </div>
                            <div class="setContent">
                                <div class="setTitle" data-i18n-key="aiModel"></div>
                                <div class="setDetail inputDetail">
                                    <input class="inputTextClass" type="text" placeholder="gpt-x-xxx" id="modelInput"
                                        autocomplete="off" />
                                </div>
                            </div>
                        </div>
                        <div id="geminiOption" style="display: none;">
                            <div class="setContent setNotNormalFlow">
                                <div class="setTitle"><span>Gemini</span><span data-i18n-key="aiEndpoint"></span></div>
                                <div class="setDetail inputDetail" style="position: relative;">
                                    <input class="inputTextClass"
                                        placeholder="https://generativelanguage.googleapis.com/" autocomplete="off"
                                        id="geminiApiHostInput" />
                                </div>
                            </div>
                            <div class="setContent">
                                <div class="setTitle" data-i18n-key="aiKey"></div>
                                <div class="setDetail inputDetail">
                                    <input class="inputTextClass" type="password" placeholder="xxxx-xxxx"
                                        id="geminiKeyInput" autocomplete="off" />
                                </div>
                            </div>
                            <div class="setContent">
                                <div class="setTitle" data-i18n-key="aiModel"></div>
                                <div class="setDetail inputDetail">
                                    <input class="inputTextClass" type="text" placeholder="gemini-xxx-xxx"
                                        id="geminiModelInput" autocomplete="off" />
                                </div>
                            </div>
                        </div>
                        <div id="claudeOption" style="display: none;">
                            <div class="setContent setNotNormalFlow">
                                <div class="setTitle"><span>Claude</span><span data-i18n-key="aiEndpoint"></span></div>
                                <div class="setDetail inputDetail" style="position: relative;">
                                    <input class="inputTextClass" placeholder="https://api.anthropic.com/"
                                        autocomplete="off" id="claudeApiHostInput" />
                                </div>
                            </div>
                            <div class="setContent">
                                <div class="setTitle" data-i18n-key="aiKey"></div>
                                <div class="setDetail inputDetail">
                                    <input class="inputTextClass" type="password" placeholder="sk-xxxxxx"
                                        id="claudeKeyInput" autocomplete="off" />
                                </div>
                            </div>
                            <div class="setContent">
                                <div class="setTitle" data-i18n-key="aiModel"></div>
                                <div class="setDetail inputDetail">
                                    <input class="inputTextClass" type="text" placeholder="claude-x-xxx-xxxx"
                                        id="claudeModelInput" autocomplete="off" />
                                </div>
                            </div>
                        </div>
                    </div>
                    <div id="hotkeyOption" style="display: none;">
                        <div class="setContent">
                            <div class="setTitle">UI</div>
                            <div class="setDetail hotKeyDetail">
                                <div>
                                    <label for="hotKeyNav" data-i18n-key="navKey"></label>
                                    <select id="hotKeyNav">
                                    </select>
                                </div>
                                <div>
                                    <label for="hotKeyWindow" data-i18n-key="fullKey"></label>
                                    <select id="hotKeyWindow">
                                    </select>
                                </div>
                                <div>
                                    <label for="hotKeyTheme" data-i18n-key="themeKey"></label>
                                    <select id="hotKeyTheme">
                                    </select>
                                </div>
                                <div>
                                    <label for="hotKeyLang" data-i18n-key="langKey"></label>
                                    <select id="hotKeyLang">
                                    </select>
                                </div>
                            </div>
                            <div class="setTitle" data-i18n-key="chat"></div>
                            <div class="setDetail hotKeyDetail">
                                <div>
                                    <label for="hotKeySearch" data-i18n-key="search"></label>
                                    <select id="hotKeySearch">
                                    </select>
                                </div>
                                <div>
                                    <label for="hotKeyInput" data-i18n-key="inputKey"></label>
                                    <select id="hotKeyInput">
                                    </select>
                                </div>
                                <div>
                                    <label for="hotKeyNewChat" data-i18n-key="newChat"></label>
                                    <select id="hotKeyNewChat">
                                    </select>
                                </div>
                                <div>
                                    <label for="hotKeyClearChat" data-i18n-key="clearChat"></label>
                                    <select id="hotKeyClearChat">
                                    </select>
                                </div>
                            </div>
                            <div class="setTitle" data-i18n-key="voiceKey"></div>
                            <div class="setDetail hotKeyDetail">
                                <div style="display: none;">
                                    <label for="hotKeyVoiceRec" data-i18n-key="recKey"></label>
                                    <select id="hotKeyVoiceRec">
                                    </select>
                                </div>
                                <div>
                                    <label for="hotKeyVoiceSpeak" data-i18n-key="speechKey"></label>
                                    <select id="hotKeyVoiceSpeak">
                                    </select>
                                </div>
                            </div>
                            <div class="setDetail keyOptionDetail">
                                <div id="resetHotKey">
                                    <svg width="24" height="24" style="transform: scaleX(-1)">
                                        <use xlink:href="#refreshIcon" />
                                    </svg>
                                    <span data-i18n-key="resetTip"></span>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div id="dataOption" style="display: none;">
                        <div class="setContent">
                            <div class="setTitle" data-i18n-key="chat"></div>
                            <div class="setDetail dataDetail">
                                <div id="exportChat">
                                    <svg width="24" height="24">
                                        <use xlink:href="#exportIcon" />
                                    </svg>
                                    <span data-i18n-key="export"></span>
                                </div>
                                <label id="importChat" for="importChatInput">
                                    <svg width="24" height="24">
                                        <use xlink:href="#importIcon" />
                                    </svg>
                                    <span data-i18n-key="import"></span>
                                </label>
                                <input type="file" style="display: none;" id="importChatInput"
                                    accept="application/json" />
                                <div id="clearChatSet">
                                    <svg width="24" height="24">
                                        <use xlink:href="#clearAllIcon" />
                                    </svg>
                                    <span data-i18n-key="clear"></span>
                                </div>
                            </div>
                        </div>
                        <div class="setContent">
                            <div class="setTitle" data-i18n-key="setting"></div>
                            <div class="setDetail dataDetail">
                                <div id="exportSet">
                                    <svg width="24" height="24">
                                        <use xlink:href="#exportSetIcon" />
                                    </svg>
                                    <span data-i18n-key="export"></span>
                                </div>
                                <label id="importSet" for="importSetInput">
                                    <svg width="24" height="24">
                                        <use xlink:href="#importSetIcon" />
                                    </svg>
                                    <span data-i18n-key="import"></span>
                                </label>
                                <input type="file" style="display: none;" id="importSetInput"
                                    accept="application/json" />
                                <div id="resetSet">
                                    <svg width="24" height="24" style="transform: scaleX(-1)">
                                        <use xlink:href="#refreshIcon" />
                                    </svg>
                                    <span data-i18n-key="reset"></span>
                                </div>
                            </div>
                        </div>
                        <div class="setContent">
                            <div class="setTitle" data-i18n-key="localStore"></div>
                            <div class="setDetail">
                                <div class="progressBar">
                                    <div class="nowProgress" id="usedStorageBar"></div>
                                </div>
                                <div class="progressDetail">
                                    <div><span data-i18n-key="used"></span><span id="usedStorage"></span></div>
                                    <div><span data-i18n-key="available"></span><span id="availableStorage"></span>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <link crossorigin="anonymous"
        href="https://fastly.jsdelivr.net/npm/github-markdown-css@5.5.1/github-markdown-light.min.css" rel="stylesheet">
    <link crossorigin="anonymous"
        href="https://fastly.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/github.min.css"
        rel="stylesheet">
    <link crossorigin="anonymous" href="https://fastly.jsdelivr.net/npm/notyf@3.10.0/notyf.min.css" rel="stylesheet">
    <script crossorigin="anonymous" src="https://fastly.jsdelivr.net/npm/notyf@3.10.0/notyf.min.js"></script>
    <script>
        const notyf = new Notyf({
            position: { x: "center", y: "top" },
            types: [
                {
                    type: "success",
                    background: "#99c959",
                    duration: 2000,
                },
                {
                    type: "warning",
                    background: "#f8b26a",
                    duration: 3000
                },
                {
                    type: "error",
                    background: "#e15b64",
                    duration: 3000,
                }
            ]
        });
        const registerSW = () => {
            if ("serviceWorker" in navigator) {
                navigator.serviceWorker.register("sw.js" + location.search).then(reg => console.log("Service worker register succeeded"),
                    error => console.error(`Service worker register failed: ${error}`))
            }
        };
        window.addEventListener("load", () => registerSW());
        const isMobile = navigator.userAgent.match(/iPhone|iPad|iPod|Android|BlackBerry|webOS/);
        if (isMobile) {
            const script = document.createElement("script");
            script.src = "https://fastly.jsdelivr.net/gh/timruffles/mobile-drag-drop@3.0.0-rc.0/release/index.min.js";
            script.crossOrigin = "anonymous";
            script.defer = true;
            script.onload = () => {
                MobileDragDrop.polyfill();
            }
            document.body.appendChild(script);
            const link = document.createElement("link");
            link.crossOrigin = "anonymous";
            link.rel = "stylesheet";
            link.href = "https://fastly.jsdelivr.net/gh/timruffles/mobile-drag-drop@3.0.0-rc.0/release/default.css";
            document.body.appendChild(link);
        }
        let envAPIEndpoint, envAPIKey, envAPIModel, envGeminiAPIEndpoint, envGeminiAPIKey, envGeminiAPIModel, envClaudeAPIEndpoint, envClaudeAPIKey, envClaudeAPIModel;
    </script>
    <script src="env.js"></script>
    <script>
        // from fflate@0.8.2
        { const t = Uint8Array, e = Uint16Array, n = Int32Array, r = new t([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0]), o = new t([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0]), l = new t([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]), s = (t, r) => { const o = new e(31); for (let e = 0; e < 31; ++e)o[e] = r += 1 << t[e - 1]; const l = new n(o[30]); for (let t = 1; t < 30; ++t)for (let e = o[t]; e < o[t + 1]; ++e)l[e] = e - o[t] << 5 | t; return { b: o, r: l } }, { b: f, r: c } = s(r, 2); f[28] = 258, c[258] = 28; const { b: i, r: a } = s(o, 0), h = new e(32768); for (let t = 0; t < 32768; ++t) { let e = (43690 & t) >> 1 | (21845 & t) << 1; e = (52428 & e) >> 2 | (13107 & e) << 2, e = (61680 & e) >> 4 | (3855 & e) << 4, h[t] = ((65280 & e) >> 8 | (255 & e) << 8) >> 1 } const u = (t, n, r) => { const o = t.length; let l = 0; const s = new e(n); for (; l < o; ++l)t[l] && ++s[t[l] - 1]; const f = new e(n); for (l = 1; l < n; ++l)f[l] = f[l - 1] + s[l - 1] << 1; let c; if (r) { c = new e(1 << n); const r = 15 - n; for (l = 0; l < o; ++l)if (t[l]) { const e = l << 4 | t[l], o = n - t[l]; let s = f[t[l] - 1]++ << o; for (const t = s | (1 << o) - 1; s <= t; ++s)c[h[s] >> r] = e } } else for (c = new e(o), l = 0; l < o; ++l)t[l] && (c[l] = h[f[t[l] - 1]++] >> 15 - t[l]); return c }, w = new t(288); for (let t = 0; t < 144; ++t)w[t] = 8; for (let t = 144; t < 256; ++t)w[t] = 9; for (let t = 256; t < 280; ++t)w[t] = 7; for (let t = 280; t < 288; ++t)w[t] = 8; const g = new t(32); for (let t = 0; t < 32; ++t)g[t] = 5; const b = u(w, 9, 0), d = u(w, 9, 1), m = u(g, 5, 0), y = u(g, 5, 1), M = t => { let e = t[0]; for (let n = 1; n < t.length; ++n)t[n] > e && (e = t[n]); return e }, p = (t, e, n) => { const r = e / 8 | 0; return (t[r] | t[r + 1] << 8) >> (7 & e) & n }, k = (t, e) => { const n = e / 8 | 0; return (t[n] | t[n + 1] << 8 | t[n + 2] << 16) >> (7 & e) }, v = t => (t + 7) / 8 | 0, x = (e, n, r) => ((null == n || n < 0) && (n = 0), (null == r || r > e.length) && (r = e.length), new t(e.subarray(n, r))), E = ["unexpected EOF", "invalid block type", "invalid length/literal", "invalid distance", "stream finished", "no stream handler", , "no callback", "invalid UTF-8 data", "extra field too long", "date not in range 1980-2099", "filename too long", "stream finishing", "invalid zip data"], A = (t, e, n) => { const r = new Error(e || E[t]); if (r.code = t, Error.captureStackTrace && Error.captureStackTrace(r, A), !n) throw r; return r }, T = (e, n, s, c) => { const a = e.length, h = c ? c.length : 0; if (!a || n.f && !n.l) return s || new t(0); const w = !s, g = w || 2 != n.i, b = n.i; w && (s = new t(3 * a)); const m = e => { let n = s.length; if (e > n) { const r = new t(Math.max(2 * n, e)); r.set(s), s = r } }; let E = n.f || 0, T = n.p || 0, U = n.b || 0, z = n.l, F = n.d, S = n.m, I = n.n; const O = 8 * a; do { if (!z) { E = p(e, T, 1); const r = p(e, T + 1, 3); if (T += 3, !r) { const t = v(T) + 4, r = e[t - 4] | e[t - 3] << 8, o = t + r; if (o > a) { b && A(0); break } g && m(U + r), s.set(e.subarray(t, o), U), n.b = U += r, n.p = T = 8 * o, n.f = E; continue } if (1 == r) z = d, F = y, S = 9, I = 5; else if (2 == r) { const n = p(e, T, 31) + 257, r = p(e, T + 10, 15) + 4, o = n + p(e, T + 5, 31) + 1; T += 14; const s = new t(o), f = new t(19); for (let t = 0; t < r; ++t)f[l[t]] = p(e, T + 3 * t, 7); T += 3 * r; const c = M(f), i = (1 << c) - 1, a = u(f, c, 1); for (let t = 0; t < o;) { const n = a[p(e, T, i)]; T += 15 & n; const r = n >> 4; if (r < 16) s[t++] = r; else { let n = 0, o = 0; for (16 == r ? (o = 3 + p(e, T, 3), T += 2, n = s[t - 1]) : 17 == r ? (o = 3 + p(e, T, 7), T += 3) : 18 == r && (o = 11 + p(e, T, 127), T += 7); o--;)s[t++] = n } } const h = s.subarray(0, n), w = s.subarray(n); S = M(h), I = M(w), z = u(h, S, 1), F = u(w, I, 1) } else A(1); if (T > O) { b && A(0); break } } g && m(U + 131072); const w = (1 << S) - 1, x = (1 << I) - 1; let j = T; for (; ; j = T) { const t = z[k(e, T) & w], n = t >> 4; if (T += 15 & t, T > O) { b && A(0); break } if (t || A(2), n < 256) s[U++] = n; else { if (256 == n) { j = T, z = null; break } { let t = n - 254; if (n > 264) { const o = n - 257, l = r[o]; t = p(e, T, (1 << l) - 1) + f[o], T += l } const l = F[k(e, T) & x], a = l >> 4; l || A(3), T += 15 & l; let u = i[a]; if (a > 3) { const t = o[a]; u += k(e, T) & (1 << t) - 1, T += t } if (T > O) { b && A(0); break } g && m(U + 131072); const w = U + t; if (U < u) { const t = h - u, e = Math.min(u, w); for (t + U < 0 && A(3); U < e; ++U)s[U] = c[t + U] } for (; U < w; ++U)s[U] = s[U - u] } } } n.l = z, n.p = j, n.b = U, n.f = E, z && (E = 1, n.m = S, n.d = F, n.n = I) } while (!E); return U != s.length && w ? x(s, 0, U) : s.subarray(0, U) }, U = (t, e, n) => { n <<= 7 & e; const r = e / 8 | 0; t[r] |= n, t[r + 1] |= n >> 8 }, z = (t, e, n) => { n <<= 7 & e; const r = e / 8 | 0; t[r] |= n, t[r + 1] |= n >> 8, t[r + 2] |= n >> 16 }, F = (n, r) => { const o = []; for (let t = 0; t < n.length; ++t)n[t] && o.push({ s: t, f: n[t] }); const l = o.length, s = o.slice(); if (!l) return { t: C, l: 0 }; if (1 == l) { const e = new t(o[0].s + 1); return e[o[0].s] = 1, { t: e, l: 1 } } o.sort(((t, e) => t.f - e.f)), o.push({ s: -1, f: 25001 }); let f = o[0], c = o[1], i = 0, a = 1, h = 2; for (o[0] = { s: -1, f: f.f + c.f, l: f, r: c }; a != l - 1;)f = o[o[i].f < o[h].f ? i++ : h++], c = o[i != a && o[i].f < o[h].f ? i++ : h++], o[a++] = { s: -1, f: f.f + c.f, l: f, r: c }; let u = s[0].s; for (let t = 1; t < l; ++t)s[t].s > u && (u = s[t].s); const w = new e(u + 1); let g = S(o[a - 1], w, 0); if (g > r) { let t = 0, e = 0; const n = g - r, o = 1 << n; for (s.sort(((t, e) => w[e.s] - w[t.s] || t.f - e.f)); t < l; ++t) { const n = s[t].s; if (!(w[n] > r)) break; e += o - (1 << g - w[n]), w[n] = r } for (e >>= n; e > 0;) { const n = s[t].s; w[n] < r ? e -= 1 << r - w[n]++ - 1 : ++t } for (; t >= 0 && e; --t) { const n = s[t].s; w[n] == r && (--w[n], ++e) } g = r } return { t: new t(w), l: g } }, S = (t, e, n) => -1 == t.s ? Math.max(S(t.l, e, n + 1), S(t.r, e, n + 1)) : e[t.s] = n, I = t => { let n = t.length; for (; n && !t[--n];); const r = new e(++n); let o = 0, l = t[0], s = 1; const f = t => { r[o++] = t }; for (let e = 1; e <= n; ++e)if (t[e] == l && e != n) ++s; else { if (!l && s > 2) { for (; s > 138; s -= 138)f(32754); s > 2 && (f(s > 10 ? s - 11 << 5 | 28690 : s - 3 << 5 | 12305), s = 0) } else if (s > 3) { for (f(l), --s; s > 6; s -= 6)f(8304); s > 2 && (f(s - 3 << 5 | 8208), s = 0) } for (; s--;)f(l); s = 1, l = t[e] } return { c: r.subarray(0, o), n: n } }, O = (t, e) => { let n = 0; for (let r = 0; r < e.length; ++r)n += t[r] * e[r]; return n }, j = (t, e, n) => { const r = n.length, o = v(e + 2); t[o] = 255 & r, t[o + 1] = r >> 8, t[o + 2] = 255 ^ t[o], t[o + 3] = 255 ^ t[o + 1]; for (let e = 0; e < r; ++e)t[o + e + 4] = n[e]; return 8 * (o + 4 + r) }, q = (t, n, s, f, c, i, a, h, d, y, M) => { U(n, M++, s), ++c[256]; const { t: p, l: k } = F(c, 15), { t: v, l: x } = F(i, 15), { c: E, n: A } = I(p), { c: T, n: S } = I(v), q = new e(19); for (let t = 0; t < E.length; ++t)++q[31 & E[t]]; for (let t = 0; t < T.length; ++t)++q[31 & T[t]]; const { t: B, l: C } = F(q, 7); let D = 19; for (; D > 4 && !B[l[D - 1]]; --D); const G = y + 5 << 3, H = O(c, w) + O(i, g) + a, J = O(c, p) + O(i, v) + a + 14 + 3 * D + O(q, B) + 2 * q[16] + 3 * q[17] + 7 * q[18]; if (d >= 0 && G <= H && G <= J) return j(n, M, t.subarray(d, d + y)); let K, L, N, P; if (U(n, M, 1 + (J < H)), M += 2, J < H) { K = u(p, k, 0), L = p, N = u(v, x, 0), P = v; const t = u(B, C, 0); U(n, M, A - 257), U(n, M + 5, S - 1), U(n, M + 10, D - 4), M += 14; for (let t = 0; t < D; ++t)U(n, M + 3 * t, B[l[t]]); M += 3 * D; const e = [E, T]; for (let r = 0; r < 2; ++r) { const o = e[r]; for (let e = 0; e < o.length; ++e) { const r = 31 & o[e]; U(n, M, t[r]), M += B[r], r > 15 && (U(n, M, o[e] >> 5 & 127), M += o[e] >> 12) } } } else K = b, L = w, N = m, P = g; for (let t = 0; t < h; ++t) { const e = f[t]; if (e > 255) { const t = e >> 18 & 31; z(n, M, K[t + 257]), M += L[t + 257], t > 7 && (U(n, M, e >> 23 & 31), M += r[t]); const l = 31 & e; z(n, M, N[l]), M += P[l], l > 3 && (z(n, M, e >> 5 & 8191), M += o[l]) } else z(n, M, K[e]), M += L[e] } return z(n, M, K[256]), M + L[256] }, B = new n([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]), C = new t(0), D = (l, s, f, i, h, u) => { const w = u.z || l.length, g = new t(i + w + 5 * (1 + Math.ceil(w / 7e3)) + h), b = g.subarray(i, g.length - h), d = u.l; let m = 7 & (u.r || 0); if (s) { m && (b[0] = u.r >> 3); const t = B[s - 1], i = t >> 13, h = 8191 & t, g = (1 << f) - 1, y = u.p || new e(32768), M = u.h || new e(g + 1), p = Math.ceil(f / 3), k = 2 * p, v = t => (l[t] ^ l[t + 1] << p ^ l[t + 2] << k) & g, x = new n(25e3), E = new e(288), A = new e(32); let T = 0, U = 0, z = u.i || 0, F = 0, S = u.w || 0, I = 0; for (; z + 2 < w; ++z) { const t = v(z); let e = 32767 & z, n = M[t]; if (y[e] = n, M[t] = e, S <= z) { const s = w - z; if ((T > 7e3 || F > 24576) && (s > 423 || !d)) { m = q(l, b, 0, x, E, A, U, F, I, z - I, m), F = T = U = 0, I = z; for (let t = 0; t < 286; ++t)E[t] = 0; for (let t = 0; t < 30; ++t)A[t] = 0 } let f = 2, u = 0, g = h, M = e - n & 32767; if (s > 2 && t == v(z - M)) { const t = Math.min(i, s) - 1, r = Math.min(32767, z), o = Math.min(258, s); for (; M <= r && --g && e != n;) { if (l[z + f] == l[z + f - M]) { let e = 0; for (; e < o && l[z + e] == l[z + e - M]; ++e); if (e > f) { if (f = e, u = M, e > t) break; const r = Math.min(M, e - 2); let o = 0; for (let t = 0; t < r; ++t) { const e = z - M + t & 32767, r = e - y[e] & 32767; r > o && (o = r, n = e) } } } e = n, n = y[e], M += e - n & 32767 } } if (u) { x[F++] = 268435456 | c[f] << 18 | a[u]; const t = 31 & c[f], e = 31 & a[u]; U += r[t] + o[e], ++E[257 + t], ++A[e], S = z + f, ++T } else x[F++] = l[z], ++E[l[z]] } } for (z = Math.max(z, S); z < w; ++z)x[F++] = l[z], ++E[l[z]]; m = q(l, b, d, x, E, A, U, F, I, z - I, m), d || (u.r = 7 & m | b[m / 8 | 0] << 3, m -= 7, u.h = M, u.p = y, u.i = z, u.w = S) } else { for (let t = u.w || 0; t < w + d; t += 65535) { let e = t + 65535; e >= w && (b[m / 8 | 0] = d, e = w), m = j(b, m + 1, l.subarray(t, e)) } u.i = w } return x(g, 0, i + v(m) + h) }, G = (e, n, r, o, l) => { if (!l && (l = { l: 1 }, n.dictionary)) { const r = n.dictionary.subarray(-32768), o = new t(r.length + e.length); o.set(r), o.set(e, r.length), e = o, l.w = r.length } return D(e, null == n.level ? 6 : n.level, null == n.mem ? l.l ? Math.ceil(1.5 * Math.max(8, Math.min(13, Math.log(e.length)))) : 20 : 12 + n.mem, r, o, l) }; function deflateSync(t, e) { return G(t, e || {}, 0, 0) } function inflateSync(t, e) { return T(t, { i: 2 }, e && e.out, e && e.dictionary) } };
        // from markdown-it-texmath@1.0.1
        function escapeHTML(e) { return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;").replace(/\//g, "&sol;") } function texmath(e, t) { const n = texmath.mergeDelimiters(t && t.delimiters), a = t && t.outerSpace || !1, o = t && t.katexOptions || {}; o.throwOnError = o.throwOnError || !1, o.macros = o.macros || t && t.macros, texmath.katex || (t && "object" == typeof t.engine ? texmath.katex = t.engine : "object" == typeof module ? texmath.katex = require("katex") : texmath.katex = { renderToString: () => "No math renderer found." }); for (const t of n.inline) a && "outerSpace" in t && (t.outerSpace = !0), e.inline.ruler.before("escape", t.name, texmath.inline(t)), e.renderer.rules[t.name] = (e, n) => t.tmpl.replace(/\$1/, texmath.render(e[n].content, !!t.displayMode, o)); for (const t of n.block) e.block.ruler.before("fence", t.name, texmath.block(t)), e.renderer.rules[t.name] = (e, n) => t.tmpl.replace(/\$2/, escapeHTML(e[n].info)).replace(/\$1/, texmath.render(e[n].content, !0, o)) } texmath.mergeDelimiters = function (e) { const t = Array.isArray(e) ? e : "string" == typeof e ? [e] : ["dollars"], n = { inline: [], block: [] }; for (const e of t) e in texmath.rules && (n.inline.push(...texmath.rules[e].inline), n.block.push(...texmath.rules[e].block)); return n }, texmath.inline = e => function (t, n) { const a = t.pos, o = t.src, r = o.startsWith(e.tag, e.rex.lastIndex = a) && (!e.pre || e.pre(o, e.outerSpace, a)) && e.rex.exec(o), s = !!r && a < e.rex.lastIndex && (!e.post || e.post(o, e.outerSpace, e.rex.lastIndex - 1)); if (s) { if (!n) { const n = t.push(e.name, "math", 0); n.content = r[1], n.markup = e.tag } t.pos = e.rex.lastIndex } return s }, texmath.block = e => function (t, n, a, o) { const r = t.bMarks[n] + t.tShift[n], s = t.src, m = s.startsWith(e.tag, e.rex.lastIndex = r) && (!e.pre || e.pre(s, !1, r)) && e.rex.exec(s), l = !!m && r < e.rex.lastIndex && (!e.post || e.post(s, !1, e.rex.lastIndex - 1)); if (l && !o) { const o = e.rex.lastIndex - 1; let r; for (r = n; r < a && !(o >= t.bMarks[r] + t.tShift[r] && o <= t.eMarks[r]); r++); const s = t.lineMax, l = t.parentType; t.lineMax = r, t.parentType = "math", "blockquote" === l && (m[1] = m[1].replace(/(\n*?^(?:\s*>)+)/gm, "")); let c = t.push(e.name, "math", 0); c.block = !0, c.tag = e.tag, c.markup = "", c.content = m[1], c.info = m[m.length - 1], c.map = [n, r + 1], t.parentType = l, t.lineMax = s, t.line = r + 1 } return l }, texmath.render = function (e, t, n) { let a; n.displayMode = t; try { a = texmath.katex.renderToString(e, n) } catch (t) { a = escapeHTML(`${e}:${t.message}`) } return a }, texmath.inlineRuleNames = ["math_inline", "math_inline_double"], texmath.blockRuleNames = ["math_block", "math_block_eqno"], texmath.$_pre = (e, t, n) => { const a = n > 0 && e[n - 1].charCodeAt(0); return t ? !a || 32 === a : !a || 92 !== a && (a < 48 || a > 57) }, texmath.$_post = (e, t, n) => { const a = e[n + 1] && e[n + 1].charCodeAt(0); return t ? !a || 32 === a || 46 === a || 44 === a || 59 === a : !a || a < 48 || a > 57 }, texmath.rules = { brackets: { inline: [{ name: "math_inline", rex: /\\\((.+?)\\\)/gy, tmpl: "<eq>$1</eq>", tag: "\\(" }], block: [{ name: "math_block_eqno", rex: /\\\[(((?!\\\]|\\\[)[\s\S])+?)\\\]\s*?\(([^)$\r\n]+?)\)/gmy, tmpl: '<section class="eqno"><eqn>$1</eqn><span>($2)</span></section>', tag: "\\[" }, { name: "math_block", rex: /\\\[([\s\S]+?)\\\]/gmy, tmpl: "<section><eqn>$1</eqn></section>", tag: "\\[" }] }, doxygen: { inline: [{ name: "math_inline", rex: /\\f\$(.+?)\\f\$/gy, tmpl: "<eq>$1</eq>", tag: "\\f$" }], block: [{ name: "math_block_eqno", rex: /\\f\[([^]+?)\\f\]\s*?\(([^)\s]+?)\)/gmy, tmpl: '<section class="eqno"><eqn>$1</eqn><span>($2)</span></section>', tag: "\\f[" }, { name: "math_block", rex: /\\f\[([^]+?)\\f\]/gmy, tmpl: "<section><eqn>$1</eqn></section>", tag: "\\f[" }] }, gitlab: { inline: [{ name: "math_inline", rex: /\$`(.+?)`\$/gy, tmpl: "<eq>$1</eq>", tag: "$`" }], block: [{ name: "math_block_eqno", rex: /`{3}math\s*([^`]+?)\s*?`{3}\s*\(([^)\r\n]+?)\)/gm, tmpl: '<section class="eqno"><eqn>$1</eqn><span>($2)</span></section>', tag: "```math" }, { name: "math_block", rex: /`{3}math\s*([^`]*?)\s*`{3}/gm, tmpl: "<section><eqn>$1</eqn></section>", tag: "```math" }] }, julia: { inline: [{ name: "math_inline", rex: /`{2}([^`]+?)`{2}/gy, tmpl: "<eq>$1</eq>", tag: "``" }, { name: "math_inline", rex: /\$((?:\S?)|(?:\S.*?\S))\$/gy, tmpl: "<eq>$1</eq>", tag: "$", spaceEnclosed: !1, pre: texmath.$_pre, post: texmath.$_post }], block: [{ name: "math_block_eqno", rex: /`{3}math\s+?([^`]+?)\s+?`{3}\s*?\(([^)$\r\n]+?)\)/gmy, tmpl: '<section class="eqno"><eqn>$1</eqn><span>($2)</span></section>', tag: "```math" }, { name: "math_block", rex: /`{3}math\s+?([^`]+?)\s+?`{3}/gmy, tmpl: "<section><eqn>$1</eqn></section>", tag: "```math" }] }, kramdown: { inline: [{ name: "math_inline", rex: /\${2}(.+?)\${2}/gy, tmpl: "<eq>$1</eq>", tag: "$$" }], block: [{ name: "math_block_eqno", rex: /\${2}([^$]+?)\${2}\s*?\(([^)\s]+?)\)/gmy, tmpl: '<section class="eqno"><eqn>$1</eqn><span>($2)</span></section>', tag: "$$" }, { name: "math_block", rex: /\${2}([^$]+?)\${2}/gmy, tmpl: "<section><eqn>$1</eqn></section>", tag: "$$" }] }, beg_end: { inline: [], block: [{ name: "math_block", rex: /(\\(?:begin)\{([a-z]+)\}[\s\S]+?\\(?:end)\{\2\})/gmy, tmpl: "<section><eqn>$1</eqn></section>", tag: "\\" }] }, dollars: { inline: [{ name: "math_inline_double", rex: /\${2}([^$]*?[^\\])\${2}/gy, tmpl: "<section><eqn>$1</eqn></section>", tag: "$$", displayMode: !0, pre: texmath.$_pre, post: texmath.$_post }, { name: "math_inline", rex: /\$((?:[^\s\\])|(?:\S.*?[^\s\\]))\$/gy, tmpl: "<eq>$1</eq>", tag: "$", outerSpace: !1, pre: texmath.$_pre, post: texmath.$_post }], block: [{ name: "math_block_eqno", rex: /\${2}([^$]*?[^\\])\${2}\s*?\(([^)\s]+?)\)/gmy, tmpl: '<section class="eqno"><eqn>$1</eqn><span>($2)</span></section>', tag: "$$" }, { name: "math_block", rex: /\${2}([^$]*?[^\\])\${2}/gmy, tmpl: "<section><eqn>$1</eqn></section>", tag: "$$" }] } };
        // from morphdom@2.7.2
        { let e, t = 11, l = (e, l) => { let n, i, r, d, o, a = l.attributes; if (l.nodeType === t || e.nodeType === t) return; for (let t = a.length - 1; t >= 0; t--)n = a[t], i = n.name, r = n.namespaceURI, d = n.value, r ? (i = n.localName || i, o = e.getAttributeNS(r, i), o !== d && ("xmlns" === n.prefix && (i = n.name), e.setAttributeNS(r, i, d))) : (o = e.getAttribute(i), o !== d && e.setAttribute(i, d)); let u = e.attributes; for (let t = u.length - 1; t >= 0; t--)n = u[t], i = n.name, r = n.namespaceURI, r ? (i = n.localName || i, l.hasAttributeNS(r, i) || e.removeAttributeNS(r, i)) : l.hasAttribute(i) || e.removeAttribute(i) }, n = "http://www.w3.org/1999/xhtml", i = "undefined" == typeof document ? void 0 : document, r = !!i && "content" in i.createElement("template"), d = !!i && i.createRange && "createContextualFragment" in i.createRange(), o = e => { let t = i.createElement("template"); return t.innerHTML = e, t.content.childNodes[0] }, a = t => (e || (e = i.createRange(), e.selectNode(i.body)), e.createContextualFragment(t).childNodes[0]), u = e => { let t = i.createElement("body"); return t.innerHTML = e, t.childNodes[0] }, s = e => (e = e.trim(), r ? o(e) : d ? a(e) : u(e)), f = (e, t) => { let l, n, i = e.nodeName, r = t.nodeName; return i === r || (l = i.charCodeAt(0), n = r.charCodeAt(0), l <= 90 && n >= 97 ? i === r.toUpperCase() : n <= 90 && l >= 97 && r === i.toUpperCase()) }, c = (e, t) => t && t !== n ? i.createElementNS(t, e) : i.createElement(e), m = (e, t) => { let l = e.firstChild; for (; l;) { let e = l.nextSibling; t.appendChild(l), l = e } return t }, p = (e, t, l) => { e[l] !== t[l] && (e[l] = t[l], e[l] ? e.setAttribute(l, "") : e.removeAttribute(l)) }, h = { OPTION: (e, t) => { let l = e.parentNode; if (l) { let n = l.nodeName.toUpperCase(); "OPTGROUP" === n && (l = l.parentNode, n = l && l.nodeName.toUpperCase()), "SELECT" !== n || l.hasAttribute("multiple") || (e.hasAttribute("selected") && !t.selected && (e.setAttribute("selected", "selected"), e.removeAttribute("selected")), l.selectedIndex = -1) } p(e, t, "selected") }, INPUT: (e, t) => { p(e, t, "checked"), p(e, t, "disabled"), e.value !== t.value && (e.value = t.value), t.hasAttribute("value") || e.removeAttribute("value") }, TEXTAREA: (e, t) => { let l = t.value; e.value !== l && (e.value = l); let n = e.firstChild; if (n) { let t = n.nodeValue; if (t == l || !l && t == e.placeholder) return; n.nodeValue = l } }, SELECT: (e, t) => { if (!t.hasAttribute("multiple")) { let t, l, n = -1, i = 0, r = e.firstChild; for (; r;)if (l = r.nodeName && r.nodeName.toUpperCase(), "OPTGROUP" === l) t = r, r = t.firstChild; else { if ("OPTION" === l) { if (r.hasAttribute("selected")) { n = i; break } i++ } r = r.nextSibling, !r && t && (r = t.nextSibling, t = null) } e.selectedIndex = n } } }, N = 1, b = 11, A = 3, C = 8, T = () => { }, g = e => { if (e) return e.getAttribute && e.getAttribute("id") || e.id }, E = e => function (t, l, n) { if (n || (n = {}), "string" == typeof l) if ("#document" === t.nodeName || "HTML" === t.nodeName || "BODY" === t.nodeName) { let e = l; (l = i.createElement("html")).innerHTML = e } else l = s(l); else l.nodeType === b && (l = l.firstElementChild); let r = n.getNodeKey || g, d = n.onBeforeNodeAdded || T, o = n.onNodeAdded || T, a = n.onBeforeElUpdated || T, u = n.onElUpdated || T, p = n.onBeforeNodeDiscarded || T, E = n.onNodeDiscarded || T, v = n.onBeforeElChildrenUpdated || T, x = n.skipFromChildren || T, y = n.addChild || function (e, t) { return e.appendChild(t) }, S = !0 === n.childrenOnly, U = Object.create(null), O = [], R = e => { O.push(e) }, V = (e, t) => { if (e.nodeType === N) { let l = e.firstChild; for (; l;) { let e; t && (e = r(l)) ? R(e) : (E(l), l.firstChild && V(l, t)), l = l.nextSibling } } }, w = (e, t, l) => { !1 !== p(e) && (t && t.removeChild(e), E(e), V(e, l)) }, I = e => { if (e.nodeType === N || e.nodeType === b) { let t = e.firstChild; for (; t;) { let e = r(t); e && (U[e] = t), I(t), t = t.nextSibling } } }; I(t); let P = e => { o(e); let t = e.firstChild; for (; t;) { let e = t.nextSibling, l = r(t); if (l) { let e = U[l]; e && f(t, e) ? (t.parentNode.replaceChild(e, t), B(e, t)) : P(t) } else P(t); t = e } }, B = (t, l, n) => { let i = r(l); if (i && delete U[i], !n) { if (!1 === a(t, l)) return; if (e(t, l), u(t), !1 === v(t, l)) return } "TEXTAREA" !== t.nodeName ? L(t, l) : h.TEXTAREA(t, l) }, L = (e, t) => { let l, n, o, a, u, s = x(e, t), c = t.firstChild, m = e.firstChild; e: for (; c;) { for (a = c.nextSibling, l = r(c); !s && m;) { if (o = m.nextSibling, c.isEqualNode && c.isEqualNode(m)) { c = a, m = o; continue e } n = r(m); let t, i = m.nodeType; if (i === c.nodeType && (i === N ? (l ? l !== n && ((u = U[l]) ? o === u ? t = !1 : (e.insertBefore(u, m), n ? R(n) : w(m, e, !0), m = u, n = r(m)) : t = !1) : n && (t = !1), t = !1 !== t && f(m, c), t && B(m, c)) : i !== A && i != C || (t = !0, m.nodeValue !== c.nodeValue && (m.nodeValue = c.nodeValue))), t) { c = a, m = o; continue e } n ? R(n) : w(m, e, !0), m = o } if (l && (u = U[l]) && f(u, c)) s || y(e, u), B(u, c); else { let t = d(c); !1 !== t && (t && (c = t), c.actualize && (c = c.actualize(e.ownerDocument || i)), y(e, c), P(c)) } c = a, m = o } ((e, t, l) => { for (; t;) { let n = t.nextSibling; (l = r(t)) ? R(l) : w(t, e, !0), t = n } })(e, m, n); let p = h[e.nodeName]; p && p(e, t) }, D = t, z = D.nodeType, H = l.nodeType; if (!S) if (z === N) H === N ? f(t, l) || (E(t), D = m(t, c(l.nodeName, l.namespaceURI))) : D = l; else if (z === A || z === C) { if (H === z) return D.nodeValue !== l.nodeValue && (D.nodeValue = l.nodeValue), D; D = l } if (B(D, l, S), O) for (let e = 0, t = O.length; e < t; e++) { let t = U[O[e]]; t && w(t, t.parentNode, !1) } return !S && D !== t && t.parentNode && (D.actualize && (D = D.actualize(t.ownerDocument || i)), t.parentNode.replaceChild(D, t)), D }; window.morphdom = E(l) };
        // from sha1-uint8array@0.10.7
        { const K = [1518500249, 1859775393, -1894007588, -899497514]; window.createHash = () => new Hash; class Hash { constructor() { this.A = 1732584193, this.B = -271733879, this.C = -1732584194, this.D = 271733878, this.E = -1009589776, this._size = 0, this._sp = 0, (!sharedBuffer || sharedOffset >= 8e3) && (sharedBuffer = new ArrayBuffer(8e3), sharedOffset = 0), this._byte = new Uint8Array(sharedBuffer, sharedOffset, 80), this._word = new Int32Array(sharedBuffer, sharedOffset, 20), sharedOffset += 80 }; update(t) { if ("string" == typeof t) return this._utf8(t); if (null == t) throw new TypeError("Invalid type: " + typeof t); const s = t.byteOffset, e = t.byteLength; let r = e / 64 | 0, i = 0; if (r && !(3 & s) && !(this._size % 64)) { const e = new Int32Array(t.buffer, s, 16 * r); for (; r--;)this._int32(e, i >> 2), i += 64; this._size += i } if (1 !== t.BYTES_PER_ELEMENT && t.buffer) { const r = new Uint8Array(t.buffer, s + i, e - i); return this._uint8(r) } return i === e ? this : this._uint8(t, i) }; _uint8(t, s) { const { _byte: e, _word: r } = this, i = t.length; for (s |= 0; s < i;) { const h = this._size % 64; let n = h; for (; s < i && n < 64;)e[n++] = t[s++]; n >= 64 && this._int32(r), this._size += n - h } return this }; _utf8(t) { const { _byte: s, _word: e } = this, r = t.length; let i = this._sp; for (let h = 0; h < r;) { const n = this._size % 64; let f = n; for (; h < r && f < 64;) { let e = 0 | t.charCodeAt(h++); e < 128 ? s[f++] = e : e < 2048 ? (s[f++] = 192 | e >>> 6, s[f++] = 128 | 63 & e) : e < 55296 || e > 57343 ? (s[f++] = 224 | e >>> 12, s[f++] = 128 | e >>> 6 & 63, s[f++] = 128 | 63 & e) : i ? (e = ((1023 & i) << 10) + (1023 & e) + 65536, s[f++] = 240 | e >>> 18, s[f++] = 128 | e >>> 12 & 63, s[f++] = 128 | e >>> 6 & 63, s[f++] = 128 | 63 & e, i = 0) : i = e } f >= 64 && (this._int32(e), e[0] = e[16]), this._size += f - n } return this._sp = i, this }; _int32(t, s) { let { A: e, B: r, C: i, D: h, E: n } = this, f = 0; for (s |= 0; f < 16;)W[f++] = swap32(t[s++]); for (f = 16; f < 80; f++)W[f] = rotate1(W[f - 3] ^ W[f - 8] ^ W[f - 14] ^ W[f - 16]); for (f = 0; f < 80; f++) { const t = f / 20 | 0, s = rotate5(e) + ft(t, r, i, h) + n + W[f] + K[t] | 0; n = h, h = i, i = rotate30(r), r = e, e = s } this.A = e + this.A | 0, this.B = r + this.B | 0, this.C = i + this.C | 0, this.D = h + this.D | 0, this.E = n + this.E | 0 }; digest(t) { const { _byte: s, _word: e } = this; let r = this._size % 64 | 0; for (s[r++] = 128; 3 & r;)s[r++] = 0; if (r >>= 2, r > 14) { for (; r < 16;)e[r++] = 0; r = 0, this._int32(e) } for (; r < 16;)e[r++] = 0; const i = 8 * this._size, h = (4294967295 & i) >>> 0, n = (i - h) / 4294967296; return n && (e[14] = swap32(n)), h && (e[15] = swap32(h)), this._int32(e), "hex" === t ? this._hex() : this._bin() }; _hex() { const { A: t, B: s, C: e, D: r, E: i } = this; return hex32(t) + hex32(s) + hex32(e) + hex32(r) + hex32(i) }; _bin() { const { A: t, B: s, C: e, D: r, E: i, _byte: h, _word: n } = this; return n[0] = swap32(t), n[1] = swap32(s), n[2] = swap32(e), n[3] = swap32(r), n[4] = swap32(i), h.slice(0, 20) } }; const W = new Int32Array(80); let sharedBuffer, sharedOffset = 0; const hex32 = t => (t + 4294967296).toString(16).substr(-8), swapLE = t => t << 24 & 4278190080 | t << 8 & 16711680 | t >> 8 & 65280 | t >> 24 & 255, swapBE = t => t, swap32 = isBE() ? swapBE : swapLE, rotate1 = t => t << 1 | t >>> 31, rotate5 = t => t << 5 | t >>> 27, rotate30 = t => t << 30 | t >>> 2; function ft(t, s, e, r) { return 0 === t ? s & e | ~s & r : 2 === t ? s & e | s & r | e & r : s ^ e ^ r } function isBE() { return 254 === new Uint8Array(new Uint16Array([65279]).buffer)[0] } };
    </script>
    <script>




        // Swipe menü için değişkenler
        let touchStartX = 0;
        let touchEndX = 0;
        let touchStartY = 0;
        let touchEndY = 0;
        const SWIPE_THRESHOLD = 140; // Daha düşük eşik değeri
        const MIN_SWIPE_DISTANCE = 60; // Minimum kaydırma mesafesi
        let isDragging = false;
        let isScrolling = false;
        let startTime = 0;

        // Sadece mobil cihazlarda touch eventleri ekle
        if (window.innerWidth <= 800) {
            document.addEventListener('touchstart', handleTouchStart, false);
            document.addEventListener('touchmove', handleTouchMove, { passive: false });
            document.addEventListener('touchend', handleTouchEnd, false);
        }


        document.querySelector('.overlay').addEventListener('click', () => {
            document.querySelector('.chat_window').classList.remove('show-nav');
        });

        function handleTouchStart(event) {
            // Eğer text seçimi varsa veya input/textarea üzerindeyse kaydırmayı engelle
            if (window.getSelection().toString() ||
                event.target.tagName.toLowerCase() === 'input' ||
                event.target.tagName.toLowerCase() === 'textarea' ||
                event.target.isContentEditable) {
                return;
            }

            touchStartX = event.touches[0].clientX;
            touchStartY = event.touches[0].clientY;
            startTime = Date.now();
            isScrolling = false;

            // Ekranın sol yarısından başlayan dokunuşları kabul et
            if (touchStartX < window.innerWidth / 2) {
                isDragging = true;
            }
        }
        function handleTouchMove(event) {
            if (!isDragging) return;

            touchEndX = event.touches[0].clientX;
            touchEndY = event.touches[0].clientY;

            const deltaY = Math.abs(touchEndY - touchStartY);
            const deltaX = Math.abs(touchEndX - touchStartX);
            const currentSwipe = touchEndX - touchStartX;
            const isNavOpen = document.querySelector('.chat_window').classList.contains('show-nav');

            // Yatay kaydırma daha belirginse ve minimum mesafeyi geçtiyse
            if (deltaX > deltaY && deltaX > MIN_SWIPE_DISTANCE) {
                // Menü açıkken sağdan sola kaydırma veya kapalıyken soldan sağa kaydırma
                if ((isNavOpen && currentSwipe < 0) || (!isNavOpen && currentSwipe > 0)) {
                    event.preventDefault();
                    updateNavPosition(currentSwipe, isNavOpen);
                }
            } else if (deltaY > deltaX) {
                // Dikey kaydırma varsa iptal et
                isScrolling = true;
                isDragging = false;
                resetNavPosition();
            }
        }

        function handleTouchEnd() {
            if (!isDragging || isScrolling) return;

            const swipeTime = Date.now() - startTime;
            const swipeDistance = touchEndX - touchStartX;
            const isNavOpen = document.querySelector('.chat_window').classList.contains('show-nav');
            const swipeSpeed = Math.abs(swipeDistance) / swipeTime;

            // Hızlı ve yeterli mesafede kaydırma kontrolü
            const isValidSwipe = (swipeTime < 300 && Math.abs(swipeDistance) > MIN_SWIPE_DISTANCE) ||
                (Math.abs(swipeDistance) > SWIPE_THRESHOLD) ||
                (swipeSpeed > 0.5);

            if (isNavOpen) {
                // Menü açıkken sola kaydırma
                if (swipeDistance < 0 && isValidSwipe) {
                    document.querySelector('.chat_window').classList.remove('show-nav');
                }
            } else {
                // Menü kapalıyken sağa kaydırma
                if (swipeDistance > 0 && isValidSwipe) {
                    document.querySelector('.chat_window').classList.add('show-nav');
                }
            }

            resetNavPosition();
            isDragging = false;
            isScrolling = false;
        }

        function updateNavPosition(swipeDistance, isNavOpen) {
            const nav = document.querySelector('.nav');
            const maxSwipe = 250; // Menü genişliği
            let progress;

            if (isNavOpen) {
                // Menü açıkken sola kaydırma için progress hesabı
                progress = Math.max(0, maxSwipe + swipeDistance);
            } else {
                // Menü kapalıyken sağa kaydırma için progress hesabı
                progress = Math.min(swipeDistance, maxSwipe);
            }

            nav.style.left = `${progress - maxSwipe}px`;

            // Overlay'in opaklığını ayarla
            const overlay = document.querySelector('.overlay');
            overlay.style.visibility = 'visible';
            overlay.style.opacity = progress / maxSwipe;
        }
        function resetNavPosition() {
            const nav = document.querySelector('.nav');
            nav.style.left = '';
            nav.style.marginLeft = '';

            const overlay = document.querySelector('.overlay');
            overlay.style.visibility = '';
            overlay.style.opacity = '';
        }

        const stringToArray = string => {
            let arr = []
            for (let i = 0; i < string.length; i++) {
                arr.push(string.charCodeAt(i));
            }
            return arr
        }
        const stringToUint = string => {
            return new Uint8Array(stringToArray(string));
        }
        const uintToString = uintArray => {
            let str = "";
            let len = Math.ceil(uintArray.byteLength / 32767);
            for (let i = 0; i < len; i++) {
                str += String.fromCharCode.apply(null, uintArray.subarray(i * 32767, Math.min((i + 1) * 32767, uintArray.byteLength)));
            }
            return str;
        }
        let isCompressedChats = localStorage.getItem("compressedChats") === "true";
        const originSetItem = localStorage.setItem;
        localStorage.setItem = (key, value) => {
            try {
                if (isCompressedChats && key === "chats") value = uintToString(deflateSync(new TextEncoder().encode(value), { level: 1 }));
                originSetItem.call(localStorage, key, value)
            } catch (e) {
                if (isCompressedChats) {
                    notyf.error(translations[locale]["localQuotaExceedTip"])
                    return;
                }
                let isKeyChats = key === "chats";
                let compressed = uintToString(deflateSync(new TextEncoder().encode(isKeyChats ? value : localStorage.getItem("chats")), { level: 1 }));
                originSetItem.call(localStorage, "chats", compressed);
                originSetItem.call(localStorage, "compressedChats", true);
                isCompressedChats = true;
                if (!isKeyChats) originSetItem.call(localStorage, key, value);
            }
        }
    </script>
    <script>
        const localeList = ["en", "tr", "zh" ];
        let locale; // UI语言
        const setLangEle = document.getElementById("setLang");
        const setLang = () => {
            let langClass = locale + "Lang";
            localStorage.setItem("UILang", locale)
            document.documentElement.lang = locale === "zh" ? "zh-CN" : "en";
            setLangEle.classList = "setDetail themeDetail langDetail " + langClass;
        }
        setLangEle.onclick = (ev) => {
            let idx = Array.prototype.indexOf.call(setLangEle.children, ev.target);
            if (locale !== localeList[idx]) {
                locale = localeList[idx];
                setLang();
                changeLocale();
            }
        }
        const initLang = () => {
            let localLang = localStorage.getItem("UILang") || (navigator.language.startsWith("tr-") ? "tr" : "en");
            let isInit = locale === void 0;
            if (locale !== localLang) {
                locale = localLang;
                if (!isInit) changeLocale();
            };
            setLang();
        }
        initLang();
        const translations = {
            "en": {
                "description": "Simple and powerful ChatGPT app",
                "newChat": "New chat",
                "newChatName": "New chat",
                "newFolder": "New folder",
                "newFolderName": "New folder",
                "search": "Search",
                "matchCaseTip": "Match case",
                "forceRe": "Force refresh",
                "clearAll": "Clear all chats",
                "setting": "Setting",
                "nav": "Navigate",
                "winedWin": "Window",
                "fullWin": "Full screen",
                "quickSet": "Quick setting",
                "chat": "Chat",
                "tts": "TTS",
                "stt": "STT",
                "avatar": "Avatar",
                "systemRole": "System role",
                "presetRole": "Preset",
                "default": "Default",
                "assistant": "Assistant",
                "cat": "Cat girl",
                "emoji": "Emoji",
                "withImg": "Image",
                "defaultText": "",
                "assistantText": "You are a helpful assistant, answer as concisely as possible.",
                "catText": "You are a cute cat girl, you must end every sentence with 'meow'",
                "emojiText": "Your personality is very lively, there must be at least one emoji icon in every sentence",
                "imageText": "When you need to send pictures, please generate them in markdown language, without backslashes or code boxes. When you need to use the unsplash API, follow the format, https://source.unsplash.com/960x640/?<English keywords>",
                "nature": "Nature",
                "natureNeg": "Accurate",
                "naturePos": "Creativity",
                "quality": "Quality",
                "qualityNeg": "Repetitive",
                "qualityPos": "Nonsense",
                "chatsWidth": "Chats width",
                "typeSpeed": "Typing speed",
                "continuousLen": "Context messages",
                "msgAbbr": " msgs.",
                "slow": "Slow",
                "fast": "Fast",
                "longReply": "Long reply",
                "ttsService": "TTS API",
                "sttService": "STT API",
                "openaiTTS": "OpenAI",
                "azureTTS": "Azure",
                "edgeTTS": "Edge",
                "systemTTS": "System",
                "azureRegion": "Azure region",
                "azureKey": "Azure key",
                "loadVoice": "Load voice",
                "voiceName": "Switch",
                "userVoice": "User voice",
                "replyVoice": "Reply voice",
                "TTSTest": "Hello, nice to meet you.",
                "play": "Play",
                "pause": "Pause",
                "resume": "Resume",
                "stop": "Stop",
                "style": "Style",
                "role": "Role",
                "volume": "Volume",
                "low": "Low",
                "high": "High",
                "rate": "Rate",
                "slow": "Slow",
                "fast": "Fast",
                "pitch": "Pitch",
                "neutral": "Neutral",
                "intense": "Intense",
                "contSpeech": "Continuous speech",
                "autoSpeech": "Auto speech",
                "unsupportRecTip": "Voice recognition is not supported in the current environment. Please refer to the documentation.",
                "loadRecVoice": "Load language",
                "lang": "Language",
                "dialect": "Dialect",
                "autoSendKey": "Auto send keyword",
                "autoStopKey": "Auto stop keyword",
                "autoSendDelay": "Auto send delay time",
                "second": "s",
                "keepListenMic": "Keep listen",
                "send": "Send",
                "askTip": "Type message here",
                "clearChat": "Clear chat",
                "general": "General",
                "hotkey": "Hotkey",
                "data": "Data",
                "theme": "Theme",
                "darkTheme": "Dark",
                "lightTheme": "Light",
                "autoWord": "Auto",
                "systemTheme": "System",
                "customDarkTheme": "Custom dark theme",
                "startDark": "Start",
                "endDark": "End",
                "aiEndpoint": " endpoint",
                "aiKey": " API key",
                "aiModel": "Custom model name",
                "used": "Used ",
                "available": "Avail ",
                "navKey": "Toggle nav",
                "fullKey": "Window size",
                "themeKey": "Toggle theme",
                "langKey": "Toggle lang",
                "inputKey": "Message",
                "voiceKey": "Voice",
                "resetTip": "Restore default",
                "recKey": "Recognition",
                "speechKey": "Start speech",
                "export": "Export",
                "import": "Import",
                "clear": "Clear",
                "reset": "Reset",
                "localStore": "Local storage",
                "forceReTip": "Force refresh page?",
                "noSpeechTip": "No speech was detected. You may need to adjust your microphone settings.",
                "noMicTip": "No microphone was found. Ensure that a microphone is installed and microphone settings are configured correctly.",
                "noMicPerTip": "Permission to use microphone is blocked.",
                "azureInvalidTip": "Invalid access key or wrong Azure region endpoint, please check!",
                "errorAiKeyTip": "Invalid or incorrect API key, please check API key!",
                "copyCode": "Copy code",
                "copySuccess": "Success",
                "update": "Update",
                "cancel": "Cancel",
                "delMsgTip": "Delete this message?",
                "edit": "Edit",
                "refresh": "Refresh",
                "continue": "Continue",
                "copy": "Copy",
                "del": "Delete",
                "downAudio": "Download audio",
                "speech": "Speech",
                "chats": " chats",
                "delFolderTip": "Delete this folder?",
                "delChatTip": "Delete this chat?",
                "exportSuccTip": "Export successful!",
                "importSuccTip": "Import successful!",
                "importFailTip": "Import failed, please check the file format!",
                "clearChatSuccTip": "Clear chats data successful!",
                "resetSetSuccTip": "Reset settings successful!",
                "clearAllTip": "Delete all chats and folders?",
                "resetSetTip": "Restore all settings to default?",
                "hotkeyConflict": "Hotkey conflict, please choose another key!",
                "customDarkTip": "Start time and end time cannot be the same!",
                "timeoutTip": "Request timeout, please try again later!",
                "largeReqTip": "Request is too large, please delete part of the chat or cancel continuous chat!",
                "noModelPerTip": "Not permission to use this model, please choose another GPT model!",
                "apiRateTip": "Trigger API call rate limit, please try again later!",
                "exceedLimitTip": "API usage exceeded limit, please check your bill!",
                "badGateTip": "Gateway error or timeout, please try again later!",
                "badEndpointTip": "Failed to access the endpoint, please check the endpoint!",
                "clearChatTip": "Clear this chat?",
                "cantSpeechTip": "Current voice cannot synthesize this message, please choose another voice or message!",
                "cantTranscribeTip": "Voice recognition failed, please try again!",
                "noStreamTip": "Automatic features aren't available for non-realtime speech recognition service!",
                "localQuotaExceedTip": "Local storage exceeded limit, please export chats data and clear or delete some chats!",
            },


            "tr": {
                "description": "Basit ve güçlü ChatGPT uygulaması",
                "newChat": "Yeni sohbet",
                "newChatName": "Yeni sohbet",
                "newFolder": "Yeni klasör",
                "newFolderName": "Yeni klasör",
                "search": "Ara",
                "matchCaseTip": "Büyük/küçük harf duyarlı",
                "forceRe": "Zorla yenile",
                "clearAll": "Tüm sohbetleri temizle",
                "setting": "Ayarlar",
                "nav": "Gezinme",
                "winedWin": "Pencere",
                "fullWin": "Tam ekran",
                "quickSet": "Hızlı ayar",
                "chat": "Sohbet",
                "tts": "TTS",
                "stt": "STT",
                "avatar": "Avatar",
                "systemRole": "Sistem rolü",
                "presetRole": "Hazır rol",
                "default": "Varsayılan",
                "assistant": "Yardımcı",
                "cat": "Kedi kızı",
                "emoji": "Emojiler",
                "withImg": "Resim ile",
                "defaultText": "",
                "assistantText": "Yardımcı bir asistan olarak, mümkün olduğunca kısa ve öz cevap ver.",
                "catText": "Sen tatlı bir kedi kızısın, her cümlenin sonuna 'meow' eklemelisin.",
                "emojiText": "Kişiliğin çok canlı, her cümlede en az bir emoji ikonu bulunmalı.",
                "imageText": "Resim göndermen gerektiğinde, lütfen resimleri markdown dilinde oluştur, ters eğik çizgi veya kod kutusu kullanmadan. Unsplash API'sini kullanman gerektiğinde, şu formatı takip et: https://source.unsplash.com/960x640/?<İngilizce anahtar kelimeler>",
                "nature": "Doğa",
                "natureNeg": "Doğru",
                "naturePos": "Yaratıcılık",
                "quality": "Kalite",
                "qualityNeg": "Tekrarlayan",
                "qualityPos": "Saçma",
                "chatsWidth": "Sohbetler genişliği",
                "typeSpeed": "Yazma hızı",
                "continuousLen": "Bağlam mesajları",
                "msgAbbr": " mesajlar.",
                "slow": "Yavaş",
                "fast": "Hızlı",
                "longReply": "Uzun yanıt",
                "ttsService": "TTS API'si",
                "sttService": "STT API'si",
                "openaiTTS": "OpenAI",
                "azureTTS": "Azure",
                "edgeTTS": "Edge",
                "systemTTS": "Sistem",
                "azureRegion": "Azure bölgesi",
                "azureKey": "Azure anahtarı",
                "loadVoice": "Ses yükle",
                "voiceName": "Ses değiştir",
                "userVoice": "Kullanıcı sesi",
                "replyVoice": "Yanıt sesi",
                "TTSTest": "Merhaba, tanıştığımıza memnun oldum.",
                "play": "Oynat",
                "pause": "Duraklat",
                "resume": "Devam et",
                "stop": "Durdur",
                "style": "Tarz",
                "role": "Rol",
                "volume": "Ses seviyesi",
                "low": "Düşük",
                "high": "Yüksek",
                "rate": "Hız",
                "slow": "Yavaş",
                "fast": "Hızlı",
                "pitch": "Tonlama",
                "neutral": "Nötr",
                "intense": "Yoğun",
                "contSpeech": "Kesintisiz konuşma",
                "autoSpeech": "Otomatik konuşma",
                "unsupportRecTip": "Ses tanıma, mevcut ortamda desteklenmiyor. Lütfen belgeleri inceleyin.",
                "loadRecVoice": "Dil yükle",
                "lang": "Dil",
                "dialect": "Ağız",
                "autoSendKey": "Otomatik gönderme anahtarı",
                "autoStopKey": "Otomatik durdurma anahtarı",
                "autoSendDelay": "Otomatik gönderme gecikme süresi",
                "second": "s",
                "keepListenMic": "Dinlemeyi sürdür",
                "send": "Gönder",
                "askTip": "Buraya mesaj yazın",
                "clearChat": "Sohbeti temizle",
                "general": "Genel",
                "hotkey": "Kısayol tuşu",
                "data": "Veri",
                "theme": "Tema",
                "darkTheme": "Koyu",
                "lightTheme": "Açık",
                "autoWord": "Otomatik",
                "systemTheme": "Sistem",
                "customDarkTheme": "Özel koyu tema",
                "startDark": "Başlat",
                "endDark": "Bitir",
                "aiEndpoint": " uç nokta",
                "aiKey": " API anahtarı",
                "aiModel": "Özel model adı",
                "used": "Kullanıldı ",
                "available": "Mevcut ",
                "navKey": "Gezinmeyi aç/kapat",
                "fullKey": "Pencere boyutu",
                "themeKey": "Tema aç/kapat",
                "langKey": "Dil aç/kapat",
                "inputKey": "Mesaj",
                "voiceKey": "Ses",
                "resetTip": "Varsayılan ayarlara geri dön",
                "recKey": "Tanıma",
                "speechKey": "Konuşmayı başlat",
                "export": "Dışa aktar",
                "import": "İçe aktar",
                "clear": "Temizle",
                "reset": "Sıfırla",
                "localStore": "Yerel depolama",
                "forceReTip": "Sayfayı zorla yenilemek istiyor musunuz?",
                "noSpeechTip": "Konuşma tespit edilmedi. Mikrofon ayarlarınızı kontrol etmeniz gerekebilir.",
                "noMicTip": "Mikrofon bulunamadı. Mikrofonun takılı olduğundan ve mikrofon ayarlarınızın doğru yapılandırıldığından emin olun.",
                "noMicPerTip": "Mikrofonu kullanma izni engellenmiş.",
                "azureInvalidTip": "Geçersiz erişim anahtarı veya yanlış Azure bölgesi uç noktası, lütfen kontrol edin!",
                "errorAiKeyTip": "Geçersiz veya yanlış API anahtarı, lütfen API anahtarını kontrol edin!",
                "copyCode": "Kodu kopyala",
                "copySuccess": "Başarılı",
                "update": "Güncelle",
                "cancel": "İptal",
                "delMsgTip": "Bu mesajı silmek istiyor musunuz?",
                "edit": "Düzenle",
                "refresh": "Yenile",
                "continue": "Devam et",
                "copy": "Kopyala",
                "del": "Sil",
                "downAudio": "Ses dosyasını indir",
                "speech": "Konuşma",
                "chats": " sohbetler",
                "delFolderTip": "Bu klasörü silmek istiyor musunuz?",
                "delChatTip": "Bu sohbeti silmek istiyor musunuz?",
                "exportSuccTip": "Dışa aktarma başarılı!",
                "importSuccTip": "İçe aktarma başarılı!",
                "importFailTip": "İçe aktarma başarısız, lütfen dosya formatını kontrol edin!",
                "clearChatSuccTip": "Sohbet verilerini temizleme başarılı!",
                "resetSetSuccTip": "Ayarları sıfırlama başarılı!",
                "clearAllTip": "Tüm sohbetleri ve klasörleri silmek istiyor musunuz?",
                "resetSetTip": "Tüm ayarları varsayılan hale getirmek istiyor musunuz?",
                "hotkeyConflict": "Kısayol tuşu çakışması, lütfen başka bir tuş seçin!",
                "customDarkTip": "Başlangıç ve bitiş saatleri aynı olamaz!",
                "timeoutTip": "İstek zaman aşımına uğradı, lütfen tekrar deneyin!",
                "largeReqTip": "İstek çok büyük, lütfen sohbetin bir kısmını silin veya sürekli sohbeti iptal edin!",
                "noModelPerTip": "Bu modeli kullanmaya yetkiniz yok, lütfen başka bir GPT modeli seçin!",
                "apiRateTip": "API çağrı hızı sınırına ulaşıldı, lütfen tekrar deneyin!",
                "exceedLimitTip": "API kullanım limiti aşıldı, lütfen faturayı kontrol edin!",
                "badGateTip": "Ağ geçidi hatası veya zaman aşımı, lütfen tekrar deneyin!",
                "badEndpointTip": "Uç noktaya erişim başarısız, lütfen uç noktayı kontrol edin!",
                "clearChatTip": "Bu sohbeti temizlemek istiyor musunuz?",
                "cantSpeechTip": "Mevcut ses bu mesajı sentezleyemiyor, lütfen başka bir ses veya mesaj seçin!",
                "cantTranscribeTip": "Ses tanıma başarısız oldu, lütfen tekrar deneyin!",
                "noStreamTip": "Otomatik özellikler, gerçek zamanlı ses tanıma servisi olmayan durumlar için geçerli değildir!",
                "localQuotaExceedTip": "Yerel depolama limiti aşıldı, lütfen sohbet verilerini dışa aktarın ve bazı sohbetleri temizleyin veya silin!"
            },


            "zh": {
                "description": "简洁而强大的ChatGPT应用",
                "newChat": "新建会话",
                "newChatName": "新的会话",
                "newFolder": "新建文件夹",
                "newFolderName": "新文件夹",
                "search": "搜索",
                "matchCaseTip": "区分大小写",
                "forceRe": "强制刷新",
                "clearAll": "清空全部",
                "setting": "设置",
                "nav": "导航",
                "winedWin": "窗口",
                "fullWin": "全屏",
                "quickSet": "快速设置",
                "chat": "会话",
                "tts": "语音合成",
                "stt": "语音识别",
                "avatar": "用户头像",
                "systemRole": "系统角色",
                "presetRole": "预设角色",
                "default": "默认",
                "assistant": "助手",
                "cat": "猫娘",
                "emoji": "表情",
                "withImg": "有图",
                "defaultText": "",
                "assistantText": "你是一个乐于助人的助手，尽量简明扼要地回答",
                "catText": "你是一个可爱的猫娘，每句话结尾都要带个'喵'",
                "emojiText": "你的性格很活泼，每句话中都要有至少一个emoji图标",
                "imageText": "当你需要发送图片的时候，请用 markdown 语言生成，不要反斜线，不要代码框，需要使用 unsplash API时，遵循一下格式， https://source.unsplash.com/960x640/? ＜英文关键词＞",
                "nature": "角色性格",
                "natureNeg": "准确严谨",
                "naturePos": "灵活创新",
                "quality": "回答质量",
                "qualityNeg": "重复保守",
                "qualityPos": "胡言乱语",
                "chatsWidth": "会话宽度",
                "typeSpeed": "打字机速度",
                "continuousLen": "上下文消息数",
                "msgAbbr": "条",
                "slow": "慢",
                "fast": "快",
                "longReply": "长回复",
                "ttsService": "语音合成服务",
                "sttService": "语音识别服务",
                "openaiTTS": "OpenAI语音",
                "azureTTS": "Azure语音",
                "edgeTTS": "Edge语音",
                "systemTTS": "系统语音",
                "azureRegion": "Azure区域",
                "azureKey": "Azure密钥",
                "loadVoice": "加载语音",
                "voiceName": "切换",
                "userVoice": "用户语音",
                "replyVoice": "回答语音",
                "TTSTest": "你好，很高兴认识你。",
                "play": "播放",
                "pause": "暂停",
                "resume": "恢复",
                "stop": "停止",
                "style": "风格",
                "role": "角色",
                "volume": "音量",
                "low": "低",
                "high": "高",
                "rate": "语速",
                "slow": "慢",
                "fast": "快",
                "pitch": "音调",
                "neutral": "平淡",
                "intense": "起伏",
                "contSpeech": "连续朗读",
                "autoSpeech": "自动朗读",
                "unsupportRecTip": "当前环境不支持语音识别，请查阅文档。",
                "loadRecVoice": "加载语言",
                "lang": "语言",
                "dialect": "方言",
                "autoSendKey": "自动发送关键词",
                "autoStopKey": "自动停止关键词",
                "autoSendDelay": "自动发送延迟时间",
                "second": "秒",
                "keepListenMic": "保持监听",
                "send": "发送",
                "askTip": "来问点什么吧",
                "clearChat": "清空会话",
                "general": "通用",
                "hotkey": "快捷键",
                "data": "数据",
                "theme": "主题",
                "darkTheme": "深色",
                "lightTheme": "浅色",
                "autoWord": "自动",
                "systemTheme": "跟随系统",
                "customDarkTheme": "自定义深色主题时间",
                "startDark": "开始时间",
                "endDark": "结束时间",
                "aiEndpoint": "接口",
                "aiKey": "API密钥",
                "aiModel": "自定义模型",
                "used": "已用 ",
                "available": "可用 ",
                "navKey": "切换导航",
                "fullKey": "全屏/窗口",
                "themeKey": "切换主题",
                "langKey": "切换语言",
                "inputKey": "输入框",
                "voiceKey": "语音",
                "resetTip": "重置设置",
                "recKey": "语音输入",
                "speechKey": "朗读会话",
                "export": "导出",
                "import": "导入",
                "clear": "清空",
                "reset": "重置",
                "localStore": "本地存储",
                "forceReTip": "是否强制刷新页面？",
                "noSpeechTip": "未识别到语音，请调整麦克风后重试！",
                "noMicTip": "未识别到麦克风，请确保已安装麦克风！",
                "noMicPerTip": "未允许麦克风权限！",
                "azureInvalidTip": "Azure区域错误或密钥无效，请检查！",
                "errorAiKeyTip": "API密钥错误或失效，请检查API密钥！",
                "copyCode": "复制代码",
                "copySuccess": "复制成功",
                "update": "更新",
                "cancel": "取消",
                "delMsgTip": "是否删除此消息？",
                "edit": "编辑",
                "refresh": "刷新",
                "continue": "继续",
                "copy": "复制",
                "del": "删除",
                "downAudio": "下载语音",
                "speech": "朗读",
                "chats": "个会话",
                "delFolderTip": "是否删除此文件夹？",
                "delChatTip": "是否删除此会话？",
                "exportSuccTip": "导出成功！",
                "importSuccTip": "导入成功！",
                "importFailTip": "导入失败，请检查文件格式！",
                "clearChatSuccTip": "清空会话成功！",
                "resetSetSuccTip": "重置设置成功！",
                "clearAllTip": "是否删除所有会话和文件夹？",
                "resetSetTip": "是否还原所有设置为默认值？",
                "hotkeyConflict": "快捷键冲突，请选择其他键位！",
                "customDarkTip": "开始时间和结束时间不能相同！",
                "timeoutTip": "请求超时，请稍后重试！",
                "largeReqTip": "请求内容过大，请删除部分对话或关闭连续对话！",
                "noModelPerTip": "无权使用此模型，请选择其他GPT模型！",
                "apiRateTip": "触发API调用频率限制，请稍后重试！",
                "exceedLimitTip": "API使用超出限额，请检查您的账单！",
                "badGateTip": "网关错误或超时，请稍后重试！",
                "badEndpointTip": "访问接口失败，请检查接口！",
                "clearChatTip": "是否清空此会话？",
                "cantSpeechTip": "当前语音无法合成此消息，请选择其他语音或消息！",
                "cantTranscribeTip": "语音识别失败，请重试！",
                "noStreamTip": "非实时语音识别服务无法使用自动功能！",
                "localQuotaExceedTip": "本地存储超出限额，请导出会话并清空或删除部分会话！",
            },
        };
        const translateElement = (ele, type) => {
            const key = ele.getAttribute("data-i18n-" + type);
            const translation = translations[locale][key];
            if (type === "title") {
                ele.setAttribute("title", translation);
            } else if (type === "place") {
                ele.setAttribute("placeholder", translation);
            } else if (type === "value") {
                ele.setAttribute("value", translation);
            } else {
                ele.textContent = translation;
            }
        }
        const initLocale = () => {
            document.querySelectorAll("[data-i18n-title]").forEach(ele => { translateElement(ele, "title") });
            document.querySelectorAll("[data-i18n-place]").forEach(ele => { translateElement(ele, "place") });
            document.querySelectorAll("[data-i18n-value]").forEach(ele => { translateElement(ele, "value") });
            document.querySelectorAll("[data-i18n-key]").forEach(ele => { translateElement(ele, "key") });
            document.querySelectorAll("[data-i18n-theme]").forEach(ele => {
                let key = themeMode === 2 ? "autoWord" : themeMode === 1 ? "lightTheme" : "darkTheme";
                ele.setAttribute("title", translations[locale][key])
            })
            document.querySelectorAll("[data-i18n-window]").forEach(ele => {
                let key = isFull ? "winedWin" : "fullWin";
                ele.setAttribute("title", translations[locale][key])
            })
            document.head.children[3].setAttribute("content", translations[locale]["description"])
        };
        initLocale();
        const changeLocale = () => {
            initLocale();
            document.querySelectorAll("[data-type='chatEdit'],[data-type='folderEdit']").forEach(ele => {
                ele.children[0].textContent = translations[locale]["edit"];
            });
            document.querySelectorAll("[data-type='chatDel'],[data-type='folderDel']").forEach(ele => {
                ele.children[0].textContent = translations[locale]["del"];
            });
            document.querySelectorAll("[data-type='folderAddChat']").forEach(ele => {
                ele.children[0].textContent = translations[locale]["newChat"];
            });
            document.querySelectorAll("[data-id]").forEach(ele => {
                let key = ele.getAttribute("data-id");
                if (key.endsWith("Md")) {
                    if (key === "speechMd" || key === "pauseMd" || key === "resumeMd") {
                        ele.children[0].textContent = translations[locale][key.slice(0, -2)];
                    } else if (key === "refreshMd") {
                        ele.setAttribute("title", translations[locale][ele.classList.contains("refreshReq") ? "refresh" : "continue"]);
                    } else {
                        ele.setAttribute("title", translations[locale][key.slice(0, -2)]);
                    }
                }
            });
            document.querySelectorAll(".folderNum").forEach(ele => {
                let num = ele.textContent.match(/\d+/)[0];
                ele.textContent = num + translations[locale]["chats"];
            });
            document.querySelectorAll(".u-mdic-copy-btn").forEach(ele => {
                ele.setAttribute("text", translations[locale]["copyCode"]);
            })
            document.querySelectorAll(".u-mdic-copy-notify").forEach(ele => {
                ele.setAttribute("text", translations[locale]["copySuccess"]);
            })
            if (editingIdx !== void 0) {
                document.querySelector("[data-i18n-key='send']").textContent = translations[locale]["update"];
                document.querySelector("[data-i18n-title='clearChat']").setAttribute("title", translations[locale]["cancel"]);
            }
            loadPrompt();
        }
    </script>
    <script>
        const windowEle = document.getElementsByClassName("chat_window")[0];
        const messagesEle = document.getElementsByClassName("messages")[0];
        const chatlog = document.getElementById("chatlog");
        const stopEle = document.getElementById("stopChat");
        const sendBtnEle = document.getElementById("sendbutton");
        const clearEle = document.getElementsByClassName("clearConv")[0];
        const inputAreaEle = document.getElementById("chatinput");
        const settingEle = document.getElementById("setting");
        const dialogEle = document.getElementById("setDialog");
        const selectorEle = document.getElementById("selector");
        const modelSetEle = document.getElementById("modelDialog");
        const lightEle = document.getElementById("toggleLight");
        const setLightEle = document.getElementById("setLight");
        const autoThemeEle = document.getElementById("autoDetail");
        const systemEle = document.getElementById("systemInput");
        const speechServiceEle = document.getElementById("preSetService");
        const recServiceEle = document.getElementById("preRecService");
        const newChatEle = document.getElementById("newChat");
        const folderListEle = document.getElementById("folderList");
        const chatListEle = document.getElementById("chatList");
        const searchChatEle = document.getElementById("searchChat");
        const voiceRecEle = document.getElementById("voiceRecIcon");
        const voiceRecSetEle = document.getElementById("voiceRecSetting");
        const preEle = document.getElementById("preSetSystem");
        let voicesData; // 语音数据
        let voiceType = 1; // 设置 0: 提问语音，1：回答语音
        let voiceRole = []; // 语音
        let voiceTestText; // 测试语音文本
        let voiceVolume = []; //音量
        let voiceRate = []; // 语速
        let voicePitch = []; // 音调
        let enableContVoice; // 连续朗读
        let enableAutoVoice; // 自动朗读
        let existVoice = 2; // 4:OpenAI语音 3:Azure语音 2:edge在线语音, 1:本地语音, 0:不支持语音
        const azureRegions = ['southafricanorth', 'eastasia', 'southeastasia', 'australiaeast', 'centralindia', 'japaneast', 'japanwest', 'koreacentral', 'canadacentral', 'northeurope', 'westeurope', 'francecentral', 'germanywestcentral', 'norwayeast', 'swedencentral', 'switzerlandnorth', 'switzerlandwest', 'uksouth', 'uaenorth', 'brazilsouth', 'qatarcentral', 'centralus', 'eastus', 'eastus2', 'northcentralus', 'southcentralus', 'westcentralus', 'westus', 'westus2', 'westus3'];
        let azureRegion;
        let azureKey;
        let azureRole = [];
        let azureStyle = [];
        const supportSpe = !!(window.speechSynthesis && window.SpeechSynthesisUtterance);
        const isSafeEnv = window.isSecureContext; // 安全上下文
        const supportLocalRec = isSafeEnv && !!window.webkitSpeechRecognition; // 是否支持本地语音识别输入
        const supportOnlineRec = isSafeEnv && navigator.mediaDevices && navigator.mediaDevices.getUserMedia && window.AudioContext && ("audioWorklet" in window.AudioContext.prototype || "createScriptProcessor" in window.AudioContext.prototype);
        const supportOnlineLegacyRec = isSafeEnv && navigator.mediaDevices && navigator.mediaDevices.getUserMedia && !!window.MediaRecorder && (MediaRecorder.isTypeSupported("audio/webm") || MediaRecorder.isTypeSupported("audio/mp4"));
        const supportRec = supportLocalRec || supportOnlineRec || supportOnlineLegacyRec;
        let existRec = 1; // 2:Azure语音，1:系统语音
        let azureRecRegion;
        let azureRecKey;
        let recing = false;
        let autoSendWord; // 自动发送关键词
        let autoStopWord; // 自动停止关键词
        let autoSendTime; // 自动发送延迟时间
        let keepListenMic; // 保持监听麦克风
        let autoSendTimer;
        let resetRecRes;
        let toggleRecEv;
        const isAndroid = /\bAndroid\b/i.test(navigator.userAgent);
        const isApple = /(Mac|iPhone|iPod|iPad)/i.test(navigator.userAgent);
        const isSafari = /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
        const isPWA = navigator.standalone || window.matchMedia("(display-mode: standalone)").matches;
        if (isPWA) {
            let bottomEle = document.querySelector(".bottom_wrapper");
            let footerEle = document.querySelector(".navFooter");
            footerEle.style.marginBottom = bottomEle.style.marginBottom = "8px";
        };
        const dayMs = 8.64e7;
        refreshPage.onclick = () => {
            if (confirmAction(translations[locale]["forceReTip"])) {
                location.href = location.origin + location.pathname + "?" + new Date().getTime()
            }
        };
        const noLoading = () => {
            return !loading && (!currentResEle || currentResEle.dataset.loading !== "true")
        };
        const uuidv4 = (upper) => {
            let uuid = ([1e7] + 1e3 + 4e3 + 8e3 + 1e11).replace(/[018]/g, c =>
                (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
            );
            return upper ? uuid.toUpperCase() : uuid;
        };

        const uuidv5 = () => {
            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                const r = Math.random() * 16 | 0;
                const v = c === 'x' ? r : (r & 0x3 | 0x8);
                    return v.toString(16);
                }
            );
        };

        if (!isMobile) inputAreaEle.focus();
        const textInputEvent = () => {
            if (noLoading()) sendBtnEle.classList.toggle("activeSendBtn", inputAreaEle.value.trim().length);
            inputAreaEle.style.height = "47px";
            inputAreaEle.style.height = inputAreaEle.scrollHeight + "px";
        };
        inputAreaEle.oninput = textInputEvent;
        const toggleNavEv = () => {
            let isShowNav = document.body.classList.toggle("show-nav");
            if (window.innerWidth > 800) {
                localStorage.setItem("pinNav", isShowNav)
            }
        }
        document.body.addEventListener("mousedown", event => {
            if (event.target.className === "toggler") {
                toggleNavEv();
            } else if (event.target.className === "overlay") {
                document.body.classList.remove("show-nav");
            } else if (event.target === document.body) {
                if (window.innerWidth <= 800) {
                    document.body.classList.remove("show-nav");
                }
            }
        });
        const endSetEvent = (ev) => {
            if (!document.getElementById("sysDialog").contains(ev.target)) {
                ev.preventDefault();
                ev.stopPropagation();
                endSet();
            }
        }
        const endSet = () => {
            document.getElementById("sysMask").style.display = "none";
            document.body.removeEventListener("click", endSetEvent, true);
        }
        document.getElementById("closeSet").onclick = endSet;
        document.getElementById("sysSetting").onclick = () => {
            document.getElementById("sysMask").style.display = "flex";
            checkStorage();
            document.getElementById("sysMask").onmousedown = endSetEvent;
        };
        const setAutoTimer = () => {
            if (autoSendTime) {
                autoSendTimer = setTimeout(() => {
                    genFunc();
                    autoSendTimer = void 0;
                }, autoSendTime * 1000);
            }
        }
        const clearAutoSendTimer = () => {
            if (autoSendTimer !== void 0) {
                clearTimeout(autoSendTimer);
                autoSendTimer = void 0;
            }
        }
        if (!supportLocalRec) recServiceEle.remove(2);
        if (!supportOnlineRec) recServiceEle.remove(1);
        if (!supportOnlineLegacyRec) recServiceEle.remove(0);
        const initRecVal = () => {
            if (!supportRec) {
                noRecTip.style.display = "block"
                noRecTip.parentElement.firstElementChild.style.display = "none";
                noRecTip.parentElement.children[1].style.display = "none";
                return;
            }
            let localRecType = localStorage.getItem("existRec");
            recServiceEle.value = existRec = parseInt(localRecType || (supportLocalRec ? "1" : "2"));
        }
        initRecVal();
        const clearAzureRec = () => {
            azureRecKey = void 0;
            localStorage.removeItem(azureRecRegion + "RecData");
            azureRecData = void 0;
            azureRecRegion = void 0;
            azureRecKeyInput.parentElement.style.display = "none";
            preRecAzureRegion.parentElement.style.display = "none";
        }
        const featStreamRec = (hide) => {
            document.querySelectorAll('[data-feat="forStream"]').forEach(item => item.style.display = (hide ? "none" : "block"))
            document.querySelectorAll('[data-feat="forNoStream"]').forEach(item => item.style.display = (hide ? "block" : "none"))
        }
        let azureRecData, systemRecData, checkAzureRecAbort;
        const toggleRecCheck = (bool) => {
            checkRecLoad.style.display = bool ? "flex" : "none";
            recDetail.style.display = bool ? "none" : "block";
            hotKeyVoiceRec.parentElement.style.display = bool ? "none" : "block";
            document.getElementById("voiceRec").style.display = bool ? "none" : "block";
            if (bool) inputAreaEle.classList.remove("message_if_voice");
            else inputAreaEle.classList.add("message_if_voice");
        }
        recServiceEle.onchange = () => {
            if (!supportRec) return;
            existRec = parseInt(recServiceEle.value);
            localStorage.setItem("existRec", existRec);
            toggleRecCheck(true);
            if (checkAzureRecAbort && !checkAzureRecAbort.signal.aborted) {
                checkAzureRecAbort.abort();
                checkAzureRecAbort = void 0;
            }
            if (existRec === 3) {
                clearAzureRec();
                loadOpenAIRec();
                featStreamRec(true);
            } else if (existRec === 2) {
                azureRecKeyInput.parentElement.style.display = "block";
                preRecAzureRegion.parentElement.style.display = "block";
                loadAzureRec();
                featStreamRec();
            } else {
                clearAzureRec();
                loadLocalRec();
                featStreamRec();
            }
        }
        const loadLocalRec = () => { initRecSetting() };
        const loadOpenAIRec = () => { initRecSetting() };
        const loadAzureRec = () => {
            let checking = false;
            const checkAzureFunc = () => {
                if (checking) return;
                if (azureRecKey) {
                    checking = true;
                    checkRecLoad.classList.add("voiceChecking");
                    checkAzureRecAbort = new AbortController();
                    setTimeout(() => {
                        if (checkAzureRecAbort && !checkAzureRecAbort.signal.aborted) {
                            checkAzureRecAbort.abort();
                            checkAzureRecAbort = void 0;
                        }
                    }, 15000);
                    getAzureToken(checkAzureRecAbort.signal).then(() => {
                        getRecList(checkAzureRecAbort.signal).then(() => {
                            initRecSetting(azureRecData);
                        }).catch(e => {
                        }).finally(() => {
                            checkRecLoad.classList.remove("voiceChecking");
                            checking = false;
                        })
                    }).catch(e => {
                    }).finally(() => {
                        checkRecLoad.classList.remove("voiceChecking");
                        checking = false;
                    })
                }
            };
            checkRecLoad.onclick = checkAzureFunc;
            const getAzureToken = (signal) => {
                return new Promise((res, rej) => {
                    fetch("https://" + azureRecRegion + ".api.cognitive.microsoft.com/sts/v1.0/issueToken", {
                        signal,
                        method: "POST",
                        headers: {
                            "Ocp-Apim-Subscription-Key": azureRecKey
                        }
                    }).then(response => {
                        response.text().then(text => {
                            try {
                                let json = JSON.parse(text);
                                notyf.error(translations[locale]["azureInvalidTip"]);
                                rej();
                            } catch (e) {
                                res();
                            }
                        });
                    }).catch(e => {
                        localStorage.removeItem(azureRecRegion + "RecData");
                        azureRecData = void 0;
                        rej();
                    })
                })
            };
            const getRecList = (signal) => {
                return new Promise((res, rej) => {
                    if (azureRecData) res();
                    else {
                        let localAzureRecData = localStorage.getItem(azureRecRegion + "RecData");
                        if (localAzureRecData) {
                            azureRecData = JSON.parse(localAzureRecData);
                            res();
                        } else {
                            fetch("https://" + azureRecRegion + ".stt.speech.microsoft.com/api/v1.0/languages/recognition", {
                                signal
                            }).then(response => {
                                response.json().then(json => {
                                    azureRecData = json;
                                    localStorage.setItem(azureRecRegion + "RecData", JSON.stringify(json));
                                    res();
                                }).catch(e => {
                                    notyf.error(translations[locale]["azureInvalidTip"]);
                                    rej();
                                })
                            }).catch(e => {
                                localStorage.removeItem(azureRecRegion + "RecData");
                                azureRecData = void 0;
                                rej();
                            })
                        }
                    }
                })
            };
            let azureRecRegionEle = document.getElementById("preRecAzureRegion");
            if (!azureRecRegionEle.options.length) {
                azureRegions.forEach((region, i) => {
                    let option = document.createElement("option");
                    option.value = region;
                    option.text = region;
                    azureRecRegionEle.options.add(option);
                });
            }
            let localAzureRecRegion = localStorage.getItem("azureRecRegion");
            if (localAzureRecRegion) {
                azureRecRegion = localAzureRecRegion;
                azureRecRegionEle.value = localAzureRecRegion;
            }
            azureRecRegionEle.onchange = () => {
                azureRecRegion = azureRecRegionEle.value;
                localStorage.setItem("azureRecRegion", azureRecRegion);
                toggleRecCheck(true);
            }
            azureRecRegionEle.dispatchEvent(new Event("change"));
            let azureRecKeyEle = document.getElementById("azureRecKeyInput");
            let localAzureRecKey = localStorage.getItem("azureRecKey");
            if (localAzureRecKey) {
                azureRecKey = localAzureRecKey;
                azureRecKeyEle.value = localAzureRecKey;
            }
            azureRecKeyEle.onchange = () => {
                azureRecKey = azureRecKeyEle.value;
                localStorage.setItem("azureRecKey", azureRecKey);
                toggleRecCheck(true);
            }
            azureRecKeyEle.dispatchEvent(new Event("change"));
            if (azureRecKey) checkAzureFunc();
        }
        const azureLangTrans = { "en-au": "Australia", "en-ca": "Canada", "en-gb": "United Kingdom", "en-gh": "Ghana", "en-hk": "Hong Kong SAR", "en-ie": "Ireland", "en-in": "India", "en-ke": "Kenya", "en-ng": "Nigeria", "en-nz": "New Zealand", "en-ph": "Philippines", "en-sg": "Singapore", "en-tz": "Tanzania", "en-us": "United States", "en-za": "South Africa", "nan-cn": "闽南语，简体", "wuu-cn": "吴语，简体", "yue-cn": "粤语，简体", "zh-cn": "普通话，简体", "zh-cn-anhui": "安徽江淮普通话，简体", "zh-cn-bilingual": "普通话，英语双语", "zh-cn-gansu": "甘肃兰银普通话，简体", "zh-cn-guangxi": "广西口音普通话，简体", "zh-cn-henan": "中原官话河南，简体", "zh-cn-hunan": "湖南口音普通话，简体", "zh-cn-liaoning": "东北官话，简体", "zh-cn-shaanxi": "中原官话陕西，简体", "zh-cn-shandong": "冀鲁官话，简体", "zh-cn-shanxi": "山西口音普通话，简体", "zh-cn-sichuan": "西南官话，简体", "zh-hk": "粤语，繁体", "zh-sg": "简体，新加坡", "zh-tw": "台湾普通话" };
        const initRecSetting = (azureData) => {
            let langs = [['中文'], ['English']];
            if (azureData) {
                azureData.forEach(item => {
                    if (item.startsWith("en-")) {
                        let lowCase = item.toLowerCase();
                        let dialectName = azureLangTrans[lowCase] || lowCase;
                        if (lowCase == "en-us") langs[1].splice(1, 0, [lowCase, dialectName]);
                        else langs[1].push([lowCase, dialectName]);
                    } else if (item.indexOf("CN") != -1 || item.indexOf("zh") != -1) {
                        let lowCase = item.toLowerCase();
                        let dialectName = azureLangTrans[lowCase] || lowCase;
                        if (lowCase == "zh-cn") langs[0].splice(1, 0, [lowCase, dialectName]);
                        else langs[0].push([lowCase, dialectName]);
                    }
                })
            } else if (existRec === 3) {
                langs = [
                    ['自动检测', ['', '自动检测']],
                    ['中文', ['zh', '汉语']],
                    ['English', ['en', 'English']]
                ];
            } else {
                langs = [ // from https://www.google.com/intl/en/chrome/demos/speech.html
                    ['中文', ['cmn-Hans-CN', '普通话 (大陆)'],
                        ['cmn-Hans-HK', '普通话 (香港)'],
                        ['cmn-Hant-TW', '中文 (台灣)'],
                        ['yue-Hant-HK', '粵語 (香港)']],
                    ['English', ['en-US', 'United States'],
                        ['en-GB', 'United Kingdom'],
                        ['en-AU', 'Australia'],
                        ['en-CA', 'Canada'],
                        ['en-IN', 'India'],
                        ['en-KE', 'Kenya'],
                        ['en-TZ', 'Tanzania'],
                        ['en-GH', 'Ghana'],
                        ['en-NZ', 'New Zealand'],
                        ['en-NG', 'Nigeria'],
                        ['en-ZA', 'South Africa'],
                        ['en-PH', 'Philippines']]
                ];
            };
            toggleRecCheck(false);
            if (locale !== "zh") {
                if (existRec === 3) {
                    langs[0][0] = langs[0][1][1] = translations[locale]["autoWord"];
                    let idx = langs.findIndex((item) => { return item[1][0] === locale });
                    let [temp] = langs.splice(idx, 1);
                    langs.splice(1, 0, temp);
                } else langs = langs.reverse();
            }
            selectLangOption.options.length = select_language.options.length = 0;
            langs.forEach((lang, i) => {
                select_language.options.add(new Option(lang[0], i));
                selectLangOption.options.add(new Option(lang[0], i))
            });
            const updateCountry = function () {
                selectLangOption.selectedIndex = select_language.selectedIndex = this.selectedIndex;
                select_dialect.innerHTML = "";
                selectDiaOption.innerHTML = "";
                let list = langs[select_language.selectedIndex];
                for (let i = 1; i < list.length; i++) {
                    select_dialect.options.add(new Option(list[i][1], list[i][0]));
                    selectDiaOption.options.add(new Option(list[i][1], list[i][0]));
                }
                select_dialect.style.visibility = list[1].length == 1 ? "hidden" : "visible";
                selectDiaOption.parentElement.style.visibility = list[1].length == 1 ? "hidden" : "visible";
                localStorage.setItem("voiceRecLang", select_dialect.value);
            };
            let localLangIdx = 0;
            let localDiaIdx = 0;
            let localRecLang = localStorage.getItem("voiceRecLang") || langs[0][1][0];
            if (localRecLang) {
                let localIndex = langs.findIndex(item => {
                    let diaIdx = item.findIndex(lang => { return lang instanceof Array && lang[0] === localRecLang });
                    if (diaIdx !== -1) {
                        localDiaIdx = diaIdx - 1;
                        return true;
                    }
                    return false;
                });
                if (localIndex !== -1) localLangIdx = localIndex;
            }
            selectLangOption.onchange = updateCountry;
            select_language.onchange = updateCountry;
            selectDiaOption.onchange = select_dialect.onchange = function () {
                selectDiaOption.selectedIndex = select_dialect.selectedIndex = this.selectedIndex;
                localStorage.setItem("voiceRecLang", select_dialect.value);
            }
            selectLangOption.selectedIndex = select_language.selectedIndex = localLangIdx;
            select_language.dispatchEvent(new Event("change"));
            selectDiaOption.selectedIndex = select_dialect.selectedIndex = localDiaIdx;
            select_dialect.dispatchEvent(new Event("change"));
            initRecEvent();
        };
        let recSetTimer;
        let initRecFunc = () => {
            if (!supportRec) return;
            let localAutoSendWord = localStorage.getItem("autoVoiceSendWord");
            autoSendWord = autoSendText.value = localAutoSendWord || autoSendText.getAttribute("value") || "";
            autoSendText.onchange = () => {
                autoSendWord = autoSendText.value;
                localStorage.setItem("autoVoiceSendWord", autoSendWord);
            }
            autoSendText.dispatchEvent(new Event("change"));
            let localAutoStopWord = localStorage.getItem("autoVoiceStopWord");
            autoStopWord = autoStopText.value = localAutoStopWord || autoStopText.getAttribute("value") || "";
            autoStopText.onchange = () => {
                autoStopWord = autoStopText.value;
                localStorage.setItem("autoVoiceStopWord", autoStopWord);
            }
            autoStopText.dispatchEvent(new Event("change"));
            let outEle = document.getElementById("autoSendTimeout");
            let localTimeout = localStorage.getItem("autoVoiceSendOut");
            outEle.value = autoSendTime = parseInt(localTimeout || outEle.getAttribute("value"));
            outEle.oninput = () => {
                outEle.style.backgroundSize = (outEle.value - outEle.min) * 100 / (outEle.max - outEle.min) + "% 100%";
                autoSendTime = parseInt(outEle.value);
                localStorage.setItem("autoVoiceSendOut", outEle.value);
            }
            outEle.dispatchEvent(new Event("input"));
            outEle.onchange = () => {
                let hasAutoTimer = !!autoSendTimer;
                clearAutoSendTimer();
                if (hasAutoTimer) setAutoTimer();
            }
            const keepMicEle = document.getElementById("keepListenMic");
            let localKeepMic = localStorage.getItem("keepListenMic");
            keepMicEle.checked = keepListenMic = (localKeepMic || keepMicEle.getAttribute("checked")) === "true";
            keepMicEle.onchange = () => {
                keepListenMic = keepMicEle.checked;
                localStorage.setItem("keepListenMic", keepListenMic);
            }
            keepMicEle.dispatchEvent(new Event("change"));
            const closeEvent = (ev) => {
                if (voiceRecSetEle.contains(ev.target)) return;
                if (!voiceRecSetEle.contains(ev.target)) {
                    voiceRecSetEle.style.display = "none";
                    document.removeEventListener("mousedown", closeEvent, true);
                    voiceRecEle.classList.remove("voiceLong");
                }
            }
            const longEvent = () => {
                voiceRecSetEle.style.display = "block";
                document.addEventListener("mousedown", closeEvent, true);
            }
            const voiceDownEvent = (ev) => {
                ev.preventDefault();
                let i = 0;
                voiceRecEle.classList.add("voiceLong");
                recSetTimer = setInterval(() => {
                    i += 1;
                    if (i >= 3) {
                        clearInterval(recSetTimer);
                        recSetTimer = void 0;
                        longEvent();
                    }
                }, 100)
            }
            const voiceUpEvent = (ev) => {
                ev.preventDefault();
                if (recSetTimer !== void 0) {
                    toggleRecEv();
                    clearInterval(recSetTimer);
                    recSetTimer = void 0;
                    voiceRecEle.classList.remove("voiceLong");
                }
            }
            voiceRecEle.onmouseup = voiceUpEvent;
            voiceRecEle.ontouchend = voiceUpEvent;
            voiceRecEle.onmousedown = voiceDownEvent;
            voiceRecEle.ontouchstart = voiceDownEvent;
        }
        initRecFunc();
        class RiffPcmEncoder {
            constructor(actualSampleRate, desiredSampleRate) {
                this.privActualSampleRate = actualSampleRate;
                this.privDesiredSampleRate = desiredSampleRate;
            }
            encode(actualAudioFrame) {
                const audioFrame = this.downSampleAudioFrame(actualAudioFrame, this.privActualSampleRate, this.privDesiredSampleRate);
                if (!audioFrame) return null;
                const audioLength = audioFrame.length * 2;
                const buffer = new ArrayBuffer(audioLength);
                const view = new DataView(buffer);
                this.floatTo16BitPCM(view, 0, audioFrame);
                return buffer;
            }
            floatTo16BitPCM(view, offset, input) {
                for (let i = 0; i < input.length; i++, offset += 2) {
                    const s = Math.max(-1, Math.min(1, input[i]));
                    view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
                }
            }
            downSampleAudioFrame(srcFrame, srcRate, dstRate) {
                if (!srcFrame) return null;
                if (dstRate === srcRate || dstRate > srcRate) return srcFrame;
                const ratio = srcRate / dstRate;
                const dstLength = Math.round(srcFrame.length / ratio);
                const dstFrame = new Float32Array(dstLength);
                let srcOffset = 0;
                let dstOffset = 0;
                while (dstOffset < dstLength) {
                    const nextSrcOffset = Math.round((dstOffset + 1) * ratio);
                    let accum = 0;
                    let count = 0;
                    while (srcOffset < nextSrcOffset && srcOffset < srcFrame.length) {
                        accum += srcFrame[srcOffset++];
                        count++;
                    }
                    dstFrame[dstOffset++] = accum / count;
                }
                return dstFrame;
            }
        }
        let recSocket;
        class Recorder {
            constructor() {
                this.ready = false;
                this.connId = "";
                this.reqId = "";
                this.label = "";
                this.processScriptURL = "";
                this.forceStop = false;
                this.sampleRate = 16000;
                // avgBytesPerSec / 10, 0.1s
                this.bufferSize = this.sampleRate / 5;
                this.chunks = [];
                this.chunksByte = 0;
                // "Content-Type: audio/x-wav\r\n" + WAV header
                this.wavHeader = new Uint8Array([67, 111, 110, 116, 101, 110, 116, 45, 84, 121, 112, 101, 58, 32, 97, 117, 100, 105, 111, 47, 120, 45, 119, 97, 118, 13, 10, 82, 73, 70, 70, 0, 0, 0, 0, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0, 0, 0, 1, 0, 1, 0, 128, 62, 0, 0, 0, 125, 0, 0, 2, 0, 16, 0, 100, 97, 116, 97, 0, 0, 0, 0])
            }
            initRecorder() {
                return new Promise((res) => {
                    // microsoft cognitive-services-speech-sdk-js
                    this.context = navigator.mediaDevices.getSupportedConstraints().sampleRate ? new AudioContext({ sampleRate: this.sampleRate }) : new AudioContext();
                    this.audioInput = this.context.createMediaStreamSource(this.stream);
                    if (this.context.audioWorklet) {
                        if (this.processScriptURL == "") {
                            const workletScript = `${RiffPcmEncoder.toString()}
                            class SP extends AudioWorkletProcessor {
                            constructor(options) {
                                super(options);
                                this.sampleRate = ${this.sampleRate};
                                // avgBytesPerSec / 10, 0.1s
                                this.bufferSize = ${this.bufferSize};
                                this.encoder = new RiffPcmEncoder(options.processorOptions.sampleRate, this.sampleRate);
                                this.chunks = [];
                                this.chunksByte = 0;
                                this.processing = true;
                                this.port.onmessage = (e) => {
                                if (e.data === "stop") {
                                    this.processing = false;
                                    this.port.close();
                                }
                                }
                            }
                            concat() {
                                let result = new Uint8Array(this.bufferSize);
                                let offset = 0;
                                for (let i = 0; i < this.chunks.length; i++) {
                                result.set(this.chunks[i], offset);
                                offset += this.chunks[i].byteLength;
                                }
                                return result;
                            }
                            process(inputs) {
                                if (inputs[0][0]) {
                                let data = new Uint8Array(this.encoder.encode(inputs[0][0]));
                                this.chunks.push(data);
                                this.chunksByte += data.byteLength;
                                if (this.chunksByte > this.bufferSize) {
                                    let lastChunk = this.chunks[this.chunks.length - 1];
                                    this.chunks[this.chunks.length - 1] = lastChunk.subarray(0, lastChunk.byteLength - this.chunksByte + this.bufferSize);
                                    let chunk = this.concat();
                                    this.port.postMessage(chunk, [chunk.buffer]);
                                    this.chunks.length = 0;
                                    this.chunks.push(lastChunk.subarray(lastChunk.byteLength - this.chunksByte + this.bufferSize));
                                    this.chunksByte = this.chunks[0].byteLength;
                                } else if (this.chunksByte === this.bufferSize) {
                                    let chunk = this.concat();
                                    this.port.postMessage(chunk, [chunk.buffer]);
                                    this.chunks.length = this.chunksByte = 0;
                                }
                                }
                                return this.processing;
                            }
                            }
                            registerProcessor('speech-processor', SP);`;
                            this.processScriptURL = URL.createObjectURL(new Blob([workletScript], { type: "application/javascript; charset=utf-8" }));
                        }
                        this.context.audioWorklet.addModule(this.processScriptURL).then(() => {
                            this.recorder = new AudioWorkletNode(this.context, "speech-processor", {
                                processorOptions: { sampleRate: this.context.sampleRate }
                            });
                            this.ready = true;
                            this.recorder.port.onmessage = (e) => { if (e.data && this.ready) recSocket.send(this.getRecBin(e.data)) };
                            if (isFirefox) { // tested firefox need volume gain
                                this.gain = this.context.createGain();
                                this.gain.gain.value = 3;
                                this.audioInput.connect(this.gain);
                                this.gain.connect(this.recorder);
                            } else this.audioInput.connect(this.recorder);
                            this.recorder.connect(this.context.destination);
                            res();
                        }).catch(e => { this.attachScriptProcessor(res) })
                    } else this.attachScriptProcessor(res);
                })
            }
            attachScriptProcessor(res) {
                this.encoder = new RiffPcmEncoder(this.context.sampleRate, this.sampleRate);
                this.recorder = (() => {
                    let bufferSize = 0;
                    try {
                        return this.context.createScriptProcessor(bufferSize, 1, 1);
                    } catch (error) {
                        // Webkit (<= version 31) requires a valid bufferSize.
                        bufferSize = 2048;
                        let audioSampleRate = this.context.sampleRate;
                        while (bufferSize < 16384 && audioSampleRate >= (this.audioInput.channelCount * this.sampleRate)) {
                            bufferSize <<= 1;
                            audioSampleRate >>= 1;
                        }
                        return this.context.createScriptProcessor(bufferSize, 1, 1);
                    }
                })();
                this.ready = true;
                this.recorder.onaudioprocess = (event) => {
                    const inputFrame = event.inputBuffer.getChannelData(0);
                    if (inputFrame && this.ready) this.pushWSFrame(new Uint8Array(this.encoder.encode(inputFrame)));
                };
                if (isFirefox) { // tested firefox need volume gain
                    this.gain = this.context.createGain();
                    this.gain.gain.value = 3;
                    this.audioInput.connect(this.gain);
                    this.gain.connect(this.recorder);
                } else this.audioInput.connect(this.recorder);
                this.recorder.connect(this.context.destination);
                res();
            }
            pushWSFrame(audio) {
                let totalByte = this.chunksByte + audio.byteLength;
                if (totalByte >= this.bufferSize) {
                    let offset = 0;
                    for (let i = 0; i < Math.floor(totalByte / this.bufferSize); i++) {
                        if (this.chunksByte) {
                            let partAudio = audio.subarray(offset, (i + 1) * this.bufferSize - this.chunksByte);
                            this.chunks.push(partAudio);
                            let chunk = this.concat();
                            recSocket.send(this.getRecBin(chunk));
                            offset = (i + 1) * this.bufferSize - this.chunksByte;
                            this.chunks.length = this.chunksByte = 0;
                        } else {
                            let partAudio = audio.subarray(offset, offset + this.bufferSize);
                            recSocket.send(this.getRecBin(partAudio));
                            offset += this.bufferSize;
                        }
                    }
                    if (offset < audio.byteLength) {
                        this.chunks.push(audio.subarray(offset));
                        this.chunksByte = this.chunks[0].byteLength;
                    }
                } else {
                    this.chunks.push(audio);
                    this.chunksByte += audio.byteLength;
                }
            }
            concat() {
                let result = new Uint8Array(this.bufferSize);
                let offset = 0;
                for (let i = 0; i < this.chunks.length; i++) {
                    result.set(this.chunks[i], offset);
                    offset += this.chunks[i].byteLength;
                }
                return result;
            }
            initRecWebsocket() {
                return new Promise((res, rej) => {
                    let url = `wss://${azureRecRegion}.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?Ocp-Apim-Subscription-Key=${azureRecKey}&language=${select_dialect.value}&storeAudio=true`;
                    if (!recSocket || recSocket.readyState > 1 || recSocket.url.slice(0, -48) !== url) {
                        if (recSocket && recSocket.readyState === 1) recSocket.close(1000);
                        recSocket = new WebSocket(url + `&X-ConnectionId=${this.connId}`);
                        recSocket.binaryType = "arraybuffer";
                        recSocket.onopen = () => { res() };
                        recSocket.onmessage = (e) => { this.handleWSMsg(e) };
                        recSocket.onerror = (e) => {
                            if (!this.ready) notyf.error(translations[locale]["badGateTip"]);
                            recSocket.close();
                            rej();
                        };
                        recSocket.onclose = (e) => {
                            if (this.ready) {
                                this.ready = false;
                                this.retryWebsocket(recSocket.url)
                            }
                        }
                    } else {
                        return res()
                    }
                })
            }
            retryWebsocket(url) {
                recSocket = new WebSocket(url);
                recSocket.binaryType = "arraybuffer";
                recSocket.onopen = () => {
                    this.startWSDetect();
                    this.ready = true;
                }
                recSocket.onmessage = (e) => { this.handleWSMsg(e) };
                recSocket.onerror = (e) => { recSocket.close() };
                recSocket.onclose = (e) => {
                    notyf.error(translations[locale]["badGateTip"]);
                    this.stopRecorder(true);
                }
            }
            handleWSMsg(e) {
                if (typeof e.data === "string") {
                    let path = e.data.match(/Path:(.+)/)[1].trim();
                    let splitData = e.data.split("\n");
                    if (this.ready && (path === "speech.phrase" || path === "speech.hypothesis")) {
                        let data = JSON.parse(splitData[splitData.length - 1]);
                        let isFinal = data.DisplayText !== void 0;
                        let autoFlag;
                        if (isFinal) {
                            recRes += data.DisplayText;
                            if (autoSendWord) {
                                let idx = recRes.indexOf(autoSendWord);
                                if (idx !== -1) {
                                    recRes = recRes.slice(0, idx);
                                    autoFlag = 1;
                                }
                            }
                            if (autoStopWord) {
                                let idx = recRes.indexOf(autoStopWord);
                                if (idx !== -1) {
                                    recRes = recRes.slice(0, idx);
                                    autoFlag = 2;
                                }
                            }
                        }
                        else if (data.Text) { tempRes = recRes + data.Text }
                        inputAreaEle.value = preRes + (isFinal ? recRes : tempRes) + affRes;
                        textInputEvent();
                        inputAreaEle.focus();
                        inputAreaEle.selectionEnd = inputAreaEle.value.length - affRes.length;
                        if (autoFlag) {
                            if (autoFlag === 1) genFunc();
                            else this.stopRecorder(true);
                        }
                        clearAutoSendTimer();
                        if (autoFlag !== 1) setAutoTimer();
                    } else if (path === "turn.end") {
                        if (!this.forceStop && keepListenMic || this.ready) {
                            this.startWSDetect();
                            this.ready = true;
                        }
                    }
                }
            }
            startWSDetect() {
                this.reqId = uuidv4(true);
                recSocket.send(this.getRecPre(this.label));
                recSocket.send(this.getRecConfig());
                recSocket.send(this.getRecPreBin());
            }
            getRecPre(label) {
                let osPlatform = (typeof window !== "undefined") ? "Browser" : "Node";
                osPlatform += "/" + navigator.platform;
                let osName = navigator.userAgent;
                let osVersion = navigator.appVersion;
                return `Path: speech.config\r\nX-RequestId: ${this.reqId}\r\nX-Timestamp: ${new Date().toISOString()}\r\nContent-Type: application/json\r\n\r\n{"context":{"system":{"name":"SpeechSDK","version":"1.35.0","build":"JavaScript","lang":"JavaScript"},"os":{"platform":"${osPlatform}","name":"${osName}","version":"${osVersion}"},"audio":{"source":{"bitspersample":16,"channelcount":1,"connectivity":"Unknown","manufacturer":"Speech SDK","model":"${label}","samplerate":${this.sampleRate},"type":"Microphones"}}},"recognition":"conversation"}`
            }
            getRecConfig() {
                return `Path: speech.context\r\nX-RequestId: ${this.reqId}\r\nX-Timestamp: ${new Date().toISOString()}\r\nContent-Type: application/json\r\n\r\n{"phraseDetection":{}}`
            }
            getRecPreBin() {
                let header = this.getRecHeader();
                let data = new Uint8Array(2 + header.length + this.wavHeader.byteLength);
                data.set([0, 126], 0);
                data.set(stringToArray(header), 2);
                data.set(this.wavHeader, 2 + header.length);
                return data
            }
            getRecBin(audio) {
                let header = this.getRecHeader();
                let data = new Uint8Array(2 + header.length + audio.byteLength);
                data.set([0, 99], 0);
                data.set(stringToArray(header), 2);
                data.set(audio, 2 + header.length);
                return data
            }
            getRecHeader() {
                return `Path: audio\r\nX-RequestId: ${this.reqId}\r\nX-Timestamp: ${new Date().toISOString()}\r\n`
            }
            getMedia() {
                return new Promise((res, rej) => {
                    navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
                        this.stream = stream;
                        res();
                    }).catch(e => {
                        notyf.error(translations[locale][e.name === "NotAllowedError" ? "noMicPerTip" : "noMicTip"]);
                        rej();
                    })
                })
            }
            async startRecorder() {
                return new Promise((res, rej) => {
                    this.connId = uuidv4(true);
                    Promise.all([this.getMedia(), this.initRecWebsocket()]).then((val) => {
                        this.label = this.stream.getAudioTracks()[0].label;
                        this.startWSDetect();
                        this.initRecorder().then(() => { res() });
                    }).catch(e => {
                        if (this.stream) {
                            this.stream.getAudioTracks().forEach(track => { track.stop() });
                            this.stream = null;
                        }
                        rej(e);
                    })
                })
            }
            stopRecWebsocket() {
                if (recSocket && recSocket.readyState === 1) {
                    let endBin = this.getRecBin(new Uint8Array());
                    recSocket.send(endBin);
                    recSocket.send(endBin);
                }
            }
            stopRecorder(forceStop) {
                this.forceStop = forceStop;
                this.ready = false;
                this.stopRecWebsocket();
                clearAutoSendTimer();
                if (!forceStop && keepListenMic) return;
                voiceRecEle.classList.remove("voiceRecing");
                recing = false;
                if (this.recorder && this.recorder.port) {
                    this.recorder.port.postMessage("stop");
                    this.recorder.port.close();
                }
                if (this.stream) {
                    this.stream.getAudioTracks().forEach(track => { track.stop() });
                    this.stream = null;
                }
                if (this.audioInput) {
                    this.audioInput.disconnect();
                    this.audioInput = null;
                }
                if (isFirefox && this.gain) {
                    this.gain.disconnect();
                    this.gain = null;
                }
                if (this.recorder) {
                    this.recorder.disconnect();
                    this.recorder = null;
                }
                if (this.context) {
                    this.context.close();
                    this.context = null;
                }
            }
        }
        class LegacyRecorder {
            constructor() {
                this.mimeType = MediaRecorder.isTypeSupported("audio/mp4") ? "audio/mp4" : "audio/webm";
                this.suffix = this.mimeType === "audio/mp4" ? ".mp4" : ".webm";
                this.bitsPerSecond = 128000;
                this.chunks = [];
            }
            initRecorder() {
                this.recorder = new MediaRecorder(this.stream, { mimeType: this.mimeType, audioBitsPerSecond: this.bitsPerSecond });
                this.chunks.length = 0;
                this.recorder.ondataavailable = e => { this.chunks.push(e.data) };
                this.recorder.start(1e3);
            }
            async processData(blob) {
                let formData = new FormData();
                formData.append("model", "whisper-1");
                formData.append("file", blob, "audio" + this.suffix);
                if (select_dialect.value !== "") formData.append("language", select_dialect.value);
                let url = apiHost + ((apiHost.length && !apiHost.endsWith("/")) ? "/" : "") + "v1/audio/transcriptions";
                let controller = new AbortController();
                let controllerId = setTimeout(() => {
                    notyf.error(translations[locale]["timeoutTip"]);
                    controller.abort();
                }, 15000);
                try {
                    const res = await fetch(url, {
                        method: "POST",
                        body: formData,
                        signal: controller.signal,
                        ...(customAPIKey ? { headers: { Authorization: "Bearer " + customAPIKey } } : {})
                    });
                    clearTimeout(controllerId);
                    if (res.status === 200) {
                        let result = await res.json();
                        if (result && result.text) {
                            inputAreaEle.value = preRes + result.text + affRes;
                            textInputEvent();
                            inputAreaEle.focus();
                            inputAreaEle.selectionEnd = inputAreaEle.value.length - affRes.length;
                            return true;
                        }
                    } else notyf.open({ type: "warning", message: translations[locale]["cantTranscribeTip"] });
                } catch (e) { }
            }
            getMedia() {
                return new Promise((res, rej) => {
                    navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
                        this.stream = stream;
                        res();
                    }).catch(e => {
                        notyf.error(translations[locale][e.name === "NotAllowedError" ? "noMicPerTip" : "noMicTip"]);
                        rej(e);
                    })
                })
            }
            async startRecorder() {
                return new Promise((res, rej) => {
                    this.getMedia().then(() => {
                        this.initRecorder();
                        res();
                    }).catch(e => { rej(e) })
                })
            }
            stopRecorder(forceStop) {
                return new Promise((res, rej) => {
                    clearAutoSendTimer();
                    if (this.recorder && this.recorder.state === "recording") {
                        this.recorder.onstop = async (e) => {
                            let blob = new Blob(this.chunks, { type: this.mimeType });
                            this.chunks.length = 0;
                            try {
                                let result = await this.processData(blob);
                                if (result) res();
                                else rej();
                            } catch (error) { rej() };
                            if (!forceStop && keepListenMic) this.recorder.start(1e3);
                        };
                        this.recorder.stop();
                    } else res();
                    if (!forceStop && keepListenMic) return;
                    voiceRecEle.classList.remove("voiceRecing");
                    recing = false;
                    if (this.recorder) this.recorder = null;
                    if (this.stream) {
                        this.stream.getAudioTracks().forEach(track => { track.stop() });
                        this.stream = null;
                    }
                })
            }
        }
        let recorder, legacyRecorder, initingRecorder;
        let recRes = tempRes = "";
        let preRes, affRes;
        resetRecRes = () => {
            preRes = inputAreaEle.value.slice(0, inputAreaEle.selectionStart);
            affRes = inputAreaEle.value.slice(inputAreaEle.selectionEnd);
            recRes = tempRes = "";
        }
        const initRecEvent = () => {
            if (existRec === 3) {
                if (legacyRecorder === void 0) legacyRecorder = new LegacyRecorder();
                toggleRecEv = async (force = true) => {
                    if (voiceRecEle.classList.contains("voiceRecing")) await legacyRecorder.stopRecorder(force);
                    else {
                        if (initingRecorder) return;
                        resetRecRes();
                        initingRecorder = true;
                        legacyRecorder.startRecorder().then(() => {
                            recing = true;
                            initingRecorder = false;
                            voiceRecEle.classList.add("voiceRecing");
                        }).catch(e => {
                            legacyRecorder.stopRecorder(force);
                            initingRecorder = false;
                        })
                    }
                }
            } else if (existRec === 2) {
                if (recorder === void 0) recorder = new Recorder();
                toggleRecEv = (force = true) => {
                    if (voiceRecEle.classList.contains("voiceRecing")) recorder.stopRecorder(force);
                    else {
                        if (initingRecorder) return;
                        resetRecRes();
                        initingRecorder = true;
                        recorder.startRecorder().then(() => {
                            recing = true;
                            initingRecorder = false;
                            voiceRecEle.classList.add("voiceRecing");
                        }).catch(e => {
                            recorder.stopRecorder(force)
                            initingRecorder = false;
                        })
                    }
                }
            } else {
                let recIns = new webkitSpeechRecognition();
                // prevent some Android bug
                recIns.continuous = !isAndroid;
                recIns.interimResults = true;
                recIns.maxAlternatives = 1;
                let resEvent = (event) => {
                    if (typeof (event.results) === "undefined") {
                        toggleRecEv();
                        return;
                    }
                    let isFinal;
                    let autoFlag;
                    for (let i = event.resultIndex; i < event.results.length; ++i) {
                        isFinal = event.results[i].isFinal;
                        if (isFinal) {
                            recRes += event.results[i][0].transcript
                            if (autoSendWord) {
                                let idx = recRes.indexOf(autoSendWord);
                                if (idx !== -1) {
                                    recRes = recRes.slice(0, idx);
                                    autoFlag = 1;
                                    break;
                                }
                            }
                            if (autoStopWord) {
                                let idx = recRes.indexOf(autoStopWord);
                                if (idx !== -1) {
                                    recRes = recRes.slice(0, idx);
                                    autoFlag = 2;
                                    break;
                                }
                            }
                        }
                        else { tempRes = recRes + event.results[i][0].transcript }
                    }
                    inputAreaEle.value = preRes + (isFinal ? recRes : tempRes) + affRes;
                    textInputEvent();
                    inputAreaEle.focus();
                    inputAreaEle.selectionEnd = inputAreaEle.value.length - affRes.length;
                    if (autoFlag) {
                        if (autoFlag === 1) genFunc();
                        else endEvent(false, false);
                    }
                    clearAutoSendTimer();
                    if (autoFlag !== 1) setAutoTimer();
                };
                const stopAction = () => {
                    clearAutoSendTimer();
                    recIns.onresult = null;
                    recIns.onerror = null;
                    recIns.onend = null;
                    voiceRecEle.classList.remove("voiceRecing");
                    recing = false;
                };
                const endEvent = (event, flag) => {
                    if (flag !== void 0) {
                        if (!flag) {
                            recIns.stop();
                            stopAction();
                        }
                    } else if (event) {
                        if (keepListenMic && event.type === "end") {
                            recIns.start();
                            resetRecRes();
                        } else {
                            if (event.type === "error") recIns.stop();
                            stopAction();
                        }
                    }
                };
                const errorEvent = (ev) => {
                    if (event.error === "no-speech") {
                        notyf.open({
                            type: "warning",
                            message: translations[locale]["noSpeechTip"]
                        });
                    }
                    if (event.error === "audio-capture") {
                        notyf.error(translations[locale]["noMicTip"])
                        endEvent(ev);
                    }
                    if (event.error === "not-allowed") {
                        notyf.error(translations[locale]["noMicPerTip"])
                        endEvent(ev);
                    }
                };
                toggleRecEv = () => {
                    if (voiceRecEle.classList.toggle("voiceRecing")) {
                        try {
                            resetRecRes();
                            recIns.lang = select_dialect.value;
                            recIns.start();
                            recIns.onresult = resEvent;
                            recIns.onerror = errorEvent;
                            recIns.onend = endEvent;
                            recing = true;
                        } catch (e) {
                            endEvent(false, false);
                        }
                    } else {
                        endEvent(false, false);
                    }
                };
            }
        }
        recServiceEle.dispatchEvent(new Event("change"));
        document.querySelector(".modelSwitch").onclick = document.querySelector(".sysSwitch").onclick = document.querySelector(".setSwitch").onclick = function (ev) {
            let activeEle = this.getElementsByClassName("activeSwitch")[0];
            if (ev.target !== activeEle) {
                activeEle.classList.remove("activeSwitch");
                ev.target.classList.add("activeSwitch");
                document.getElementById(ev.target.dataset.id).style.display = "block";
                document.getElementById(activeEle.dataset.id).style.display = "none";
            }
        };
        if (!supportSpe) speechServiceEle.remove(3);
        const initVoiceVal = () => {
            let localVoiceType = localStorage.getItem("existVoice");
            speechServiceEle.value = existVoice = parseInt(localVoiceType || "2");
        }
        initVoiceVal();
        const clearAzureVoice = () => {
            azureKey = void 0;
            localStorage.removeItem(azureRegion + "VoiceData");
            azureRegion = void 0;
            azureRole = [];
            azureStyle = [];
            document.getElementById("azureExtra").style.display = "none";
            azureKeyInput.parentElement.style.display = "none";
            preSetAzureRegion.parentElement.style.display = "none";
        }
        speechServiceEle.onchange = () => {
            existVoice = parseInt(speechServiceEle.value);
            localStorage.setItem("existVoice", existVoice);
            toggleVoiceCheck(true);
            if (checkAzureAbort && !checkAzureAbort.signal.aborted) {
                checkAzureAbort.abort();
                checkAzureAbort = void 0;
            }
            if (checkEdgeAbort && !checkEdgeAbort.signal.aborted) {
                checkEdgeAbort.abort();
                checkEdgeAbort = void 0;
            }
            if (existVoice === 4) {
                toggleVoiceCheck(false);
                clearAzureVoice();
                loadOpenAIVoice();
            } else if (existVoice === 3) {
                azureKeyInput.parentElement.style.display = "block";
                preSetAzureRegion.parentElement.style.display = "block";
                loadAzureVoice();
            } else if (existVoice === 2) {
                clearAzureVoice();
                loadEdgeVoice();
            } else if (existVoice === 1) {
                toggleVoiceCheck(false);
                clearAzureVoice();
                loadLocalVoice();
            }
        }
        let openaiVoiceData, edgeVoiceData, systemVoiceData, checkAzureAbort, checkEdgeAbort;
        const toggleVoiceCheck = (bool) => {
            checkVoiceLoad.style.display = bool ? "flex" : "none";
            speechDetail.style.display = bool ? "none" : "block";
        }
        const loadOpenAIVoice = () => {
            if (openaiVoiceData) {
                initVoiceSetting(openaiVoiceData);
            } else {
                openaiVoiceData = [{ name: "alloy", displayName: "alloy" }, { name: "echo", displayName: "echo" }, { name: "fable", displayName: "fable" }, { name: "onyx", displayName: "onyx" }, { name: "nova", displayName: "nova" }, { name: "shimmer", displayName: "shimmer" }]
                initVoiceSetting(openaiVoiceData);
            }
        };
        const loadAzureVoice = () => {
            let checking = false;
            const checkAzureFunc = () => {
                if (checking) return;
                if (azureKey) {
                    checking = true;
                    checkVoiceLoad.classList.add("voiceChecking");
                    checkAzureAbort = new AbortController();
                    setTimeout(() => {
                        if (checkAzureAbort && !checkAzureAbort.signal.aborted) {
                            checkAzureAbort.abort();
                            checkAzureAbort = void 0;
                        }
                    }, 15000);
                    getAzureToken(checkAzureAbort.signal).then(() => {
                        getVoiceList(checkAzureAbort.signal).then(() => {
                            toggleVoiceCheck(false);
                        }).catch(e => {
                        }).finally(() => {
                            checkVoiceLoad.classList.remove("voiceChecking");
                            checking = false;
                        })
                    }).catch(e => {
                    }).finally(() => {
                        checkVoiceLoad.classList.remove("voiceChecking");
                        checking = false;
                    })
                }
            };
            checkVoiceLoad.onclick = checkAzureFunc;
            const getAzureToken = (signal) => {
                return new Promise((res, rej) => {
                    fetch("https://" + azureRegion + ".api.cognitive.microsoft.com/sts/v1.0/issueToken", {
                        signal,
                        method: "POST",
                        headers: {
                            "Ocp-Apim-Subscription-Key": azureKey
                        }
                    }).then(response => {
                        response.text().then(text => {
                            try {
                                let json = JSON.parse(text);
                                notyf.error(translations[locale]["azureInvalidTip"]);
                                rej();
                            } catch (e) {
                                res();
                            }
                        });
                    }).catch(e => {
                        localStorage.removeItem(azureRegion + "VoiceData");
                        rej();
                    })
                })
            };
            const getVoiceList = (signal) => {
                return new Promise((res, rej) => {
                    let localAzureVoiceData = localStorage.getItem(azureRegion + "VoiceData");
                    if (localAzureVoiceData) {
                        initVoiceSetting(JSON.parse(localAzureVoiceData));
                        res();
                    } else {
                        fetch("https://" + azureRegion + ".tts.speech.microsoft.com/cognitiveservices/voices/list", {
                            signal,
                            headers: {
                                "Ocp-Apim-Subscription-Key": azureKey
                            }
                        }).then(response => {
                            response.json().then(json => {
                                localStorage.setItem(azureRegion + "VoiceData", JSON.stringify(json));
                                initVoiceSetting(json);
                                res();
                            }).catch(e => {
                                notyf.error(translations[locale]["azureInvalidTip"]);
                                rej();
                            })
                        }).catch(e => {
                            localStorage.removeItem(azureRegion + "VoiceData");
                            rej();
                        })
                    }
                })
            };
            let azureRegionEle = document.getElementById("preSetAzureRegion");
            if (!azureRegionEle.options.length) {
                azureRegions.forEach((region, i) => {
                    let option = document.createElement("option");
                    option.value = region;
                    option.text = region;
                    azureRegionEle.options.add(option);
                });
            }
            let localAzureRegion = localStorage.getItem("azureRegion");
            if (localAzureRegion) {
                azureRegion = localAzureRegion;
                azureRegionEle.value = localAzureRegion;
            }
            azureRegionEle.onchange = () => {
                azureRegion = azureRegionEle.value;
                localStorage.setItem("azureRegion", azureRegion);
                toggleVoiceCheck(true);
            }
            azureRegionEle.dispatchEvent(new Event("change"));
            let azureKeyEle = document.getElementById("azureKeyInput");
            let localAzureKey = localStorage.getItem("azureKey");
            if (localAzureKey) {
                azureKey = localAzureKey;
                azureKeyEle.value = localAzureKey;
            }
            azureKeyEle.onchange = () => {
                azureKey = azureKeyEle.value;
                localStorage.setItem("azureKey", azureKey);
                toggleVoiceCheck(true);
            }
            azureKeyEle.dispatchEvent(new Event("change"));
            if (azureKey) {
                checkAzureFunc();
            }
        }
        const loadEdgeVoice = () => {
            let checking = false;
            const endCheck = () => {
                checkVoiceLoad.classList.remove("voiceChecking");
                checking = false;
            };
            const checkEdgeFunc = () => {
                if (checking) return;
                checking = true;
                checkVoiceLoad.classList.add("voiceChecking");
                if (edgeVoiceData) {
                    initVoiceSetting(edgeVoiceData);
                    toggleVoiceCheck(false);
                    endCheck();
                } else {
                    checkEdgeAbort = new AbortController();
                    setTimeout(() => {
                        if (checkEdgeAbort && !checkEdgeAbort.signal.aborted) {
                            checkEdgeAbort.abort();
                            checkEdgeAbort = void 0;
                        }
                    }, 10000);
                    fetch("https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list?trustedclienttoken=6A5AA1D4EAFF4E9FB37E23D68491D6F4", { signal: checkEdgeAbort.signal }).then(response => {
                        response.json().then(json => {
                            edgeVoiceData = json;
                            toggleVoiceCheck(false);
                            initVoiceSetting(json);
                            endCheck();
                        });
                    }).catch(err => {
                        endCheck();
                    })
                }
            };
            checkEdgeFunc();
            checkVoiceLoad.onclick = checkEdgeFunc;
        };
        const loadLocalVoice = () => {
            if (systemVoiceData) {
                initVoiceSetting(systemVoiceData);
            } else {
                let initedVoice = false;
                const getLocalVoice = () => {
                    let voices = speechSynthesis.getVoices();
                    if (voices.length) {
                        if (!initedVoice) {
                            initedVoice = true;
                            systemVoiceData = voices;
                            initVoiceSetting(voices);
                        }
                        return true;
                    } else {
                        return false;
                    }
                }
                let syncExist = getLocalVoice();
                if (!syncExist) {
                    if ("onvoiceschanged" in speechSynthesis) {
                        speechSynthesis.onvoiceschanged = () => {
                            getLocalVoice();
                        }
                    } else if (speechSynthesis.addEventListener) {
                        speechSynthesis.addEventListener("voiceschanged", () => {
                            getLocalVoice();
                        })
                    }
                    let timeout = 0;
                    let timer = setInterval(() => {
                        if (getLocalVoice() || timeout > 1000) {
                            if (timeout > 1000) {
                                existVoice = 0;
                            }
                            clearInterval(timer);
                            timer = null;
                        }
                        timeout += 300;
                    }, 300)
                }
            }
        };
        const voicesEle = document.getElementById("preSetSpeech");
        const initVoiceSetting = (voices) => {
            if (existVoice < 4) {
                let isOnline = existVoice === 2 || existVoice === 3;
                // 支持中文和英文
                voices = isOnline ? voices.filter(item => item.Locale.match(/^(zh-|en-)/)) : voices.filter(item => item.lang.match(/^(zh-|en-)/));
                if (isOnline) {
                    voices.map(item => {
                        item.name = item.FriendlyName || (`${item.DisplayName} Online (${item.VoiceType}) - ${item.LocaleName}`);
                        item.lang = item.Locale;
                    })
                } else if (isSafari && voices[0].voiceURI.startsWith("com.apple")) {
                    voices = voices.filter(item => {
                        return !item.voiceURI.startsWith("com.apple.voice.super-compact")
                    })
                }
                voices.sort((a, b) => {
                    if (a.lang.slice(0, 2) === b.lang.slice(0, 2)) {
                        if (a.lang.slice(0, 2) === "zh") {
                            return (a.lang === b.lang) ? 0 : (a.lang > b.lang) ? 1 : -1; // zh-CN 在前
                        } else {
                            return 0
                        }
                    }
                    return (locale === "zh" ? (a.lang < b.lang) : (a.lang > b.lang)) ? 1 : -1; // 中文UI，则中文"z"在前
                });
                voices.map(item => {
                    if (item.name.match(/^(Google |Microsoft )/)) {
                        item.displayName = item.name.replace(/^.*? /, "");
                    } else {
                        item.displayName = item.name;
                    }
                });
                if (isSafari && !isOnline) {
                    voices.map(item => { item.displayName = `${item.name} (${item.lang})` });
                };
            };
            voicesData = voices;
            voicesEle.innerHTML = "";
            voices.forEach((voice, i) => {
                let option = document.createElement("option");
                option.value = i;
                option.text = voice.displayName;
                voicesEle.options.add(option);
            });
            const loadAnother = (type) => {
                type = type ^ 1;
                let localVoice = localStorage.getItem("voice" + type);
                if (localVoice) {
                    let localIndex = voices.findIndex(item => { return item.name === localVoice });
                    if (localIndex === -1) localIndex = 0;
                    voiceRole[type] = voices[localIndex];
                } else {
                    voiceRole[type] = voices[0];
                }
                if (existVoice === 3) {
                    let localStyle = localStorage.getItem("azureStyle" + type);
                    azureStyle[type] = localStyle ? localStyle : void 0;
                    let localRole = localStorage.getItem("azureRole" + type);
                    azureRole[type] = localRole ? localRole : void 0;
                }
            }
            voiceChange();
            loadAnother(voiceType);
        };
        let voiceChange;
        const initVoiceFunc = () => {
            voicesEle.onchange = () => {
                voiceRole[voiceType] = voicesData[voicesEle.value];
                localStorage.setItem("voice" + voiceType, voiceRole[voiceType].name);
                if (voiceRole[voiceType].StyleList || voiceRole[voiceType].RolePlayList) {
                    document.getElementById("azureExtra").style.display = "block";
                    let voiceStyles = voiceRole[voiceType].StyleList;
                    let voiceRoles = voiceRole[voiceType].RolePlayList;
                    if (voiceRoles) {
                        preSetVoiceRole.innerHTML = "";
                        let option = document.createElement("option");
                        option.value = "Default";
                        option.text = "Default";
                        preSetVoiceRole.options.add(option);
                        voiceRoles.forEach((role, i) => {
                            let option = document.createElement("option");
                            option.value = role;
                            option.text = role;
                            preSetVoiceRole.options.add(option);
                        });
                        let localRole = localStorage.getItem("azureRole" + voiceType);
                        if (localRole && voiceRoles.indexOf(localRole) !== -1) {
                            preSetVoiceRole.value = localRole;
                            azureRole[voiceType] = localRole;
                        } else {
                            preSetVoiceRole.selectedIndex = 0;
                            azureRole[voiceType] = voiceRole[0];
                        }
                        preSetVoiceRole.onchange = () => {
                            azureRole[voiceType] = preSetVoiceRole.value;
                            localStorage.setItem("azureRole" + voiceType, preSetVoiceRole.value);
                        }
                        preSetVoiceRole.dispatchEvent(new Event("change"));
                    } else {
                        azureRole[voiceType] = void 0;
                        localStorage.removeItem("azureRole" + voiceType);
                    }
                    preSetVoiceRole.style.display = voiceRoles ? "block" : "none";
                    preSetVoiceRole.previousElementSibling.style.display = voiceRoles ? "block" : "none";
                    if (voiceStyles) {
                        preSetVoiceStyle.innerHTML = "";
                        let option = document.createElement("option");
                        option.value = "Default";
                        option.text = "Default";
                        preSetVoiceStyle.options.add(option);
                        voiceStyles.forEach((style, i) => {
                            let option = document.createElement("option");
                            option.value = style;
                            option.text = style;
                            preSetVoiceStyle.options.add(option);
                        });
                        let localStyle = localStorage.getItem("azureStyle" + voiceType);
                        if (localStyle && voiceStyles.indexOf(localStyle) !== -1) {
                            preSetVoiceStyle.value = localStyle;
                            azureStyle[voiceType] = localStyle;
                        } else {
                            preSetVoiceStyle.selectedIndex = 0;
                            azureStyle[voiceType] = voiceStyles[0];
                        }
                        preSetVoiceStyle.onchange = () => {
                            azureStyle[voiceType] = preSetVoiceStyle.value;
                            localStorage.setItem("azureStyle" + voiceType, preSetVoiceStyle.value)
                        }
                        preSetVoiceStyle.dispatchEvent(new Event("change"));
                    } else {
                        azureStyle[voiceType] = void 0;
                        localStorage.removeItem("azureStyle" + voiceType);
                    }
                    preSetVoiceStyle.style.display = voiceStyles ? "block" : "none";
                    preSetVoiceStyle.previousElementSibling.style.display = voiceStyles ? "block" : "none";
                } else {
                    document.getElementById("azureExtra").style.display = "none";
                    azureRole[voiceType] = void 0;
                    localStorage.removeItem("azureRole" + voiceType);
                    azureStyle[voiceType] = void 0;
                    localStorage.removeItem("azureStyle" + voiceType);
                }
            };
            voiceChange = () => {
                let localVoice = localStorage.getItem("voice" + voiceType);
                if (localVoice) {
                    let localIndex = voicesData.findIndex(item => { return item.name === localVoice });
                    if (localIndex === -1) localIndex = 0;
                    voiceRole[voiceType] = voicesData[localIndex];
                    voicesEle.value = localIndex;
                } else {
                    voiceRole[voiceType] = voicesData[0];
                }
                voicesEle.dispatchEvent(new Event("change"));
            }
            let volumeEle = document.getElementById("voiceVolume");
            let localVolume = localStorage.getItem("voiceVolume0");
            voiceVolume[0] = parseFloat(localVolume || volumeEle.getAttribute("value"));
            const voiceVolumeChange = () => {
                let localVolume = localStorage.getItem("voiceVolume" + voiceType);
                volumeEle.value = voiceVolume[voiceType] = parseFloat(localVolume || volumeEle.getAttribute("value"));
                volumeEle.style.backgroundSize = (volumeEle.value - volumeEle.min) * 100 / (volumeEle.max - volumeEle.min) + "% 100%";
            }
            volumeEle.oninput = () => {
                volumeEle.style.backgroundSize = (volumeEle.value - volumeEle.min) * 100 / (volumeEle.max - volumeEle.min) + "% 100%";
                voiceVolume[voiceType] = parseFloat(volumeEle.value);
                localStorage.setItem("voiceVolume" + voiceType, volumeEle.value);
            }
            voiceVolumeChange();
            let rateEle = document.getElementById("voiceRate");
            let localRate = localStorage.getItem("voiceRate0");
            voiceRate[0] = parseFloat(localRate || rateEle.getAttribute("value"));
            const voiceRateChange = () => {
                let localRate = localStorage.getItem("voiceRate" + voiceType);
                rateEle.value = voiceRate[voiceType] = parseFloat(localRate || rateEle.getAttribute("value"));
                rateEle.style.backgroundSize = (rateEle.value - rateEle.min) * 100 / (rateEle.max - rateEle.min) + "% 100%";
            }
            rateEle.oninput = () => {
                rateEle.style.backgroundSize = (rateEle.value - rateEle.min) * 100 / (rateEle.max - rateEle.min) + "% 100%";
                voiceRate[voiceType] = parseFloat(rateEle.value);
                localStorage.setItem("voiceRate" + voiceType, rateEle.value);
            }
            voiceRateChange();
            let pitchEle = document.getElementById("voicePitch");
            let localPitch = localStorage.getItem("voicePitch0");
            voicePitch[0] = parseFloat(localPitch || pitchEle.getAttribute("value"));
            const voicePitchChange = () => {
                let localPitch = localStorage.getItem("voicePitch" + voiceType);
                pitchEle.value = voicePitch[voiceType] = parseFloat(localPitch || pitchEle.getAttribute("value"));
                pitchEle.style.backgroundSize = (pitchEle.value - pitchEle.min) * 100 / (pitchEle.max - pitchEle.min) + "% 100%";
            }
            pitchEle.oninput = () => {
                pitchEle.style.backgroundSize = (pitchEle.value - pitchEle.min) * 100 / (pitchEle.max - pitchEle.min) + "% 100%";
                voicePitch[voiceType] = parseFloat(pitchEle.value);
                localStorage.setItem("voicePitch" + voiceType, pitchEle.value);
            }
            voicePitchChange();
            document.getElementById("voiceTypes").onclick = (ev) => {
                let type = ev.target.dataset.type;
                if (type !== void 0) {
                    type = parseInt(type);
                    if (type != voiceType) {
                        voiceType = type;
                        ev.target.classList.add("selVoiceType");
                        ev.target.parentElement.children[type ^ 1].classList.remove("selVoiceType");
                        voiceChange();
                        voiceVolumeChange();
                        voiceRateChange();
                        voicePitchChange();
                    }
                };
            };
            const voiceTestEle = document.getElementById("testVoiceText");
            let localTestVoice = localStorage.getItem("voiceTestText");
            voiceTestText = voiceTestEle.value = localTestVoice || voiceTestEle.getAttribute("value");
            voiceTestEle.oninput = () => {
                voiceTestText = voiceTestEle.value;
                localStorage.setItem("voiceTestText", voiceTestText);
            }
            const contVoiceEle = document.getElementById("enableContVoice");
            let localCont = localStorage.getItem("enableContVoice");
            contVoiceEle.checked = enableContVoice = (localCont || contVoiceEle.getAttribute("checked")) === "true";
            contVoiceEle.onchange = () => {
                enableContVoice = contVoiceEle.checked;
                localStorage.setItem("enableContVoice", enableContVoice);
            }
            contVoiceEle.dispatchEvent(new Event("change"));
            const autoVoiceEle = document.getElementById("enableAutoVoice");
            let localAuto = localStorage.getItem("enableAutoVoice");
            autoVoiceEle.checked = enableAutoVoice = (localAuto || autoVoiceEle.getAttribute("checked")) === "true";
            autoVoiceEle.onchange = () => {
                enableAutoVoice = autoVoiceEle.checked;
                localStorage.setItem("enableAutoVoice", enableAutoVoice);
            }
            autoVoiceEle.dispatchEvent(new Event("change"));
        };
        initVoiceFunc();
        speechServiceEle.dispatchEvent(new Event("change"));
    </script>
    <script crossorigin="anonymous"
        src="https://fastly.jsdelivr.net/npm/markdown-it@14.1.0/dist/markdown-it.min.js"></script>
    <script crossorigin="anonymous"
        src="https://fastly.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js"></script>
    <script crossorigin="anonymous" src="https://fastly.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js"></script>
    <script src="cl.js"></script>
    <link crossorigin="anonymous" href="https://fastly.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css"
        rel="stylesheet">
    <script defer>
        let downRoleController = new AbortController();
        const loadPrompt = () => {
            downRoleController.abort();
            downRoleController = new AbortController();
            setTimeout(() => {
                downRoleController.abort();
            }, 10000);
            preEle.options.length = 5;
            if (locale === "zh") {
                fetch("https://fastly.jsdelivr.net/gh/PlexPt/awesome-chatgpt-prompts-zh/prompts-zh.json", {
                    signal: downRoleController.signal
                }).then(async (response) => {
                    let res = await response.json();
                    for (let i = 0; i < res.length; i++) {
                        let key = "act" + i;
                        presetRoleData[key] = res[i].prompt.trim();
                        let optionEle = document.createElement("option");
                        optionEle.text = res[i].act;
                        optionEle.value = key;
                        preEle.options.add(optionEle);
                    }
                }).catch(e => { })
            } else {
                fetch("https://fastly.jsdelivr.net/gh/f/awesome-chatgpt-prompts/prompts.csv", {
                    signal: downRoleController.signal
                }).then(async (response) => {
                    let res = await response.text();
                    let arr = res.split("\n");
                    for (let i = 1; i < arr.length - 1; i++) {
                        let key = "act" + i;
                        let index = arr[i].indexOf(",");
                        presetRoleData[key] = arr[i].slice(index + 2, -1);
                        let optionEle = document.createElement("option");
                        optionEle.text = arr[i].slice(1, index - 1);
                        optionEle.value = key;
                        preEle.options.add(optionEle);
                    }
                }).catch(e => { })
            }
        }
        loadPrompt();
    </script>
</body>

</html>