<!-- 
Program:
    Flask-Docs HTML Template
Version:
    0.6.6
History:
    Created on 2020/10/29
    Last modified on 2021/10/09
Author:
    kwkw
-->

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge，chrome=1">

    <!-- ___CSS_TEMPLATE___ -->

    <style>
        [v-cloak] {
            display: none !important;
        }
    </style>

    <link rel="icon" href="static/icon/book.svg" type="image/x-icon">
    <link rel="shortcut icon" href="static/icon/book.svg" type="image/x-icon">

    <title>Documentation</title>
</head>

<body>
    <div id="app" v-cloak>
        <el-card class="box-card" :style="mainDisplay">
            <el-container>
                <el-header>
                    <el-menu :default-active="headerIndex" class="el-menu-demo" mode="horizontal">
                        <el-menu-item index="1">{{ titleVersion }}</el-menu-item>
                        <el-button class="lock" type="text" icon="el-icon-lock" @click="lock"
                            v-if="authPasswordSHA2 != ''"></el-button>
                        <el-button class="download" type="text" icon="el-icon-download" @click="download"></el-button>
                        <el-button class="debug" type="text" :icon="debugShowIcon" @click="debugShow"></el-button>
                    </el-menu>
                </el-header>
                <el-main v-loading="loading" :style="docDisplay">
                    <el-row>
                        <el-col :span="8">
                            <el-input placeholder="Filter keyword" v-model="treeFilterText" style="padding-bottom:10px">
                            </el-input>
                            <div :style="menuStyle">
                                <el-tree class="filter-tree" :data="treeDataNew" :props="treeDefaultProps" node-key="id"
                                    highlight-current :filter-node-method="treeFilterNode" ref="apiTree"
                                    @node-click="treeNodeClick">
                                </el-tree>
                            </div>
                        </el-col>
                        <el-col :span="16" style="padding-left:20px">
                            <div :style="contentStyle">
                                <article class="markdown-body">
                                    <div id="md"></div>
                                </article>
                            </div>
                        </el-col>
                    </el-row>
                </el-main>
                <el-main :style="debugDisplay">
                    <el-card class="box-card">
                        <el-divider content-position="left">Method && URL</el-divider>
                        <el-select v-model="methodValue" placeholder="Select" style="width:8%;min-width:130px;">
                            <el-option v-for="item in methodOptions" :key="item.value" :label="item.label"
                                :value="item.value">
                            </el-option>
                        </el-select>
                        <el-select v-model="hostValue" filterable allow-create clearable default-first-option
                            placeholder="Select" style="width:20%;min-width:160px;">
                            <el-option v-for="item in hostOptions" :key="item.value" :label="item.label"
                                :value="item.value">
                            </el-option>
                        </el-select>
                        <el-select v-model="urlValue" filterable allow-create clearable default-first-option
                            placeholder="Select" style="width:50%;;min-width:209px;">
                            <el-option v-for="item in urlOptions" :key="item.value" :label="item.label"
                                :value="item.value">
                            </el-option>
                        </el-select>
                        <el-button type="primary" style="width:6%;min-width:80px;" @click="sendRequest"
                            :loading="loading">Send</el-button>
                    </el-card>
                    <el-card class="box-card" style="margin-top:10px">
                        <el-divider content-position="left">Headers</el-divider>
                        <el-row>
                            <el-input v-model="headerNameInput" size="small" style="width:20%;min-width:160px;"
                                placeholder="name" clearable>
                            </el-input>
                            <el-input v-model="headerValueInput" size="small" style="width:20%;min-width:160px;"
                                placeholder="value" clearable>
                            </el-input>
                            <el-button type="primary" size="small" style="width:60px;" @click="addHeader">Add
                            </el-button>
                        </el-row></br>
                        <el-row>
                            <el-tag v-for="tag in headerTags" :key="tag.name" closable :type="tag.type"
                                style="margin-left: 10px;" @close="delHeader(tag)">
                                {{tag.name.length>50?tag.name.substring(0,49)+"...":tag.name}}
                            </el-tag>
                        </el-row>
                    </el-card>
                    <el-card class="box-card" style="margin-top:10px">
                        <el-divider content-position="left">Body</el-divider>
                        <el-row>
                            <el-input type="textarea" :autosize="{ minRows: 6}" placeholder="Request Body"
                                v-model="bodyTextarea">
                            </el-input>
                        </el-row>
                    </el-card>
                    <el-card class="box-card" style="margin-top:10px">
                        <el-divider content-position="left">Response</el-divider>
                        <el-button class="copyResponse" type="text" icon="el-icon-document-copy" @click="copyResponse">
                        </el-button>
                        <el-tabs type="card" v-model="responseTabsActiveName">
                            <el-tab-pane label="Headers" name="Headers">
                                <div id="responseHeaderText">
                                    <pre><code class="hljs language-bash">&nbsp;</code></pre>
                                </div>
                            </el-tab-pane>
                            <el-tab-pane label="Response" name="Response">
                                <div id="responseResponseText">
                                    <pre><code class="hljs language-bash">&nbsp;</code></pre>
                                </div>
                            </el-tab-pane>
                            <el-tab-pane label="Preview" name="Preview">
                                <div id="responsePreviewText">
                                    <pre><code class="hljs language-bash">&nbsp;</code></pre>
                                </div>
                            </el-tab-pane>
                        </el-tabs>
                    </el-card>
                </el-main>
            </el-container>
            <a class="project-name-version" href="https://github.com/kwkwc/flask-docs/" target="_blank">{{PROJECT_NAME}}
                v{{PROJECT_VERSION}}</a>
        </el-card>
        <div class="auth" :style="authDisplay">
            <el-card class="auth-box-card">
                <div slot="header">
                    <span>
                        <h2>Welcome to Flask-Docs</h2>
                    </span>
                    <span>Please enter the original password for $API_DOC_PASSWORD_SHA2</span>
                </div>
                <el-row>
                    <el-input v-model="authPassword" style="width:70%;min-width:160px;" placeholder="PASSWORD"
                        show-password ref="passwordInput" @keyup.enter.native="verifyAuth">
                    </el-input>
                    <el-button type="primary" style="width:100px;" @click="verifyAuth" :loading="loading">SUBMIT
                    </el-button>
                </el-row>
            </el-card>
        </div>
    </div>
</body>

<!-- ___JS_TEMPLATE___ -->

<script>
    new Vue({
        el: "#app",
        data: {
            loading: false,
            headerIndex: "1",
            treeFilterText: "",
            treeData: {},
            treeDefaultProps: {
                label: "full_name",
                children: "children"
            },
            PROJECT_NAME: "",
            PROJECT_VERSION: "",
            title: "Documentation",
            version: "1.0.0",
            description: "",
            titleVersion: "Documentation",
            noDocText: "No documentation found for this Api",
            menuContentStyle: "padding-right:10px;overflow-y:auto;max-height:",
            menuStyle: "padding-right:10px;overflow-y:auto;max-height:670px",
            contentStyle: "padding-right:10px;overflow-y:auto;max-height:720px",
            docDisplay: "display:block",
            debugDisplay: "display:none",
            debugShowIcon: "el-icon-picture-outline-round",
            methodList: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD", "TRACE", "CONNECT", "PATCH"],
            methodOptions: [],
            methodValue: "GET",
            hostOptions: [],
            hostValue: "http://127.0.0.1",
            hostValueBak: "",
            urlOptions: [],
            urlValue: "",
            urlValueBak: "",
            headerNameInput: "",
            headerValueInput: "",
            headerTagsTypeDict: { 0: "primary", 1: "success", 2: "info", 3: "warning", 4: "danger" },
            headerTags: [],
            bodyTextarea: "",
            responseTabsActiveName: "Headers",
            responseTabsActiveDict: { "Headers": "responseHeaderText", "Response": "responseResponseText", "Preview": "responsePreviewText" },
            authPassword: "",
            authPasswordSHA2: "",
            authDisplay: "display:none",
            mainDisplay: "display:none"
        },
        created: function () {
            this.changeWindowSize()

            document.title = this.title
            document.getElementById("md").innerHTML = marked("# " + this.title)

            this.makeMethodOptions()
        },
        mounted: function () {
            this.getAuthCache()
            this.getData()
            this.getHostCache()
            this.getHeaderCache()
            this.pageShow()

            window.onresize = () => {
                this.changeWindowSize()
            }
        },
        methods: {
            changeWindowSize() {
                let screenHeightMenu = window.innerHeight - 220
                let screenHeightContent = screenHeightMenu + 50
                this.menuStyle = this.menuContentStyle + screenHeightMenu + "px"
                this.contentStyle = this.menuContentStyle + screenHeightContent + "px"
            },
            getData() {
                this.loading = true
                axios({
                    method: "GET",
                    url: "data",
                    timeout: 1000 * 30,
                    headers: { "Auth-Password-SHA2": this.authPasswordSHA2 }
                }).then(res => {
                    this.setCache("cache:auth", this.authPasswordSHA2)
                    this.mainShow()
                    this.treeData = res.data.data
                    this.PROJECT_NAME = res.data.PROJECT_NAME
                    this.PROJECT_VERSION = res.data.PROJECT_VERSION
                    this.title = res.data.title
                    this.version = res.data.version
                    this.description = res.data.description
                    this.titleVersion = this.title + " (" + this.version + ")"
                    this.noDocText = res.data.noDocText
                    this.hostValue = res.data.host
                    document.title = this.titleVersion
                    let md = "# " + this.titleVersion
                    if (this.description != "") {
                        md += "\n> " + this.description
                    }
                    document.getElementById("md").innerHTML = marked(md)
                    this.makeUrlOptions(res.data.data)
                    this.getUrlCache()
                    this.jumpAnchor()
                    this.loading = false
                },
                    err => {
                        if (err.response && err.response.status === 401) {
                            this.authShow()
                            if (this.authPassword != "") {
                                this.$message.error("Incorrect password")
                            }
                            else {
                                this.$message.error("Unauthorized")
                            }
                        }
                        else {
                            this.mainShow()
                            this.$message.error("Error")
                        }
                        this.loading = false
                    }
                )
            },
            make_md(md, con) {
                md += "### url" + "\n"
                var urls = new Array()
                urls = con.url.split(" ")
                if (urls.length == 1) {
                    urls = [urls[0].split("\t")[0]]
                }
                for (i = 0; i < urls.length; i++) {
                    md += "- " + urls[i].replace(/\t/g, " ") + "\n\n"
                }
                if (con.api_type === "api") {
                    md += "### method" + "\n"
                    md += "- " + con.method + "\n\n"
                }
                if (con.doc == this.noDocText && con.doc_md != "") {
                }
                else {
                    md += "### doc" + "\n"
                    md += "```doc\n" + con.doc + "\n```\n\n"
                }
                return md
            },
            download() {
                let md = ""
                this.treeDataNew.forEach((t, index) => {
                    md += "# " + t.full_name + "\n\n"
                    this.treeData[t.full_name]["children"].forEach((con, index) => {
                        md += "## " + con.name
                        if (con.name_extra != "") {
                            md += "(" + con.name_extra + ")"
                        }
                        md += "\n\n"
                        md = this.make_md(md, con)
                        md += con.doc_md + "\n\n\n"
                    })
                    md += "\n\n"
                })
                saveAs(new Blob([md], { type: "text/markdown;charset=utf-8" }), this.title + " (" + this.version + ")" + ".md")
            },
            treeFilterNode(value, data) {
                if (!value) return true
                let srcStr = data.full_name.toLowerCase()
                let desStr = value.toLowerCase()
                return srcStr.indexOf(desStr) !== -1
            },
            treeNodeClick(data) {
                if (data.router != null) {
                    let md = ""
                    this.treeData[data.router]["children"].forEach((con, index) => {
                        if (con.name == data.name) {
                            md += "# " + data.full_name + "\n\n"
                            md = this.make_md(md, con)
                            md += con.doc_md
                        }
                    })
                    document.getElementById("md").innerHTML = marked(md)
                    document.querySelectorAll("pre code").forEach((block) => {
                        hljs.highlightElement(block)
                    })
                    this.dropAnchor(data.id)
                }
            },
            debugShow() {
                if (this.debugDisplay === "display:none") {
                    this.debugShowIcon = "el-icon-document"
                    this.debugDisplay = "display:block"
                    this.docDisplay = "display:none"
                    this.setCache("cache:page", "debugger")
                }
                else {
                    this.debugShowIcon = "el-icon-picture-outline-round"
                    this.debugDisplay = "display:none"
                    this.docDisplay = "display:block"
                    this.setCache("cache:page", "document")
                }
            },
            makeMethodOptions() {
                this.methodList.forEach((m, index) => {
                    this.methodOptions.push({ value: m, label: m })
                })
            },
            makeUrlOptions(dataDict) {
                let urlOptionsNew = new Array()
                for (key in dataDict) {
                    dataDict[key]["children"].forEach((con, index) => {
                        let urls = new Array()
                        urls = con.url.split(" ")
                        if (urls.length == 1) {
                            urls = [urls[0].split("\t")[0]]
                        }
                        for (i = 0; i < urls.length; i++) {
                            let url = urls[i].split("\t")[0]
                            if (!urlOptionsNew.some(item => {
                                if (item.label == url) {
                                    return true
                                }
                            })) {
                                urlOptionsNew.push({ value: url, label: url })
                            }

                        }
                    })
                }
                this.urlOptions = urlOptionsNew
            },
            changeOptions(options, optionsBak, val) {
                val = val.trim()
                if (!val) {
                    let optionsNew = new Array()
                    this[options].forEach((item, index) => {
                        if (item.label !== this[optionsBak]) {
                            optionsNew.push({ value: item.value, label: item.label })
                        }
                    })
                    this[options] = optionsNew
                    return
                }
                if (val === "") {
                    return
                }
                this[optionsBak] = val
                if (!this[options].some(item => {
                    if (item.label == val) {
                        return true
                    }
                })) {
                    this[options].push({ value: val, label: val })
                }
            },
            addHeader() {
                let headerNameInputNew = this.headerNameInput.trim()
                let headerValueInputNew = this.headerValueInput.trim()
                if ((headerNameInputNew !== "") && (headerValueInputNew !== "")) {
                    if (headerNameInputNew.toLowerCase() === "content-type") {
                        headerNameInputNew = headerNameInputNew.toLowerCase()
                        headerValueInputNew = headerValueInputNew.toLowerCase()
                    }
                    type = Math.floor(Math.random() * 5)
                    this.headerTags.push({
                        name: [headerNameInputNew, headerValueInputNew].join(":"),
                        type: this.headerTagsTypeDict[type]
                    })
                    this.setCache("cache:header", this.headerTags)
                }
            },
            delHeader(tag) {
                this.headerTags.splice(this.headerTags.indexOf(tag), 1)
                this.setCache("cache:header", this.headerTags)
            },
            makeHljsPreCode(id, text) {
                document.getElementById(id).innerHTML = "<pre><code>" + text + "</code></pre>"
            },
            makeResponse(res) {
                resStatus = [res.status, res.statusText].join(" ")
                resHeaders = res.headers
                resData = res.data
                let resHeadersdict = Object.assign({ "status code": resStatus }, resHeaders)

                this.makeHljsPreCode("responseHeaderText", JSON.stringify(resHeadersdict, null, 4))
                if (resHeaders["content-type"] && resHeaders["content-type"].indexOf("application/json") != -1) {
                    this.makeHljsPreCode("responseResponseText", JSON.stringify(resData))
                    this.makeHljsPreCode("responsePreviewText", JSON.stringify(resData, null, 4))
                }
                else if (resHeaders["content-type"] && resHeaders["content-type"].indexOf("text/html") != -1) {
                    document.getElementById("responseResponseText").innerHTML = "<code>" + resData + "</code>"
                    document.getElementById("responsePreviewText").innerHTML = "<code>" + resData + "</code>"
                }
                else {
                    this.makeHljsPreCode("responseResponseText", resData)
                    this.makeHljsPreCode("responsePreviewText", resData)
                }
                document.querySelectorAll("pre code").forEach((block) => {
                    hljs.highlightElement(block)
                })
            },
            sendRequest() {
                if ((this.hostValue === "") || (this.urlValue === "")) {
                    return
                }
                this.loading = true
                headers = {}
                this.headerTags.forEach((item, index) => {
                    headerTag = item.name.split(":")
                    headers[headerTag[0]] = headerTag[1]
                })

                data = ""
                params = {}
                if (this.bodyTextarea !== "") {
                    if (this.methodValue === "GET" || this.methodValue === "DELETE") {
                        this.bodyTextarea.split("&").forEach((item, index) => {
                            params[item.split("=")[0]] = item.split("=")[1]
                        })
                    }
                    else {
                        if (!headers["content-type"] || (headers["content-type"] &&
                            (headers["content-type"].indexOf("application/x-www-form-urlencoded") === -1 &&
                                headers["content-type"].indexOf("multipart/form-data") === -1 &&
                                headers["content-type"].indexOf("text/plain") === -1))) {
                            try {
                                data = JSON.parse(this.bodyTextarea)
                            }
                            catch (err) {
                                data = this.bodyTextarea
                                this.$notify.error({
                                    title: "Error",
                                    message: "The request body is not json"
                                })
                            }
                        }
                        else {
                            data = this.bodyTextarea
                        }
                    }
                }
                this.setBodyCache()

                document.getElementById("responseHeaderText").innerHTML = ""
                document.getElementById("responsePreviewText").innerHTML = ""
                document.getElementById("responseResponseText").innerHTML = ""
                axios({
                    method: this.methodValue,
                    url: this.hostValue + this.urlValue,
                    timeout: 1000 * 30,
                    headers: headers,
                    data: data,
                    params: params
                }).then(res => {
                    this.makeResponse(res)
                    this.$notify({
                        title: "Success",
                        type: "success"
                    })
                    this.loading = false
                },
                    err => {
                        if (err.response) {
                            errResponse = err.response
                            this.makeResponse(errResponse)
                            this.$notify({
                                title: "Warning",
                                type: "warning"
                            })
                            this.loading = false
                            return
                        } else if (err.request) {
                            console.log(err.request)
                            document.getElementById("responseResponseText").innerHTML = err.request
                        } else {
                            console.log("Error", err.message)
                            document.getElementById("responseResponseText").innerHTML = err.message
                        }
                        document.querySelectorAll("pre code").forEach((block) => {
                            hljs.highlightElement(block)
                        })
                        this.responseTabsActiveName = "Response"
                        this.$notify.error({
                            title: "Error",
                        })
                        this.loading = false
                    }
                )
            },
            setCache(k, v) {
                try {
                    localStorage.setItem(k, JSON.stringify(v))
                }
                catch (err) {
                    localStorage.setItem(k, v)
                }
            },
            getCache(k) {
                try {
                    cacheValue = JSON.parse(localStorage.getItem(k))
                }
                catch (err) {
                    cacheValue = localStorage.getItem(k)
                }
                return cacheValue
            },
            setBodyCache() {
                bodyKey = "cache:body:" + sha1([this.hostValue, this.urlValue, this.methodValue].join("-"))
                this.setCache(bodyKey, this.bodyTextarea)
            },
            getHostCache() {
                let hostCacheOptions = this.getCache("cache:host")
                if (hostCacheOptions) {
                    this.hostOptions = hostCacheOptions
                }
            },
            getUrlCache() {
                let urlCacheOptions = this.getCache("cache:url")
                if (urlCacheOptions) {
                    urlCacheOptions.forEach((item, index) => {
                        this.changeOptions("urlOptions", "urlOptionsBak", item.label)
                    })
                }
            },
            getHeaderCache() {
                let headerCacheTags = this.getCache("cache:header")
                if (headerCacheTags) {
                    this.headerTags = headerCacheTags
                }
            },
            getBodyCache() {
                if ((this.hostValue === "") || (this.urlValue === "")) {
                    return
                }
                bodyKey = "cache:body:" + sha1([this.hostValue, this.urlValue, this.methodValue].join("-"))
                let bodyCacheTextarea = this.getCache(bodyKey)
                if (bodyCacheTextarea) {
                    this.bodyTextarea = bodyCacheTextarea
                }
            },
            pageShow() {
                let pageCache = this.getCache("cache:page")
                if (pageCache && pageCache === "debugger") {
                    this.debugShow()
                }
            },
            copyResponse() {
                let text = document.getElementById(this.responseTabsActiveDict[this.responseTabsActiveName]).innerText
                let input = document.createElement("textarea")
                document.body.appendChild(input)
                input.value = text
                input.select()
                if (document.execCommand("copy")) {
                    this.$message({
                        message: "Copied",
                        type: "success"
                    })
                }
                document.body.removeChild(input)
            },
            dropAnchor(anchor) {
                let currentUrl = window.location.href
                let hostUrl = currentUrl.split("#")[0]
                history.pushState("", "", hostUrl + "#" + anchor)
            },
            jumpAnchor() {
                this.$nextTick(function () {
                    try {
                        let currentUrl = decodeURI(window.location.href)
                        let anchor = currentUrl.split("#")[1]
                        let anchorParent = anchor.split("-")[0]
                        this.$refs.apiTree.store.nodesMap[anchorParent].expanded = true
                        this.$refs.apiTree.setCurrentKey(anchor)
                        let node = this.$refs.apiTree.getNode(anchor)
                        this.treeNodeClick(node.data)
                    }
                    catch (err) {
                    }
                })
            },
            getAuthCache() {
                let authCache = this.getCache("cache:auth")
                if (authCache) {
                    this.authPasswordSHA2 = authCache
                }
            },
            authShow() {
                this.authDisplay = "display:block"
                this.mainDisplay = "display:none"
                this.$nextTick(function () {
                    this.$refs.passwordInput.focus()
                })
            },
            mainShow() {
                this.authDisplay = "display:none"
                this.mainDisplay = "display:block"
            },
            verifyAuth() {
                let authPassword = this.authPassword.trim()
                if (authPassword === "") {
                    return
                }
                this.authPasswordSHA2 = sha256(authPassword)
                this.getData()
            },
            lock() {
                localStorage.removeItem("cache:auth")
                this.authPasswordSHA2 = ""
                this.authPassword = ""
                this.getData()
            }
        },
        computed: {
            treeDataNew() {
                let treeDataNew = new Array()
                for (key in this.treeData) {
                    let childrenData = new Array()
                    this.treeData[key]["children"].forEach((con, index) => {
                        let id = con.router + "-" + con.name
                        if (con.name_extra == "") {
                            childrenData.push({ "id": id, "full_name": con.name, "name": con.name, "router": con.router })
                        }
                        else {
                            childrenData.push({ "id": id, "full_name": con.name + "(" + con.name_extra + ")", "name": con.name, "router": con.router })
                        }
                    })
                    treeDataNew.push({ "id": key, "full_name": key, "children": childrenData })
                }
                return treeDataNew
            }
        },
        watch: {
            treeFilterText(val) {
                this.$refs.apiTree.filter(val)
            },
            methodValue(val) {
                this.getBodyCache()
            },
            hostValue(val) {
                this.changeOptions("hostOptions", "hostOptionsBak", val)
                this.setCache("cache:host", this.hostOptions)
                this.getBodyCache()
            },
            urlValue(val) {
                this.changeOptions("urlOptions", "urlValueBak", val)
                this.setCache("cache:url", this.urlOptions)
                this.getBodyCache()
            }
        }
    })
</script>

<style>
    @media screen and (min-width: 914px) {
        body {
            width: 96%;
            margin: 10px auto;
        }
    }

    /* Webkit */
    ::-webkit-scrollbar {
        background: #f7f7f9;
        width: 8px;
        height: 8px;
    }

    ::-webkit-scrollbar-thumb {
        background: #e5e5e5;
    }

    ::-webkit-scrollbar-thumb:hover {
        background: #bababa
    }

    /* Firefox */
    * {
        scrollbar-color: #e5e5e5 #f7f7f9;
        scrollbar-width: thin;
    }

    .el-button+.el-button {
        margin-left: 0px;
    }

    .debug,
    .download,
    .lock {
        padding-top: 25px;
        padding-right: 20px;
        font-size: 20px;
        float: right;
    }

    pre {
        white-space: pre-wrap;
        word-wrap: break-word;
        font-size: 85%;
        line-height: 1.45;
        background-color: #f6f8fa;
    }

    @-moz-document url-prefix() {
        pre {
            margin-top: 12px
        }
    }

    code,
    textarea {
        font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
    }

    .project-name-version {
        float: right;
        margin-bottom: 6px;
        font-size: 12px;
        color: #e5e5e5;
        text-decoration: none;
    }

    .copyResponse {
        margin-top: 54px;
        padding-left: 6px;
        padding-right: 20px;
        font-size: 20px;
        float: right;
    }

    .auth {
        position: fixed;
        left: 50%;
        top: 42%;
        -webkit-transform: translate(-50%, -50%);
        transform: translate(-50%, -50%);
    }

    .auth-box-card {
        max-width: 580px;
    }
</style>

</html>