Create a local web editor that allows for the following functions:

    Precise Gutter Line Highlighting:
        Highlight the gutter line index when the caret or cursor moves to a specific line.
        Maintain the highlight during:
            Navigation using search/anchors like L# (e.g., L3 to jump to line 3).
            Keyword searches that land on a matching line.
            Regular typing and caret movement.

    Gutter Highlight Styling:
        Use clear, contrasting styles for highlighted lines (e.g., red background, white text) with rounded corners and padding.

    Live Editing Features:
        Integrate CodeMirror for syntax-highlighted HTML/JS/CSS editing.
        Render live code by opening a new tab to preview the editor's content.
        Allow users to save the editor's content as an HTML file using a "Save" button.

    Search Functionality:
        Include a search input to perform:
            Keyword searches (i.e., highlight matching instances in the editor).
            Direct line jumping using the L# format (e.g., L3 to move to line 3).

    Error Indications:
        Blink the search input (e.g., red border) if the user attempts to jump to an invalid line or searches for a nonexistent keyword.




"""

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>local-web editor with blob detachment</title>

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">

    <!-- CodeMirror Core CSS -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/codemirror.min.css" rel="stylesheet">

    <!-- Custom Styling -->
    <style>
        body {
            margin: 0;
            background-color: #1d1f21;
            color: #c5c8c6;
            font-family: Arial, sans-serif;
            height: 100vh;
            display: flex;
            flex-direction: column;
        }

        .editor-container {
            flex: 1;
            padding: 10px;
            overflow: hidden;
        }

        .CodeMirror {
            height: calc(100% - 10px);
            background-color: #282a36 !important;
            color: #f8f8f2 !important;
            border: 2px solid #44475a;
            border-radius: 6px;
            font-family: "Courier New", monospace;
            font-size: 14px;
        }

        .CodeMirror-gutters {
            background-color: #212634;
            border-right: 2px solid #44475a;
        }

        /* Highlighted gutter line number (red) */
        .CodeMirror-linenumbers .line-number-highlight {
            color: #ff4444 !important;
            font-weight: bold;
        }

        .CodeMirror-focused .CodeMirror-cursor {
            border-left: 2px solid #ffffff !important;
        }

        .buttons-container {
            padding: 10px;
            background-color: #212634;
            display: flex;
            justify-content: space-between;
            align-items: center;
            gap: 10px;
        }

        button {
            background-color: #6272a4;
            color: #f8f8f2;
            border: none;
            padding: 8px 16px;
            font-size: 14px;
            font-weight: bold;
            border-radius: 5px;
        }

        .search-container input {
            padding: 6px 10px;
            border: 2px solid #44475a;
            border-radius: 4px;
            background: #282a36;
            color: #f8f8f2;
            width: 230px;
        }

        .search-container input::placeholder {
            color: #6272a4;
        }

        /* No Results Red Blink Animation */
        .search-blink-error {
            animation: blink-error 0.4s linear 2;
        }

        @keyframes blink-error {
            0%, 100% {
                border-color: #f8f8f2;
            }
            50% {
                border-color: #ff4444;
            }
        }
    </style>
</head>

<body>
    <div class="editor-container">
        <textarea id="editor"></textarea>
    </div>

    <div class="buttons-container">
        <div class="search-container">
            <input id="searchField" type="text" placeholder="L#:toLine||search">
            <button id="searchButton">Search/Go</button>
        </div>
        <div>
            <button id="runButton">Run Code</button>
            <button id="saveButton">Save HTML</button>
        </div>
    </div>

    <!-- CodeMirror Core and Addons -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/codemirror.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/addon/search/search.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/addon/search/searchcursor.min.js"></script>

    <!-- Syntax Highlighting Modes -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/mode/htmlmixed/htmlmixed.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/mode/xml/xml.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/mode/javascript/javascript.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/mode/css/css.min.js"></script>

    <script>
        // Initialize CodeMirror
        const editor = CodeMirror.fromTextArea(document.getElementById("editor"), {
            mode: "htmlmixed",
            lineNumbers: true,
            matchBrackets: true,
            autoCloseBrackets: true,
            theme: "default"
        });

        const searchField = document.getElementById("searchField");
        let highlightedLine = null;

        // Search or Go To
        document.getElementById("searchButton").addEventListener("click", () => {
            const query = searchField.value.trim();

            // Check if it's an L<number> anchor
            if (query.toLowerCase().startsWith("l")) {
                const lineNumber = parseInt(query.slice(1), 10) - 1;
                if (!isNaN(lineNumber) && lineNumber >= 0 && lineNumber < editor.lineCount()) {
                    focusLine(lineNumber);
                } else {
                    triggerBlinkAnimation();
                }
            } else {
                searchAndHighlight(query);
            }
        });

        // Highlight the Gutter Line Number
        function focusLine(lineNumber) {
            clearPreviousHighlight();

            editor.setCursor({ line: lineNumber, ch: 0 });
            editor.scrollIntoView({ line: lineNumber, ch: 0 });

            const gutters = document.querySelectorAll(".CodeMirror-linenumbers > div");
            if (gutters[lineNumber]) {
                gutters[lineNumber].classList.add("line-number-highlight");
                highlightedLine = lineNumber;
            }
        }

        // Search and Highlight in the Editor
        function searchAndHighlight(query) {
            clearPreviousHighlight();

            const cursor = editor.getSearchCursor(query, editor.getCursor());
            if (cursor.findNext()) {
                editor.setSelection(cursor.from(), cursor.to());
                editor.scrollIntoView(cursor.from());
            } else {
                triggerBlinkAnimation();
            }
        }

        // Clear Previous Highlights
        function clearPreviousHighlight() {
            if (highlightedLine !== null) {
                const gutters = document.querySelectorAll(".CodeMirror-linenumbers > div");
                if (gutters[highlightedLine]) {
                    gutters[highlightedLine].classList.remove("line-number-highlight");
                }
            }
            highlightedLine = null;
        }

        // Trigger Blink Animation for Errors
        function triggerBlinkAnimation() {
            searchField.classList.add("search-blink-error");
            setTimeout(() => searchField.classList.remove("search-blink-error"), 500);
        }

        // Clear highlights on click elsewhere
        editor.on("mousedown", () => {
            clearPreviousHighlight();
        });

        // Run Code Button
        document.getElementById("runButton").addEventListener("click", () => {
            const code = editor.getValue();
            const newTab = window.open();
            newTab.document.write(code);
            newTab.document.close();
        });

        // Save HTML Button
        document.getElementById("saveButton").addEventListener("click", () => {
            const code = editor.getValue();
            const blob = new Blob([code], { type: "text/html" });
            const url = URL.createObjectURL(blob);
            const a = document.createElement("a");
            a.href = url;
            a.download = "index.html";
            a.click();
        });
    </script>
</body>

</html>

""".


output full corrected.