YouTube Gemini Summarizer

Summarizes YouTube videos using Gemini API with a GUI for API key, model, language selection, custom system prompts (with RTL support), and Markdown rendering.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         YouTube Gemini Summarizer
// @namespace    http://tampermonkey.net/
// @version      0.5.1
// @description  Summarizes YouTube videos using Gemini API with a GUI for API key, model, language selection, custom system prompts (with RTL support), and Markdown rendering.
// @author       kobaltGIT
// @match        https://www.youtube.com/watch*
// @icon         data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCIgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0Ij48cmVjdCB4PSIxMCIgeT0iMTAiIHdpZHRoPSI0NCIgaGVpZ2h0PSI0NCIgcng9IjUiIHJ5PSI1IiBmaWxsPSIjNENBRjUwIi8+PGxpbmUgeDE9IjE4IiB5MT0iMjQiIHgyPSI0NiIgeTI9IjI0IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjMiLz48bGluZSB4MT0iMTgiIHkxPSIzMiIgeDI9IjQ2IiB5Mj0iMzIiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMyIvPjxsaW5lIHgxPSIxOCIgeTE9IjQwIiB4Mj0iMzQiIHkyPSI0MCIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIzIi8+PHBvbHlnb24gcG9pbnRzPSIzOCwzNyA0Niw0MCAzOCw0MyIgZmlsbD0id2hpdGUiLz48L3N2Zz4=
// @license      MIT
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @connect      generativelanguage.googleapis.com
// ==/UserScript==

/**
 * marked v15.0.12 - a markdown parser
 * Copyright (c) 2011-2025, Christopher Jeffrey. (MIT Licensed)
 * https://github.com/markedjs/marked
 */

/**
 * DO NOT EDIT THIS FILE
 * The code in this file is generated from files in ./src/
 */
(function(g,f){if(typeof exports=="object"&&typeof module<"u"){module.exports=f()}else if("function"==typeof define && define.amd){define("marked",f)}else {g["marked"]=f()}}(typeof globalThis < "u" ? globalThis : typeof self < "u" ? self : this,function(){var exports={};var __exports=exports;var module={exports};
"use strict";var H=Object.defineProperty;var be=Object.getOwnPropertyDescriptor;var Te=Object.getOwnPropertyNames;var we=Object.prototype.hasOwnProperty;var ye=(l,e)=>{for(var t in e)H(l,t,{get:e[t],enumerable:!0})},Re=(l,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Te(e))!we.call(l,s)&&s!==t&&H(l,s,{get:()=>e[s],enumerable:!(n=be(e,s))||n.enumerable});return l};var Se=l=>Re(H({},"__esModule",{value:!0}),l);var kt={};ye(kt,{Hooks:()=>L,Lexer:()=>x,Marked:()=>E,Parser:()=>b,Renderer:()=>$,TextRenderer:()=>_,Tokenizer:()=>S,defaults:()=>w,getDefaults:()=>z,lexer:()=>ht,marked:()=>k,options:()=>it,parse:()=>pt,parseInline:()=>ct,parser:()=>ut,setOptions:()=>ot,use:()=>lt,walkTokens:()=>at});module.exports=Se(kt);function z(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var w=z();function N(l){w=l}var I={exec:()=>null};function h(l,e=""){let t=typeof l=="string"?l:l.source,n={replace:(s,i)=>{let r=typeof i=="string"?i:i.source;return r=r.replace(m.caret,"$1"),t=t.replace(s,r),n},getRegex:()=>new RegExp(t,e)};return n}var m={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceTabs:/^\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] /,listReplaceTask:/^\[[ xX]\] +/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,unescapeTest:/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:l=>new RegExp(`^( {0,3}${l})((?:[	 ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:l=>new RegExp(`^ {0,${Math.min(3,l-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ 	][^\\n]*)?(?:\\n|$))`),hrRegex:l=>new RegExp(`^ {0,${Math.min(3,l-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:l=>new RegExp(`^ {0,${Math.min(3,l-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:l=>new RegExp(`^ {0,${Math.min(3,l-1)}}#`),htmlBeginRegex:l=>new RegExp(`^ {0,${Math.min(3,l-1)}}<(?:[a-z].*>|!--)`,"i")},$e=/^(?:[ \t]*(?:\n|$))+/,_e=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,Le=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,O=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,ze=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,F=/(?:[*+-]|\d{1,9}[.)])/,ie=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,oe=h(ie).replace(/bull/g,F).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),Me=h(ie).replace(/bull/g,F).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),Q=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,Pe=/^[^\n]+/,U=/(?!\s*\])(?:\\.|[^\[\]\\])+/,Ae=h(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",U).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),Ee=h(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,F).getRegex(),v="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",K=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,Ce=h("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ 	]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ 	]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ 	]*)+\\n|$))","i").replace("comment",K).replace("tag",v).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),le=h(Q).replace("hr",O).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex(),Ie=h(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",le).getRegex(),X={blockquote:Ie,code:_e,def:Ae,fences:Le,heading:ze,hr:O,html:Ce,lheading:oe,list:Ee,newline:$e,paragraph:le,table:I,text:Pe},re=h("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",O).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3}	)[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex(),Oe={...X,lheading:Me,table:re,paragraph:h(Q).replace("hr",O).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",re).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",v).getRegex()},Be={...X,html:h(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",K).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:I,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:h(Q).replace("hr",O).replace("heading",` *#{1,6} *[^
]`).replace("lheading",oe).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},qe=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,ve=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,ae=/^( {2,}|\\)\n(?!\s*$)/,De=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,D=/[\p{P}\p{S}]/u,W=/[\s\p{P}\p{S}]/u,ce=/[^\s\p{P}\p{S}]/u,Ze=h(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,W).getRegex(),pe=/(?!~)[\p{P}\p{S}]/u,Ge=/(?!~)[\s\p{P}\p{S}]/u,He=/(?:[^\s\p{P}\p{S}]|~)/u,Ne=/\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g,ue=/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/,je=h(ue,"u").replace(/punct/g,D).getRegex(),Fe=h(ue,"u").replace(/punct/g,pe).getRegex(),he="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",Qe=h(he,"gu").replace(/notPunctSpace/g,ce).replace(/punctSpace/g,W).replace(/punct/g,D).getRegex(),Ue=h(he,"gu").replace(/notPunctSpace/g,He).replace(/punctSpace/g,Ge).replace(/punct/g,pe).getRegex(),Ke=h("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,ce).replace(/punctSpace/g,W).replace(/punct/g,D).getRegex(),Xe=h(/\\(punct)/,"gu").replace(/punct/g,D).getRegex(),We=h(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Je=h(K).replace("(?:-->|$)","-->").getRegex(),Ve=h("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment",Je).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),q=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,Ye=h(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label",q).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),ke=h(/^!?\[(label)\]\[(ref)\]/).replace("label",q).replace("ref",U).getRegex(),ge=h(/^!?\[(ref)\](?:\[\])?/).replace("ref",U).getRegex(),et=h("reflink|nolink(?!\\()","g").replace("reflink",ke).replace("nolink",ge).getRegex(),J={_backpedal:I,anyPunctuation:Xe,autolink:We,blockSkip:Ne,br:ae,code:ve,del:I,emStrongLDelim:je,emStrongRDelimAst:Qe,emStrongRDelimUnd:Ke,escape:qe,link:Ye,nolink:ge,punctuation:Ze,reflink:ke,reflinkSearch:et,tag:Ve,text:De,url:I},tt={...J,link:h(/^!?\[(label)\]\((.*?)\)/).replace("label",q).getRegex(),reflink:h(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",q).getRegex()},j={...J,emStrongRDelimAst:Ue,emStrongLDelim:Fe,url:h(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,"i").replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/},nt={...j,br:h(ae).replace("{2,}","*").getRegex(),text:h(j.text).replace("\\b_","\\b_| {2,}\\n").replace(/\{2,\}/g,"*").getRegex()},B={normal:X,gfm:Oe,pedantic:Be},P={normal:J,gfm:j,breaks:nt,pedantic:tt};var st={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},fe=l=>st[l];function R(l,e){if(e){if(m.escapeTest.test(l))return l.replace(m.escapeReplace,fe)}else if(m.escapeTestNoEncode.test(l))return l.replace(m.escapeReplaceNoEncode,fe);return l}function V(l){try{l=encodeURI(l).replace(m.percentDecode,"%")}catch{return null}return l}function Y(l,e){let t=l.replace(m.findPipe,(i,r,o)=>{let a=!1,c=r;for(;--c>=0&&o[c]==="\\";)a=!a;return a?"|":" |"}),n=t.split(m.splitPipe),s=0;if(n[0].trim()||n.shift(),n.length>0&&!n.at(-1)?.trim()&&n.pop(),e)if(n.length>e)n.splice(e);else for(;n.length<e;)n.push("");for(;s<n.length;s++)n[s]=n[s].trim().replace(m.slashPipe,"|");return n}function A(l,e,t){let n=l.length;if(n===0)return"";let s=0;for(;s<n;){let i=l.charAt(n-s-1);if(i===e&&!t)s++;else if(i!==e&&t)s++;else break}return l.slice(0,n-s)}function de(l,e){if(l.indexOf(e[1])===-1)return-1;let t=0;for(let n=0;n<l.length;n++)if(l[n]==="\\")n++;else if(l[n]===e[0])t++;else if(l[n]===e[1]&&(t--,t<0))return n;return t>0?-2:-1}function me(l,e,t,n,s){let i=e.href,r=e.title||null,o=l[1].replace(s.other.outputLinkReplace,"$1");n.state.inLink=!0;let a={type:l[0].charAt(0)==="!"?"image":"link",raw:t,href:i,title:r,text:o,tokens:n.inlineTokens(o)};return n.state.inLink=!1,a}function rt(l,e,t){let n=l.match(t.other.indentCodeCompensation);if(n===null)return e;let s=n[1];return e.split(`
`).map(i=>{let r=i.match(t.other.beginningSpace);if(r===null)return i;let[o]=r;return o.length>=s.length?i.slice(s.length):i}).join(`
`)}var S=class{options;rules;lexer;constructor(e){this.options=e||w}space(e){let t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return{type:"space",raw:t[0]}}code(e){let t=this.rules.block.code.exec(e);if(t){let n=t[0].replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?n:A(n,`
`)}}}fences(e){let t=this.rules.block.fences.exec(e);if(t){let n=t[0],s=rt(n,t[3]||"",this.rules);return{type:"code",raw:n,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:s}}}heading(e){let t=this.rules.block.heading.exec(e);if(t){let n=t[2].trim();if(this.rules.other.endingHash.test(n)){let s=A(n,"#");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(n=s.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(e){let t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:A(t[0],`
`)}}blockquote(e){let t=this.rules.block.blockquote.exec(e);if(t){let n=A(t[0],`
`).split(`
`),s="",i="",r=[];for(;n.length>0;){let o=!1,a=[],c;for(c=0;c<n.length;c++)if(this.rules.other.blockquoteStart.test(n[c]))a.push(n[c]),o=!0;else if(!o)a.push(n[c]);else break;n=n.slice(c);let p=a.join(`
`),u=p.replace(this.rules.other.blockquoteSetextReplace,`
    $1`).replace(this.rules.other.blockquoteSetextReplace2,"");s=s?`${s}
${p}`:p,i=i?`${i}
${u}`:u;let d=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTokens(u,r,!0),this.lexer.state.top=d,n.length===0)break;let g=r.at(-1);if(g?.type==="code")break;if(g?.type==="blockquote"){let T=g,f=T.raw+`
`+n.join(`
`),y=this.blockquote(f);r[r.length-1]=y,s=s.substring(0,s.length-T.raw.length)+y.raw,i=i.substring(0,i.length-T.text.length)+y.text;break}else if(g?.type==="list"){let T=g,f=T.raw+`
`+n.join(`
`),y=this.list(f);r[r.length-1]=y,s=s.substring(0,s.length-g.raw.length)+y.raw,i=i.substring(0,i.length-T.raw.length)+y.raw,n=f.substring(r.at(-1).raw.length).split(`
`);continue}}return{type:"blockquote",raw:s,tokens:r,text:i}}}list(e){let t=this.rules.block.list.exec(e);if(t){let n=t[1].trim(),s=n.length>1,i={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");let r=this.rules.other.listItemRegex(n),o=!1;for(;e;){let c=!1,p="",u="";if(!(t=r.exec(e))||this.rules.block.hr.test(e))break;p=t[0],e=e.substring(p.length);let d=t[2].split(`
`,1)[0].replace(this.rules.other.listReplaceTabs,Z=>" ".repeat(3*Z.length)),g=e.split(`
`,1)[0],T=!d.trim(),f=0;if(this.options.pedantic?(f=2,u=d.trimStart()):T?f=t[1].length+1:(f=t[2].search(this.rules.other.nonSpaceChar),f=f>4?1:f,u=d.slice(f),f+=t[1].length),T&&this.rules.other.blankLine.test(g)&&(p+=g+`
`,e=e.substring(g.length+1),c=!0),!c){let Z=this.rules.other.nextBulletRegex(f),te=this.rules.other.hrRegex(f),ne=this.rules.other.fencesBeginRegex(f),se=this.rules.other.headingBeginRegex(f),xe=this.rules.other.htmlBeginRegex(f);for(;e;){let G=e.split(`
`,1)[0],C;if(g=G,this.options.pedantic?(g=g.replace(this.rules.other.listReplaceNesting,"  "),C=g):C=g.replace(this.rules.other.tabCharGlobal,"    "),ne.test(g)||se.test(g)||xe.test(g)||Z.test(g)||te.test(g))break;if(C.search(this.rules.other.nonSpaceChar)>=f||!g.trim())u+=`
`+C.slice(f);else{if(T||d.replace(this.rules.other.tabCharGlobal,"    ").search(this.rules.other.nonSpaceChar)>=4||ne.test(d)||se.test(d)||te.test(d))break;u+=`
`+g}!T&&!g.trim()&&(T=!0),p+=G+`
`,e=e.substring(G.length+1),d=C.slice(f)}}i.loose||(o?i.loose=!0:this.rules.other.doubleBlankLine.test(p)&&(o=!0));let y=null,ee;this.options.gfm&&(y=this.rules.other.listIsTask.exec(u),y&&(ee=y[0]!=="[ ] ",u=u.replace(this.rules.other.listReplaceTask,""))),i.items.push({type:"list_item",raw:p,task:!!y,checked:ee,loose:!1,text:u,tokens:[]}),i.raw+=p}let a=i.items.at(-1);if(a)a.raw=a.raw.trimEnd(),a.text=a.text.trimEnd();else return;i.raw=i.raw.trimEnd();for(let c=0;c<i.items.length;c++)if(this.lexer.state.top=!1,i.items[c].tokens=this.lexer.blockTokens(i.items[c].text,[]),!i.loose){let p=i.items[c].tokens.filter(d=>d.type==="space"),u=p.length>0&&p.some(d=>this.rules.other.anyLine.test(d.raw));i.loose=u}if(i.loose)for(let c=0;c<i.items.length;c++)i.items[c].loose=!0;return i}}html(e){let t=this.rules.block.html.exec(e);if(t)return{type:"html",block:!0,raw:t[0],pre:t[1]==="pre"||t[1]==="script"||t[1]==="style",text:t[0]}}def(e){let t=this.rules.block.def.exec(e);if(t){let n=t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal," "),s=t[2]?t[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",i=t[3]?t[3].substring(1,t[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):t[3];return{type:"def",tag:n,raw:t[0],href:s,title:i}}}table(e){let t=this.rules.block.table.exec(e);if(!t||!this.rules.other.tableDelimiter.test(t[2]))return;let n=Y(t[1]),s=t[2].replace(this.rules.other.tableAlignChars,"").split("|"),i=t[3]?.trim()?t[3].replace(this.rules.other.tableRowBlankLine,"").split(`
`):[],r={type:"table",raw:t[0],header:[],align:[],rows:[]};if(n.length===s.length){for(let o of s)this.rules.other.tableAlignRight.test(o)?r.align.push("right"):this.rules.other.tableAlignCenter.test(o)?r.align.push("center"):this.rules.other.tableAlignLeft.test(o)?r.align.push("left"):r.align.push(null);for(let o=0;o<n.length;o++)r.header.push({text:n[o],tokens:this.lexer.inline(n[o]),header:!0,align:r.align[o]});for(let o of i)r.rows.push(Y(o,r.header.length).map((a,c)=>({text:a,tokens:this.lexer.inline(a),header:!1,align:r.align[c]})));return r}}lheading(e){let t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:t[2].charAt(0)==="="?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){let t=this.rules.block.paragraph.exec(e);if(t){let n=t[1].charAt(t[1].length-1)===`
`?t[1].slice(0,-1):t[1];return{type:"paragraph",raw:t[0],text:n,tokens:this.lexer.inline(n)}}}text(e){let t=this.rules.block.text.exec(e);if(t)return{type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){let t=this.rules.inline.escape.exec(e);if(t)return{type:"escape",raw:t[0],text:t[1]}}tag(e){let t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&this.rules.other.startATag.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){let t=this.rules.inline.link.exec(e);if(t){let n=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;let r=A(n.slice(0,-1),"\\");if((n.length-r.length)%2===0)return}else{let r=de(t[2],"()");if(r===-2)return;if(r>-1){let a=(t[0].indexOf("!")===0?5:4)+t[1].length+r;t[2]=t[2].substring(0,r),t[0]=t[0].substring(0,a).trim(),t[3]=""}}let s=t[2],i="";if(this.options.pedantic){let r=this.rules.other.pedanticHrefTitle.exec(s);r&&(s=r[1],i=r[3])}else i=t[3]?t[3].slice(1,-1):"";return s=s.trim(),this.rules.other.startAngleBracket.test(s)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(n)?s=s.slice(1):s=s.slice(1,-1)),me(t,{href:s&&s.replace(this.rules.inline.anyPunctuation,"$1"),title:i&&i.replace(this.rules.inline.anyPunctuation,"$1")},t[0],this.lexer,this.rules)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){let s=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," "),i=t[s.toLowerCase()];if(!i){let r=n[0].charAt(0);return{type:"text",raw:r,text:r}}return me(n,i,n[0],this.lexer,this.rules)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s||s[3]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(s[1]||s[2]||"")||!n||this.rules.inline.punctuation.exec(n)){let r=[...s[0]].length-1,o,a,c=r,p=0,u=s[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(u.lastIndex=0,t=t.slice(-1*e.length+r);(s=u.exec(t))!=null;){if(o=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!o)continue;if(a=[...o].length,s[3]||s[4]){c+=a;continue}else if((s[5]||s[6])&&r%3&&!((r+a)%3)){p+=a;continue}if(c-=a,c>0)continue;a=Math.min(a,a+c+p);let d=[...s[0]][0].length,g=e.slice(0,r+s.index+d+a);if(Math.min(r,a)%2){let f=g.slice(1,-1);return{type:"em",raw:g,text:f,tokens:this.lexer.inlineTokens(f)}}let T=g.slice(2,-2);return{type:"strong",raw:g,text:T,tokens:this.lexer.inlineTokens(T)}}}}codespan(e){let t=this.rules.inline.code.exec(e);if(t){let n=t[2].replace(this.rules.other.newLineCharGlobal," "),s=this.rules.other.nonSpaceChar.test(n),i=this.rules.other.startingSpaceChar.test(n)&&this.rules.other.endingSpaceChar.test(n);return s&&i&&(n=n.substring(1,n.length-1)),{type:"codespan",raw:t[0],text:n}}}br(e){let t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){let t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){let t=this.rules.inline.autolink.exec(e);if(t){let n,s;return t[2]==="@"?(n=t[1],s="mailto:"+n):(n=t[1],s=n),{type:"link",raw:t[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let n,s;if(t[2]==="@")n=t[0],s="mailto:"+n;else{let i;do i=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??"";while(i!==t[0]);n=t[0],t[1]==="www."?s="http://"+t[0]:s=t[0]}return{type:"link",raw:t[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}inlineText(e){let t=this.rules.inline.text.exec(e);if(t){let n=this.lexer.state.inRawBlock;return{type:"text",raw:t[0],text:t[0],escaped:n}}}};var x=class l{tokens;options;state;tokenizer;inlineQueue;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||w,this.options.tokenizer=this.options.tokenizer||new S,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let t={other:m,block:B.normal,inline:P.normal};this.options.pedantic?(t.block=B.pedantic,t.inline=P.pedantic):this.options.gfm&&(t.block=B.gfm,this.options.breaks?t.inline=P.breaks:t.inline=P.gfm),this.tokenizer.rules=t}static get rules(){return{block:B,inline:P}}static lex(e,t){return new l(t).lex(e)}static lexInline(e,t){return new l(t).inlineTokens(e)}lex(e){e=e.replace(m.carriageReturn,`
`),this.blockTokens(e,this.tokens);for(let t=0;t<this.inlineQueue.length;t++){let n=this.inlineQueue[t];this.inlineTokens(n.src,n.tokens)}return this.inlineQueue=[],this.tokens}blockTokens(e,t=[],n=!1){for(this.options.pedantic&&(e=e.replace(m.tabCharGlobal,"    ").replace(m.spaceLine,""));e;){let s;if(this.options.extensions?.block?.some(r=>(s=r.call({lexer:this},e,t))?(e=e.substring(s.raw.length),t.push(s),!0):!1))continue;if(s=this.tokenizer.space(e)){e=e.substring(s.raw.length);let r=t.at(-1);s.raw.length===1&&r!==void 0?r.raw+=`
`:t.push(s);continue}if(s=this.tokenizer.code(e)){e=e.substring(s.raw.length);let r=t.at(-1);r?.type==="paragraph"||r?.type==="text"?(r.raw+=`
`+s.raw,r.text+=`
`+s.text,this.inlineQueue.at(-1).src=r.text):t.push(s);continue}if(s=this.tokenizer.fences(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.heading(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.hr(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.blockquote(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.list(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.html(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.def(e)){e=e.substring(s.raw.length);let r=t.at(-1);r?.type==="paragraph"||r?.type==="text"?(r.raw+=`
`+s.raw,r.text+=`
`+s.raw,this.inlineQueue.at(-1).src=r.text):this.tokens.links[s.tag]||(this.tokens.links[s.tag]={href:s.href,title:s.title});continue}if(s=this.tokenizer.table(e)){e=e.substring(s.raw.length),t.push(s);continue}if(s=this.tokenizer.lheading(e)){e=e.substring(s.raw.length),t.push(s);continue}let i=e;if(this.options.extensions?.startBlock){let r=1/0,o=e.slice(1),a;this.options.extensions.startBlock.forEach(c=>{a=c.call({lexer:this},o),typeof a=="number"&&a>=0&&(r=Math.min(r,a))}),r<1/0&&r>=0&&(i=e.substring(0,r+1))}if(this.state.top&&(s=this.tokenizer.paragraph(i))){let r=t.at(-1);n&&r?.type==="paragraph"?(r.raw+=`
`+s.raw,r.text+=`
`+s.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=r.text):t.push(s),n=i.length!==e.length,e=e.substring(s.raw.length);continue}if(s=this.tokenizer.text(e)){e=e.substring(s.raw.length);let r=t.at(-1);r?.type==="text"?(r.raw+=`
`+s.raw,r.text+=`
`+s.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=r.text):t.push(s);continue}if(e){let r="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(r);break}else throw new Error(r)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n=e,s=null;if(this.tokens.links){let o=Object.keys(this.tokens.links);if(o.length>0)for(;(s=this.tokenizer.rules.inline.reflinkSearch.exec(n))!=null;)o.includes(s[0].slice(s[0].lastIndexOf("[")+1,-1))&&(n=n.slice(0,s.index)+"["+"a".repeat(s[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;(s=this.tokenizer.rules.inline.anyPunctuation.exec(n))!=null;)n=n.slice(0,s.index)+"++"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);for(;(s=this.tokenizer.rules.inline.blockSkip.exec(n))!=null;)n=n.slice(0,s.index)+"["+"a".repeat(s[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);let i=!1,r="";for(;e;){i||(r=""),i=!1;let o;if(this.options.extensions?.inline?.some(c=>(o=c.call({lexer:this},e,t))?(e=e.substring(o.raw.length),t.push(o),!0):!1))continue;if(o=this.tokenizer.escape(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.tag(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.link(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(o.raw.length);let c=t.at(-1);o.type==="text"&&c?.type==="text"?(c.raw+=o.raw,c.text+=o.text):t.push(o);continue}if(o=this.tokenizer.emStrong(e,n,r)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.codespan(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.br(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.del(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.autolink(e)){e=e.substring(o.raw.length),t.push(o);continue}if(!this.state.inLink&&(o=this.tokenizer.url(e))){e=e.substring(o.raw.length),t.push(o);continue}let a=e;if(this.options.extensions?.startInline){let c=1/0,p=e.slice(1),u;this.options.extensions.startInline.forEach(d=>{u=d.call({lexer:this},p),typeof u=="number"&&u>=0&&(c=Math.min(c,u))}),c<1/0&&c>=0&&(a=e.substring(0,c+1))}if(o=this.tokenizer.inlineText(a)){e=e.substring(o.raw.length),o.raw.slice(-1)!=="_"&&(r=o.raw.slice(-1)),i=!0;let c=t.at(-1);c?.type==="text"?(c.raw+=o.raw,c.text+=o.text):t.push(o);continue}if(e){let c="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(c);break}else throw new Error(c)}}return t}};var $=class{options;parser;constructor(e){this.options=e||w}space(e){return""}code({text:e,lang:t,escaped:n}){let s=(t||"").match(m.notSpaceStart)?.[0],i=e.replace(m.endingNewline,"")+`
`;return s?'<pre><code class="language-'+R(s)+'">'+(n?i:R(i,!0))+`</code></pre>
`:"<pre><code>"+(n?i:R(i,!0))+`</code></pre>
`}blockquote({tokens:e}){return`<blockquote>
${this.parser.parse(e)}</blockquote>
`}html({text:e}){return e}heading({tokens:e,depth:t}){return`<h${t}>${this.parser.parseInline(e)}</h${t}>
`}hr(e){return`<hr>
`}list(e){let t=e.ordered,n=e.start,s="";for(let o=0;o<e.items.length;o++){let a=e.items[o];s+=this.listitem(a)}let i=t?"ol":"ul",r=t&&n!==1?' start="'+n+'"':"";return"<"+i+r+`>
`+s+"</"+i+`>
`}listitem(e){let t="";if(e.task){let n=this.checkbox({checked:!!e.checked});e.loose?e.tokens[0]?.type==="paragraph"?(e.tokens[0].text=n+" "+e.tokens[0].text,e.tokens[0].tokens&&e.tokens[0].tokens.length>0&&e.tokens[0].tokens[0].type==="text"&&(e.tokens[0].tokens[0].text=n+" "+R(e.tokens[0].tokens[0].text),e.tokens[0].tokens[0].escaped=!0)):e.tokens.unshift({type:"text",raw:n+" ",text:n+" ",escaped:!0}):t+=n+" "}return t+=this.parser.parse(e.tokens,!!e.loose),`<li>${t}</li>
`}checkbox({checked:e}){return"<input "+(e?'checked="" ':"")+'disabled="" type="checkbox">'}paragraph({tokens:e}){return`<p>${this.parser.parseInline(e)}</p>
`}table(e){let t="",n="";for(let i=0;i<e.header.length;i++)n+=this.tablecell(e.header[i]);t+=this.tablerow({text:n});let s="";for(let i=0;i<e.rows.length;i++){let r=e.rows[i];n="";for(let o=0;o<r.length;o++)n+=this.tablecell(r[o]);s+=this.tablerow({text:n})}return s&&(s=`<tbody>${s}</tbody>`),`<table>
<thead>
`+t+`</thead>
`+s+`</table>
`}tablerow({text:e}){return`<tr>
${e}</tr>
`}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+`</${n}>
`}strong({tokens:e}){return`<strong>${this.parser.parseInline(e)}</strong>`}em({tokens:e}){return`<em>${this.parser.parseInline(e)}</em>`}codespan({text:e}){return`<code>${R(e,!0)}</code>`}br(e){return"<br>"}del({tokens:e}){return`<del>${this.parser.parseInline(e)}</del>`}link({href:e,title:t,tokens:n}){let s=this.parser.parseInline(n),i=V(e);if(i===null)return s;e=i;let r='<a href="'+e+'"';return t&&(r+=' title="'+R(t)+'"'),r+=">"+s+"</a>",r}image({href:e,title:t,text:n,tokens:s}){s&&(n=this.parser.parseInline(s,this.parser.textRenderer));let i=V(e);if(i===null)return R(n);e=i;let r=`<img src="${e}" alt="${n}"`;return t&&(r+=` title="${R(t)}"`),r+=">",r}text(e){return"tokens"in e&&e.tokens?this.parser.parseInline(e.tokens):"escaped"in e&&e.escaped?e.text:R(e.text)}};var _=class{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return""+e}image({text:e}){return""+e}br(){return""}};var b=class l{options;renderer;textRenderer;constructor(e){this.options=e||w,this.options.renderer=this.options.renderer||new $,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new _}static parse(e,t){return new l(t).parse(e)}static parseInline(e,t){return new l(t).parseInline(e)}parse(e,t=!0){let n="";for(let s=0;s<e.length;s++){let i=e[s];if(this.options.extensions?.renderers?.[i.type]){let o=i,a=this.options.extensions.renderers[o.type].call({parser:this},o);if(a!==!1||!["space","hr","heading","code","table","blockquote","list","html","paragraph","text"].includes(o.type)){n+=a||"";continue}}let r=i;switch(r.type){case"space":{n+=this.renderer.space(r);continue}case"hr":{n+=this.renderer.hr(r);continue}case"heading":{n+=this.renderer.heading(r);continue}case"code":{n+=this.renderer.code(r);continue}case"table":{n+=this.renderer.table(r);continue}case"blockquote":{n+=this.renderer.blockquote(r);continue}case"list":{n+=this.renderer.list(r);continue}case"html":{n+=this.renderer.html(r);continue}case"paragraph":{n+=this.renderer.paragraph(r);continue}case"text":{let o=r,a=this.renderer.text(o);for(;s+1<e.length&&e[s+1].type==="text";)o=e[++s],a+=`
`+this.renderer.text(o);t?n+=this.renderer.paragraph({type:"paragraph",raw:a,text:a,tokens:[{type:"text",raw:a,text:a,escaped:!0}]}):n+=a;continue}default:{let o='Token with "'+r.type+'" type was not found.';if(this.options.silent)return console.error(o),"";throw new Error(o)}}}return n}parseInline(e,t=this.renderer){let n="";for(let s=0;s<e.length;s++){let i=e[s];if(this.options.extensions?.renderers?.[i.type]){let o=this.options.extensions.renderers[i.type].call({parser:this},i);if(o!==!1||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(i.type)){n+=o||"";continue}}let r=i;switch(r.type){case"escape":{n+=t.text(r);break}case"html":{n+=t.html(r);break}case"link":{n+=t.link(r);break}case"image":{n+=t.image(r);break}case"strong":{n+=t.strong(r);break}case"em":{n+=t.em(r);break}case"codespan":{n+=t.codespan(r);break}case"br":{n+=t.br(r);break}case"del":{n+=t.del(r);break}case"text":{n+=t.text(r);break}default:{let o='Token with "'+r.type+'" type was not found.';if(this.options.silent)return console.error(o),"";throw new Error(o)}}}return n}};var L=class{options;block;constructor(e){this.options=e||w}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}provideLexer(){return this.block?x.lex:x.lexInline}provideParser(){return this.block?b.parse:b.parseInline}};var E=class{defaults=z();options=this.setOptions;parse=this.parseMarkdown(!0);parseInline=this.parseMarkdown(!1);Parser=b;Renderer=$;TextRenderer=_;Lexer=x;Tokenizer=S;Hooks=L;constructor(...e){this.use(...e)}walkTokens(e,t){let n=[];for(let s of e)switch(n=n.concat(t.call(this,s)),s.type){case"table":{let i=s;for(let r of i.header)n=n.concat(this.walkTokens(r.tokens,t));for(let r of i.rows)for(let o of r)n=n.concat(this.walkTokens(o.tokens,t));break}case"list":{let i=s;n=n.concat(this.walkTokens(i.items,t));break}default:{let i=s;this.defaults.extensions?.childTokens?.[i.type]?this.defaults.extensions.childTokens[i.type].forEach(r=>{let o=i[r].flat(1/0);n=n.concat(this.walkTokens(o,t))}):i.tokens&&(n=n.concat(this.walkTokens(i.tokens,t)))}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let s={...n};if(s.async=this.defaults.async||s.async||!1,n.extensions&&(n.extensions.forEach(i=>{if(!i.name)throw new Error("extension name required");if("renderer"in i){let r=t.renderers[i.name];r?t.renderers[i.name]=function(...o){let a=i.renderer.apply(this,o);return a===!1&&(a=r.apply(this,o)),a}:t.renderers[i.name]=i.renderer}if("tokenizer"in i){if(!i.level||i.level!=="block"&&i.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let r=t[i.level];r?r.unshift(i.tokenizer):t[i.level]=[i.tokenizer],i.start&&(i.level==="block"?t.startBlock?t.startBlock.push(i.start):t.startBlock=[i.start]:i.level==="inline"&&(t.startInline?t.startInline.push(i.start):t.startInline=[i.start]))}"childTokens"in i&&i.childTokens&&(t.childTokens[i.name]=i.childTokens)}),s.extensions=t),n.renderer){let i=this.defaults.renderer||new $(this.defaults);for(let r in n.renderer){if(!(r in i))throw new Error(`renderer '${r}' does not exist`);if(["options","parser"].includes(r))continue;let o=r,a=n.renderer[o],c=i[o];i[o]=(...p)=>{let u=a.apply(i,p);return u===!1&&(u=c.apply(i,p)),u||""}}s.renderer=i}if(n.tokenizer){let i=this.defaults.tokenizer||new S(this.defaults);for(let r in n.tokenizer){if(!(r in i))throw new Error(`tokenizer '${r}' does not exist`);if(["options","rules","lexer"].includes(r))continue;let o=r,a=n.tokenizer[o],c=i[o];i[o]=(...p)=>{let u=a.apply(i,p);return u===!1&&(u=c.apply(i,p)),u}}s.tokenizer=i}if(n.hooks){let i=this.defaults.hooks||new L;for(let r in n.hooks){if(!(r in i))throw new Error(`hook '${r}' does not exist`);if(["options","block"].includes(r))continue;let o=r,a=n.hooks[o],c=i[o];L.passThroughHooks.has(r)?i[o]=p=>{if(this.defaults.async)return Promise.resolve(a.call(i,p)).then(d=>c.call(i,d));let u=a.call(i,p);return c.call(i,u)}:i[o]=(...p)=>{let u=a.apply(i,p);return u===!1&&(u=c.apply(i,p)),u}}s.hooks=i}if(n.walkTokens){let i=this.defaults.walkTokens,r=n.walkTokens;s.walkTokens=function(o){let a=[];return a.push(r.call(this,o)),i&&(a=a.concat(i.call(this,o))),a}}this.defaults={...this.defaults,...s}}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return x.lex(e,t??this.defaults)}parser(e,t){return b.parse(e,t??this.defaults)}parseMarkdown(e){return(n,s)=>{let i={...s},r={...this.defaults,...i},o=this.onError(!!r.silent,!!r.async);if(this.defaults.async===!0&&i.async===!1)return o(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof n>"u"||n===null)return o(new Error("marked(): input parameter is undefined or null"));if(typeof n!="string")return o(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));r.hooks&&(r.hooks.options=r,r.hooks.block=e);let a=r.hooks?r.hooks.provideLexer():e?x.lex:x.lexInline,c=r.hooks?r.hooks.provideParser():e?b.parse:b.parseInline;if(r.async)return Promise.resolve(r.hooks?r.hooks.preprocess(n):n).then(p=>a(p,r)).then(p=>r.hooks?r.hooks.processAllTokens(p):p).then(p=>r.walkTokens?Promise.all(this.walkTokens(p,r.walkTokens)).then(()=>p):p).then(p=>c(p,r)).then(p=>r.hooks?r.hooks.postprocess(p):p).catch(o);try{r.hooks&&(n=r.hooks.preprocess(n));let p=a(n,r);r.hooks&&(p=r.hooks.processAllTokens(p)),r.walkTokens&&this.walkTokens(p,r.walkTokens);let u=c(p,r);return r.hooks&&(u=r.hooks.postprocess(u)),u}catch(p){return o(p)}}}onError(e,t){return n=>{if(n.message+=`
Please report this to https://github.com/markedjs/marked.`,e){let s="<p>An error occurred:</p><pre>"+R(n.message+"",!0)+"</pre>";return t?Promise.resolve(s):s}if(t)return Promise.reject(n);throw n}}};var M=new E;function k(l,e){return M.parse(l,e)}k.options=k.setOptions=function(l){return M.setOptions(l),k.defaults=M.defaults,N(k.defaults),k};k.getDefaults=z;k.defaults=w;k.use=function(...l){return M.use(...l),k.defaults=M.defaults,N(k.defaults),k};k.walkTokens=function(l,e){return M.walkTokens(l,e)};k.parseInline=M.parseInline;k.Parser=b;k.parser=b.parse;k.Renderer=$;k.TextRenderer=_;k.Lexer=x;k.lexer=x.lex;k.Tokenizer=S;k.Hooks=L;k.parse=k;var it=k.options,ot=k.setOptions,lt=k.use,at=k.walkTokens,ct=k.parseInline,pt=k,ut=b.parse,ht=x.lex;

if(__exports != exports)module.exports = exports;return module.exports}));

(function() {
    /* global marked */ // ESLint directive for global 'marked'
    'use strict';
    console.log('MY SCRIPT IS TRYING TO RUN (v0.3.1)');

    const SCRIPT_PREFIX = 'yt_gemini_summarizer_';
    const GEMINI_API_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/models";

    const HIDE_BUTTON_DELAY = 2000;
    const HIDE_BUTTON_DELAY_FAST = 500;
    const DIAGNOSTIC_INTERVAL_MS = 3000;

    const SUPPORTED_LANGUAGES = [
        { value: 'Russian', display: 'Russian', isRTL: false },
        { value: 'English', display: 'English', isRTL: false },
        { value: 'German', display: 'German', isRTL: false },
        { value: 'French', display: 'French', isRTL: false },
        { value: 'Italian', display: 'Italian', isRTL: false },
        { value: 'Spanish', display: 'Spanish', isRTL: false },
        { value: 'Hebrew', display: 'Hebrew', isRTL: true },
        { value: 'Yiddish', display: 'Yiddish', isRTL: true },
        { value: 'Arabic', display: 'Arabic', isRTL: true },
        { value: 'Chinese', display: 'Chinese', isRTL: false },
        { value: 'Korean', display: 'Korean', isRTL: false },
        { value: 'Japanese', display: 'Japanese', isRTL: false },
        { value: 'Czech', display: 'Czech', isRTL: false },
        { value: 'Polish', display: 'Polish', isRTL: false }
    ];
    const DEFAULT_LANGUAGE = 'Russian';

    let apiKey = '';
    let models = [];
    let selectedModel = '';
    let selectedLanguage = DEFAULT_LANGUAGE;
    let systemPrompt = '';

    let panel, apiKeyInput, modelSelect, languageSelect, systemPromptTextarea, summarizeButton, summaryOutput, statusDiv, fetchModelsButton;
    let togglePanelButton;
    let isPanelVisible = false;
    let playerContainer = null;

    let hideButtonTimer = null;
    let diagnosticIntervalId = null;

    // Initialize Marked.js options
    if (typeof marked !== 'undefined') {
        marked.setOptions({
            gfm: true,
            breaks: true,
            sanitize: false, // Relying on Trusted Types for security if active
            smartypants: true
        });
    } else {
        console.error(SCRIPT_PREFIX + "Marked.js library not loaded!");
    }

    // Initialize Trusted Types policy for summary HTML
    let summaryHtmlPolicy;
    if (window.trustedTypes && window.trustedTypes.createPolicy) {
        try {
            summaryHtmlPolicy = window.trustedTypes.createPolicy(SCRIPT_PREFIX + 'summaryHTML#script', {
                createHTML: (string) => {
                    // Basic sanitization can be added here if needed,
                    // but for now, we assume marked.js output (if sanitize:true in marked)
                    // or Gemini's Markdown is relatively safe.
                    // For a more robust solution, a dedicated sanitizer library (like DOMPurify)
                    // should be used here if marked.js's sanitize option is false.
                    return string;
                }
            });
        } catch (e) {
            console.warn(SCRIPT_PREFIX + "Could not create a new Trusted Types policy (it might already exist or be blocked):", e.message);
            summaryHtmlPolicy = null;
        }
    } else {
        summaryHtmlPolicy = null; // Trusted Types not supported
    }


    function loadSettings() {
        apiKey = GM_getValue(SCRIPT_PREFIX + 'api_key', '');
        selectedModel = GM_getValue(SCRIPT_PREFIX + 'selected_model', '');
        selectedLanguage = GM_getValue(SCRIPT_PREFIX + 'selected_language', DEFAULT_LANGUAGE);
        systemPrompt = GM_getValue(SCRIPT_PREFIX + 'system_prompt', '');
        isPanelVisible = GM_getValue(SCRIPT_PREFIX + 'is_panel_visible', false);
        if (apiKeyInput) apiKeyInput.value = apiKey;
        if (languageSelect) {
            languageSelect.value = selectedLanguage;
        }
        if (systemPromptTextarea) systemPromptTextarea.value = systemPrompt;
    }

    function saveSettings() {
        GM_setValue(SCRIPT_PREFIX + 'api_key', apiKey);
        GM_setValue(SCRIPT_PREFIX + 'selected_model', selectedModel);
        GM_setValue(SCRIPT_PREFIX + 'selected_language', selectedLanguage);
        GM_setValue(SCRIPT_PREFIX + 'system_prompt', systemPrompt);
        GM_setValue(SCRIPT_PREFIX + 'is_panel_visible', isPanelVisible);
    }

    function createGUI() {
        panel = document.createElement('div');
        panel.id = SCRIPT_PREFIX + 'panel';
        panel.style.display = isPanelVisible ? 'block' : 'none';

        const title = document.createElement('h3');
        title.textContent = 'Gemini Video Summarizer';
        panel.appendChild(title);

        const apiKeyDiv = document.createElement('div');
        const apiKeyLabel = document.createElement('label');
        apiKeyLabel.htmlFor = SCRIPT_PREFIX + 'api_key_input';
        apiKeyLabel.textContent = 'Gemini API Key:';
        apiKeyDiv.appendChild(apiKeyLabel);
        apiKeyInput = document.createElement('input');
        apiKeyInput.type = 'password';
        apiKeyInput.id = SCRIPT_PREFIX + 'api_key_input';
        apiKeyDiv.appendChild(apiKeyInput);
        fetchModelsButton = document.createElement('button');
        fetchModelsButton.id = SCRIPT_PREFIX + 'fetch_models_button';
        fetchModelsButton.textContent = 'Save & Fetch Models';
        apiKeyDiv.appendChild(fetchModelsButton);
        panel.appendChild(apiKeyDiv);

        const modelDiv = document.createElement('div');
        const modelLabel = document.createElement('label');
        modelLabel.htmlFor = SCRIPT_PREFIX + 'model_select';
        modelLabel.textContent = 'Select Model:';
        modelDiv.appendChild(modelLabel);
        modelSelect = document.createElement('select');
        modelSelect.id = SCRIPT_PREFIX + 'model_select';
        modelDiv.appendChild(modelSelect);
        panel.appendChild(modelDiv);

        const languageDiv = document.createElement('div');
        const languageLabel = document.createElement('label');
        languageLabel.htmlFor = SCRIPT_PREFIX + 'language_select';
        languageLabel.textContent = 'Select Summary Language:';
        languageDiv.appendChild(languageLabel);
        languageSelect = document.createElement('select');
        languageSelect.id = SCRIPT_PREFIX + 'language_select';
        SUPPORTED_LANGUAGES.forEach(lang => {
            const option = document.createElement('option');
            option.value = lang.value;
            option.textContent = lang.display;
            languageSelect.appendChild(option);
        });
        languageSelect.value = selectedLanguage;
        languageDiv.appendChild(languageSelect);
        panel.appendChild(languageDiv);

        const systemPromptDiv = document.createElement('div');
        const systemPromptLabel = document.createElement('label');
        systemPromptLabel.htmlFor = SCRIPT_PREFIX + 'system_prompt_textarea';
        systemPromptLabel.textContent = 'System Prompt (Optional):';
        systemPromptDiv.appendChild(systemPromptLabel);
        systemPromptTextarea = document.createElement('textarea');
        systemPromptTextarea.id = SCRIPT_PREFIX + 'system_prompt_textarea';
        systemPromptTextarea.placeholder = `E.g., "Summarize this video in 5 bullet points."\nIf empty, a default summary prompt is used.`;
        systemPromptTextarea.rows = 3;
        systemPromptDiv.appendChild(systemPromptTextarea);
        panel.appendChild(systemPromptDiv);

        const summarizeDiv = document.createElement('div');
        summarizeButton = document.createElement('button');
        summarizeButton.id = SCRIPT_PREFIX + 'summarize_button';
        summarizeButton.textContent = 'Summarize Video';
        summarizeButton.disabled = true;
        summarizeDiv.appendChild(summarizeButton);
        panel.appendChild(summarizeDiv);

        statusDiv = document.createElement('div');
        statusDiv.id = SCRIPT_PREFIX + 'status_div';
        statusDiv.style.marginTop = '5px';
        statusDiv.style.fontStyle = 'italic';
        panel.appendChild(statusDiv);

        const summaryTitle = document.createElement('h4');
        summaryTitle.textContent = 'Summary:';
        panel.appendChild(summaryTitle);

        summaryOutput = document.createElement('div');
        summaryOutput.id = SCRIPT_PREFIX + 'summary_output';
        summaryOutput.dir = 'ltr';
        summaryOutput.style.textAlign = 'left';
        panel.appendChild(summaryOutput);

        document.body.appendChild(panel);

        fetchModelsButton.addEventListener('click', handleFetchModelsClick);
        modelSelect.addEventListener('change', (e) => {
            selectedModel = e.target.value;
            saveSettings();
            updateSummarizeButtonState();
        });
        languageSelect.addEventListener('change', (e) => {
            selectedLanguage = e.target.value;
            saveSettings();
            const languageInfo = SUPPORTED_LANGUAGES.find(lang => lang.value === selectedLanguage);
            if (summaryOutput.innerHTML.trim() !== "") {
                 if (languageInfo && languageInfo.isRTL) {
                    summaryOutput.dir = 'rtl';
                    summaryOutput.style.textAlign = 'right';
                } else {
                    summaryOutput.dir = 'ltr';
                    summaryOutput.style.textAlign = 'left';
                }
            }
        });
        systemPromptTextarea.addEventListener('input', (e) => {
            systemPrompt = e.target.value;
            saveSettings();
        });
        summarizeButton.addEventListener('click', handleSummarizeClick);
    }

    function createToggleButton() {
        togglePanelButton = document.createElement('button');
        togglePanelButton.id = SCRIPT_PREFIX + 'toggle_button';
        togglePanelButton.textContent = 'Summarize';
        togglePanelButton.title = 'Toggle Summarizer Panel';
        togglePanelButton.addEventListener('click', handleTogglePanelClick);
    }

    function handleTogglePanelClick() {
        isPanelVisible = !isPanelVisible;
        panel.style.display = isPanelVisible ? 'block' : 'none';
        saveSettings();
        console.log(SCRIPT_PREFIX + "Panel visibility toggled. Is visible:", isPanelVisible);
        if (isPanelVisible && panel.matches(':hover')) {
            showToggleButton();
        } else if (!isPanelVisible && playerContainer && !playerContainer.matches(':hover')) {
            startHideButtonTimer(0);
        }
    }

    function showToggleButton() {
        if (!togglePanelButton) {
            console.warn(SCRIPT_PREFIX + "showToggleButton called but togglePanelButton is null!");
            return;
        }
        clearTimeout(hideButtonTimer);
        hideButtonTimer = null;
        if (togglePanelButton.style.opacity !== '1') {
            togglePanelButton.style.opacity = '1';
            togglePanelButton.style.pointerEvents = 'auto';
        }
    }

    function hideToggleButton() {
        if (!togglePanelButton) {
            console.warn(SCRIPT_PREFIX + "hideToggleButton called but togglePanelButton is null!");
            return;
        }
        if (togglePanelButton.style.opacity !== '0') {
            togglePanelButton.style.opacity = '0';
            togglePanelButton.style.pointerEvents = 'none';
        }
    }

    function startHideButtonTimer(delay = HIDE_BUTTON_DELAY) {
        clearTimeout(hideButtonTimer);
        hideButtonTimer = setTimeout(() => {
            if (playerContainer && playerContainer.matches(':hover')) return;
            if (panel && panel.matches(':hover') && isPanelVisible) return;
            if (togglePanelButton && togglePanelButton.matches(':hover')) return;
            hideToggleButton();
        }, delay);
    }

    function addStyles() {
        GM_addStyle(`
            #${SCRIPT_PREFIX}panel {
                position: fixed; top: 60px; right: 10px; width: 350px;
                background-color: #f9f9f9; border: 1px solid #ccc; padding: 15px;
                z-index: 9999; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);
                font-family: Arial, sans-serif; font-size: 13px;
            }
            #${SCRIPT_PREFIX}toggle_button {
                position: absolute; bottom: 55px; left: 15px;
                padding: 5px 8px; background-color: rgba(20, 20, 20, 0.7); color: white;
                border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 3px;
                cursor: pointer; z-index: 65; box-shadow: 0 1px 3px rgba(0,0,0,0.3);
                font-size: 12px; line-height: 1;
                opacity: 0;
                pointer-events: none;
                transition: opacity 0.2s ease-in-out;
            }
            #${SCRIPT_PREFIX}toggle_button:hover {
                background-color: rgba(40, 40, 40, 0.9);
            }
            #movie_player.relative-positioning,
            .html5-video-player.relative-positioning,
            ytd-player.relative-positioning {
                position: relative !important;
            }
            #${SCRIPT_PREFIX}panel h3, #${SCRIPT_PREFIX}panel h4 { margin-top: 0; margin-bottom: 10px; color: #333; }
            #${SCRIPT_PREFIX}panel label { display: block; margin-bottom: 3px; font-weight: bold; color: #555; }
            #${SCRIPT_PREFIX}panel div { margin-bottom: 10px; }
            #${SCRIPT_PREFIX}panel input[type="password"],
            #${SCRIPT_PREFIX}panel select { padding: 6px; border: 1px solid #ddd; border-radius: 3px; box-sizing: border-box; width: 100%;}
            #${SCRIPT_PREFIX}api_key_input { width: calc(100% - 165px); margin-right: 5px; vertical-align: middle; }
            #${SCRIPT_PREFIX}system_prompt_textarea { font-family: Arial, sans-serif; font-size: 12px; resize: vertical; width: 100%; }
            #${SCRIPT_PREFIX}summary_output {
                width: 100%;
                height: 150px;
                background-color: #fff;
                border: 1px solid #ddd;
                border-radius: 3px;
                padding: 6px;
                box-sizing: border-box;
                overflow-y: auto;
                white-space: pre-wrap;
                word-wrap: break-word;
                font-size: 12px;
                line-height: 1.4;
            }
            #${SCRIPT_PREFIX}panel button { background-color: #4CAF50; color: white; padding: 8px 12px; border: none; border-radius: 3px; cursor: pointer; margin-right: 5px; vertical-align: middle; }
            #${SCRIPT_PREFIX}panel button:last-child { margin-right: 0; }
            #${SCRIPT_PREFIX}panel button:hover { background-color: #45a049; }
            #${SCRIPT_PREFIX}panel button:disabled { background-color: #ccc; cursor: not-allowed; }
        `);
    }

    function updateStatus(message, isError = false) {
        if (statusDiv) {
            statusDiv.textContent = message;
            statusDiv.style.color = isError ? 'red' : 'green';
        }
    }

    function handleFetchModelsClick() {
        const newApiKey = apiKeyInput.value.trim();
        if (!newApiKey) {
            updateStatus("API Key cannot be empty.", true);
            return;
        }
        apiKey = newApiKey;
        saveSettings();
        updateStatus("API Key saved. Fetching models...");
        fetchAndPopulateModels();
    }

    function fetchAndPopulateModels() {
        if (!apiKey) {
            updateStatus("API Key is not set. Cannot fetch models.", true);
            populateModelDropdown([]);
            return;
        }
        updateStatus("Fetching models...");
        GM_xmlhttpRequest({
            method: "GET",
            url: `${GEMINI_API_BASE_URL}?key=${apiKey}`,
            onload: function(response) {
                if (response.status === 200) {
                    try {
                        const data = JSON.parse(response.responseText);
                        models = data.models.filter(model =>
                            model.supportedGenerationMethods && model.supportedGenerationMethods.includes("generateContent")
                        );
                        if (models.length === 0) {
                            updateStatus("No models supporting 'generateContent' found for this API key.", true);
                            populateModelDropdown([]);
                            return;
                        }
                        updateStatus(`Found ${models.length} compatible models.`, false);
                        populateModelDropdown(models);
                    } catch (e) {
                        updateStatus("Error parsing models response: " + e.message, true);
                        console.error(SCRIPT_PREFIX + "Error parsing models response:", e, response.responseText);
                        populateModelDropdown([]);
                    }
                } else {
                    let errorMsg = `Error fetching models: ${response.status}`;
                    try {
                        const errorData = JSON.parse(response.responseText);
                        if (errorData.error && errorData.error.message) {
                            errorMsg += ` - ${errorData.error.message}`;
                        }
                    } catch (e) { /* ignore */ }
                    updateStatus(errorMsg, true);
                    console.error(SCRIPT_PREFIX + "Error fetching models:", response);
                    populateModelDropdown([]);
                }
                updateSummarizeButtonState();
            },
            onerror: function(response) {
                updateStatus("Network error fetching models: " + response.statusText, true);
                console.error(SCRIPT_PREFIX + "Network error fetching models:", response);
                populateModelDropdown([]);
                updateSummarizeButtonState();
            }
        });
    }

    function populateModelDropdown(modelsToPopulate) {
        while (modelSelect.firstChild) {
            modelSelect.removeChild(modelSelect.firstChild);
        }
        if (modelsToPopulate.length === 0) {
            const option = document.createElement('option');
            option.value = "";
            option.textContent = "No models available";
            modelSelect.appendChild(option);
            modelSelect.disabled = true;
            selectedModel = "";
        } else {
            modelsToPopulate.forEach(model => {
                const option = document.createElement('option');
                option.value = model.name;
                option.textContent = model.displayName + ` (${model.name.split('/')[1]})`;
                modelSelect.appendChild(option);
            });
            modelSelect.disabled = false;
            let foundPrevious = false;
            if (selectedModel) {
                for (let i = 0; i < modelSelect.options.length; i++) {
                    if (modelSelect.options[i].value === selectedModel) {
                        modelSelect.selectedIndex = i;
                        foundPrevious = true;
                        break;
                    }
                }
            }
            if (!foundPrevious) {
                let flashModelIndex = modelsToPopulate.findIndex(m => m.name.includes("flash"));
                if (flashModelIndex !== -1) {
                    modelSelect.selectedIndex = flashModelIndex;
                } else if (modelSelect.options.length > 0) {
                    modelSelect.selectedIndex = 0;
                }
            }
            selectedModel = modelSelect.value;
        }
        saveSettings();
        updateSummarizeButtonState();
    }

    function updateSummarizeButtonState() {
        if (summarizeButton) {
            summarizeButton.disabled = !(apiKey && selectedModel && models.length > 0 && modelSelect.value && !modelSelect.disabled && selectedLanguage);
        }
    }

    function setSummaryTextAndDirection(text, languageValue) {
        console.log(SCRIPT_PREFIX + "Raw text received for summary:", text);

        if (typeof marked === 'undefined') {
            summaryOutput.innerText = text;
            console.error(SCRIPT_PREFIX + "Marked.js not available, displaying raw text.");
        } else {
            try {
                const htmlString = marked.parse(text);
                console.log(SCRIPT_PREFIX + "HTML string after marked.parse():", htmlString);

                if (summaryHtmlPolicy) {
                    summaryOutput.innerHTML = summaryHtmlPolicy.createHTML(htmlString);
                } else if (window.trustedTypes && window.trustedTypes.emptyHTML !== undefined) {
                     // Check for emptyHTML as a more reliable way to see if Trusted Types are active and policies are enforced
                    console.warn(SCRIPT_PREFIX + "Trusted Types policy not available or not created, but Trusted Types are enforced. Falling back to innerText for security.");
                    summaryOutput.innerText = text;
                } else {
                    // Trusted Types not supported or not enforced, assign HTML directly
                    summaryOutput.innerHTML = htmlString;
                }
                console.log(SCRIPT_PREFIX + "summaryOutput.innerHTML (after policy/direct assignment):", summaryOutput.innerHTML);

            } catch (e) {
                console.error(SCRIPT_PREFIX + "Error parsing Markdown or applying TrustedHTML:", e);
                summaryOutput.innerText = text; // Fallback on any error
            }
        }

        const languageInfo = SUPPORTED_LANGUAGES.find(lang => lang.value === languageValue);
        if (languageInfo && languageInfo.isRTL) {
            summaryOutput.dir = 'rtl';
            summaryOutput.style.textAlign = 'right';
        } else {
            summaryOutput.dir = 'ltr';
            summaryOutput.style.textAlign = 'left';
        }
    }

    async function handleSummarizeClick() {
        updateStatus("Starting summarization...", false);
        setSummaryTextAndDirection("", selectedLanguage);

        if (!apiKey || !selectedModel || !modelSelect.value || !selectedLanguage) {
            updateStatus("API Key, Model, or Language not selected correctly.", true);
            return;
        }
        const currentSelectedModel = modelSelect.value;
        const currentSelectedLanguage = languageSelect.value;
        const currentSystemPrompt = systemPromptTextarea.value.trim();

        const transcript = await getYouTubeTranscript();
        if (!transcript) {
            updateStatus("Could not retrieve video transcript.", true);
            return;
        }
        updateStatus(`Transcript retrieved. Sending to Gemini API...`, false);

        let promptText;
        if (currentSystemPrompt) {
            promptText = `${currentSystemPrompt}\n\nVideo Transcript:\n${transcript}`;
        } else {
            promptText = `Please summarize the following video transcript in ${currentSelectedLanguage}. You can use Markdown for formatting if appropriate (e.g., lists, bold text).\n\nTranscript:\n${transcript}`;
        }


        GM_xmlhttpRequest({
            method: "POST",
            url: `${GEMINI_API_BASE_URL}/${currentSelectedModel.replace("models/", "")}:generateContent?key=${apiKey}`,
            headers: {
                "Content-Type": "application/json"
            },
            data: JSON.stringify({
                "contents": [{
                    "parts": [{
                        "text": promptText
                    }]
                }],
                "generationConfig": {
                    "temperature": 0.7,
                    "topK": 1,
                    "topP": 1,
                    "maxOutputTokens": 6144, // Kept user's value
                }
            }),
            onload: function(response) {
                if (response.status === 200) {
                    try {
                        const data = JSON.parse(response.responseText);
                        if (data.candidates && data.candidates.length > 0 &&
                            data.candidates[0].content && data.candidates[0].content.parts &&
                            data.candidates[0].content.parts.length > 0 && data.candidates[0].content.parts[0].text) {
                            const summaryText = data.candidates[0].content.parts[0].text;
                            setSummaryTextAndDirection(summaryText, currentSelectedLanguage);
                            updateStatus("Summary generated successfully!", false);
                        } else if (data.promptFeedback && data.promptFeedback.blockReason) {
                            const errorText = `Error: Content generation blocked. Reason: ${data.promptFeedback.blockReasonDetails || data.promptFeedback.blockReason}`;
                            setSummaryTextAndDirection(errorText, DEFAULT_LANGUAGE);
                            updateStatus(`Content blocked: ${data.promptFeedback.blockReason}`, true);
                        } else {
                            const errorText = "Error: Received an unexpected response format from Gemini.";
                            setSummaryTextAndDirection(errorText, DEFAULT_LANGUAGE);
                            updateStatus("Could not extract summary from Gemini response.", true);
                            console.error(SCRIPT_PREFIX + "Gemini response format error:", data);
                        }
                    } catch (e) {
                        const errorText = "Error: Could not parse the response from Gemini.";
                        setSummaryTextAndDirection(errorText, DEFAULT_LANGUAGE);
                        updateStatus("Error parsing Gemini response: " + e.message, true);
                        console.error(SCRIPT_PREFIX + "Error parsing Gemini response:", e, response.responseText);
                    }
                } else {
                    let errorMsg = `Error from Gemini API: ${response.status}`;
                     try {
                        const errorData = JSON.parse(response.responseText);
                        if (errorData.error && errorData.error.message) {
                            errorMsg += ` - ${errorData.error.message}`;
                        }
                    } catch (e) { /* ignore */ }
                    setSummaryTextAndDirection(`Error: Gemini API returned status ${response.status}.`, DEFAULT_LANGUAGE);
                    updateStatus(errorMsg, true);
                    console.error(SCRIPT_PREFIX + "Error from Gemini API:", response);
                }
            },
            onerror: function(response) {
                const errorText = "Error: Network problem while contacting Gemini API.";
                setSummaryTextAndDirection(errorText, DEFAULT_LANGUAGE);
                updateStatus("Network error during summarization: " + response.statusText, true);
                console.error(SCRIPT_PREFIX + "Network error during summarization:", response);
            }
        });
    }

    async function getYouTubeTranscript() {
        updateStatus("Attempting to fetch transcript...", false);
        try {
            const threeDotsButton = document.querySelector('button#button.style-scope.ytd-menu-renderer[aria-label="More actions"], button.ytp-button[title="Settings"],  button[aria-label*="More actions" i][aria-haspopup="true"]');
            if (threeDotsButton) {
                threeDotsButton.click();
                await new Promise(resolve => setTimeout(resolve, 600));
            } else {
                console.warn(SCRIPT_PREFIX + "Three dots/Settings button not found initially.");
            }

            let transcriptButton = Array.from(document.querySelectorAll('yt-formatted-string, ytd-menu-service-item-renderer, tp-yt-paper-item, div.ytp-menuitem-label'))
                                         .find(el => {
                                             const text = el.textContent?.trim().toLowerCase();
                                             return text === 'show transcript' || text === 'показать расшифровку видео' || text === 'расшифровка' || text === 'transkript anzeigen' || text === 'mostrar transcripción';
                                         });
            if (transcriptButton) {
                 if (transcriptButton.closest('ytd-menu-popup-renderer') || transcriptButton.closest('.ytp-popup') || transcriptButton.closest('tp-yt-paper-listbox')) {
                    transcriptButton.click();
                 } else {
                    if(transcriptButton.offsetParent !== null) transcriptButton.click();
                    else console.warn(SCRIPT_PREFIX + "Transcript button found but not in expected parent, or not visible.");
                 }
            } else {
                const directTranscriptButton = document.querySelector('#description-inline-expander ytd-structured-description-content-renderer [aria-label*="transcript"], #description ytd-text-inline-expander [aria-label*="transcript"]');
                if(directTranscriptButton) {
                    directTranscriptButton.click();
                } else {
                    const existingPanel = document.querySelector("ytd-engagement-panel-section-list-renderer[target-id='engagement-panel-searchable-transcript'], ytd-transcript-renderer, .ytd-transcript-segment-list-renderer");
                    if (!existingPanel) {
                        updateStatus("Show transcript button/panel not found or could not be opened.", true);
                        return getTranscriptFromWindow();
                    } else {
                         updateStatus("Transcript panel might be already open or button was not found.", false);
                    }
                }
            }

            updateStatus("Transcript panel requested or already open. Waiting for content...", false);
            await new Promise(resolve => setTimeout(resolve, 2500));

            const transcriptPanelSelectors = [
                "ytd-engagement-panel-section-list-renderer[target-id='engagement-panel-searchable-transcript']",
                "ytd-transcript-renderer",
                ".ytd-transcript-segment-list-renderer",
                "div#transcript.ytd-item-section-renderer",
                "ytd-transcript-body-renderer"
            ];
            let transcriptPanelElement;
            for (const selector of transcriptPanelSelectors) {
                transcriptPanelElement = document.querySelector(selector);
                if (transcriptPanelElement) break;
            }

            if (!transcriptPanelElement) {
                 updateStatus("Transcript panel DOM element not found after click/check.", true);
                 return getTranscriptFromWindow();
            }

            const segmentSelectors = [
                'ytd-transcript-segment-renderer .segment-text',
                '.ytd-transcript-body-renderer .cue-group .cue',
                'yt-formatted-string.ytd-transcript-segment-renderer',
                'div[role="button"].ytd-transcript-segment-renderer div.text',
                'yt-formatted-string.ytd-transcript-cue-group-renderer',
                '.cue.ytd-transcript-body-renderer'
            ];
            let segments;
            for (const selector of segmentSelectors) {
                segments = transcriptPanelElement.querySelectorAll(selector);
                if (segments && segments.length > 0) break;
            }

            let fullTranscript = "";
            if (segments && segments.length > 0) {
                segments.forEach(segment => {
                    fullTranscript += (segment.textContent || "").trim().replace(/\s+/g, ' ') + " ";
                });
            }

            if (fullTranscript.trim()) {
                updateStatus("Transcript extracted from panel.", false);
                try {
                    const closeButtonSelectors = [
                        '#engagement-panel-searchable-transcript button[aria-label*="Close" i]',
                        'ytd-engagement-panel-title-header-renderer button[aria-label*="Close" i]',
                        'button.ytp-settings-button[title="Settings"][aria-expanded="true"]',
                        'ytd-transcript-renderer #header button[aria-label*="Close" i]',
                        'ytd-popup-container tp-yt-paper-dialog #header #close-button',
                        'button[aria-label*="Close transcript" i]'
                    ];
                    let closeButton;
                    for(const selector of closeButtonSelectors){
                        closeButton = document.querySelector(selector);
                        if(closeButton && closeButton.offsetParent !== null) break;
                        else closeButton = null;
                    }

                    if (closeButton) {
                         closeButton.click();
                    } else if (threeDotsButton && threeDotsButton.getAttribute('aria-expanded') === 'true') {
                        threeDotsButton.click();
                    }
                } catch(e) { console.warn(SCRIPT_PREFIX + "Could not close transcript panel/menu cleanly:", e); }
                return fullTranscript.trim();
            } else {
                 updateStatus("Transcript panel/segments found, but no text extracted.", true);
                 return getTranscriptFromWindow();
            }
        } catch (error) {
            updateStatus("Error interacting with transcript UI: " + error.message, true);
            console.error(SCRIPT_PREFIX + "Error in getYouTubeTranscript (UI interaction):", error);
            return getTranscriptFromWindow();
        }
    }

    function getTranscriptFromWindow() {
        updateStatus("Attempting fallback transcript extraction (window.ytInitialPlayerResponse)...", false);
        try {
            const playerResponse = window.ytInitialPlayerResponse || (window.ytplayer && window.ytplayer.config && window.ytplayer.config.args && window.ytplayer.config.args.player_response && JSON.parse(window.ytplayer.config.args.player_response));

            if (playerResponse && playerResponse.captions &&
                playerResponse.captions.playerCaptionsTracklistRenderer) {
                const tracks = playerResponse.captions.playerCaptionsTracklistRenderer.captionTracks;
                if (tracks && tracks.length > 0) {
                    let chosenTrack = tracks.find(t => t.kind === 'asr' && (t.languageCode === 'en' || t.languageCode.startsWith('en-'))) ||
                                      tracks.find(t => t.kind === 'asr') ||
                                      tracks.find(t => (t.languageCode === 'en' || t.languageCode.startsWith('en-'))) ||
                                      tracks[0];

                    if (chosenTrack && chosenTrack.baseUrl) {
                        updateStatus(`Found caption track: ${chosenTrack.name ? (chosenTrack.name.simpleText || JSON.stringify(chosenTrack.name)) : 'Unknown'} (${chosenTrack.languageCode}). Fetching...`, false);
                        return new Promise((resolve) => {
                            GM_xmlhttpRequest({
                                method: "GET",
                                url: chosenTrack.baseUrl + "&fmt=json3",
                                onload: function(response) {
                                    if (response.status === 200) {
                                        try {
                                            const captionData = JSON.parse(response.responseText);
                                            let transcriptText = "";
                                            if (captionData.events) {
                                                captionData.events.forEach(event => {
                                                    if (event.segs) {
                                                        event.segs.forEach(seg => {
                                                            transcriptText += seg.utf8.replace(/\n/g, ' ').trim() + " ";
                                                        });
                                                    }
                                                });
                                            }
                                            if (transcriptText.trim()) {
                                                updateStatus("Transcript extracted from caption track.", false);
                                                resolve(transcriptText.trim());
                                            } else {
                                                updateStatus("Caption track fetched but no text found.", true);
                                                resolve(null);
                                            }
                                        } catch (e) {
                                            updateStatus("Error parsing caption data: " + e.message, true);
                                            console.error(SCRIPT_PREFIX + "Error parsing caption data:", e);
                                            resolve(null);
                                        }
                                    } else {
                                        updateStatus(`Error fetching caption track: ${response.status}`, true);
                                        resolve(null);
                                    }
                                },
                                onerror: function() {
                                    updateStatus("Network error fetching caption track.", true);
                                    resolve(null);
                                }
                            });
                        });
                    }
                }
            }
            updateStatus("No suitable caption tracks found in player response.", true);
            return Promise.resolve(null);
        } catch (e) {
            updateStatus("Error accessing player response for transcripts: " + e.message, true);
            console.error(SCRIPT_PREFIX + "Error in getTranscriptFromWindow:", e);
            return Promise.resolve(null);
        }
    }

    function runDiagnosticChecks() {
        // Intentionally left for potential future use.
    }

    function handleGlobalMouseOver(event) {
        if (playerContainer && (event.target === playerContainer || playerContainer.contains(event.target))) {
            showToggleButton();
            startHideButtonTimer();
        }
    }

    function handleGlobalMouseOut(event) {
        if (playerContainer && (event.target === playerContainer || playerContainer.contains(event.target))) {
            const isLeavingToActiveElements = (panel && panel.contains(event.relatedTarget)) ||
                                              (togglePanelButton && togglePanelButton.contains(event.relatedTarget)) ||
                                              (playerContainer && playerContainer.contains(event.relatedTarget));

            if (!isLeavingToActiveElements) {
                startHideButtonTimer(HIDE_BUTTON_DELAY_FAST);
            }
        }
    }

    function init() {
        console.log(SCRIPT_PREFIX + "Attempting to initialize script...");
        loadSettings();

        document.body.addEventListener('mouseover', handleGlobalMouseOver, true);
        document.body.addEventListener('mouseout', handleGlobalMouseOut, true);

        const playerCheckInterval = setInterval(function() {
            playerContainer = document.getElementById('movie_player') ||
                              document.querySelector('.html5-video-player') ||
                              document.querySelector('ytd-player');

            if (playerContainer && (document.readyState === 'interactive' || document.readyState === 'complete')) {
                clearInterval(playerCheckInterval);
                console.log(SCRIPT_PREFIX + "Player container found.");

                addStyles();
                createGUI();
                loadSettings();
                createToggleButton();

                if (togglePanelButton && playerContainer) {
                    const currentPosition = window.getComputedStyle(playerContainer).position;
                    if (currentPosition === 'static' || !currentPosition) {
                         playerContainer.classList.add('relative-positioning');
                    }
                    playerContainer.appendChild(togglePanelButton);

                    const buttonPanelMouseOverHandler = (event) => {
                        showToggleButton();
                        event.stopPropagation();
                    };
                    togglePanelButton.addEventListener('mouseover', buttonPanelMouseOverHandler);
                    if (panel) panel.addEventListener('mouseover', buttonPanelMouseOverHandler);

                    const buttonPanelMouseLeaveHandler = (event) => {
                         if (playerContainer && !playerContainer.contains(event.relatedTarget) &&
                             togglePanelButton && !togglePanelButton.contains(event.relatedTarget) &&
                             panel && !panel.contains(event.relatedTarget)) {
                            startHideButtonTimer(HIDE_BUTTON_DELAY_FAST);
                         }
                    };
                    togglePanelButton.addEventListener('mouseleave', buttonPanelMouseLeaveHandler);
                    if (panel) panel.addEventListener('mouseleave', buttonPanelMouseLeaveHandler);

                } else {
                    console.error(SCRIPT_PREFIX + "togglePanelButton or playerContainer not available for event setup.");
                }

                if (apiKeyInput && apiKey) {
                    apiKeyInput.value = apiKey;
                    fetchAndPopulateModels();
                } else {
                    populateModelDropdown([]);
                }
                updateStatus("Summarizer ready. " + (isPanelVisible ? "Panel is visible." : ""), false);

                if (diagnosticIntervalId) clearInterval(diagnosticIntervalId);
                diagnosticIntervalId = setInterval(runDiagnosticChecks, DIAGNOSTIC_INTERVAL_MS);

            }
        }, 1000);

        setTimeout(() => {
            if (!document.getElementById(SCRIPT_PREFIX + 'panel')) {
                clearInterval(playerCheckInterval);
                if (diagnosticIntervalId) clearInterval(diagnosticIntervalId);
                document.body.removeEventListener('mouseover', handleGlobalMouseOver, true);
                document.body.removeEventListener('mouseout', handleGlobalMouseOut, true);
                console.warn(SCRIPT_PREFIX + "Fallback init triggered. Main init likely failed.");

                 playerContainer = document.getElementById('movie_player') || document.querySelector('.html5-video-player') || document.querySelector('ytd-player');
                 if (playerContainer && !document.getElementById(SCRIPT_PREFIX + 'toggle_button')) {
                    console.log(SCRIPT_PREFIX + "FALLBACK: Player found, attempting to setup GUI.");
                    addStyles(); createGUI(); loadSettings(); createToggleButton();
                    if (togglePanelButton) {
                        const currentPosition = window.getComputedStyle(playerContainer).position;
                        if (currentPosition === 'static' || !currentPosition) playerContainer.classList.add('relative-positioning');
                        playerContainer.appendChild(togglePanelButton);
                        playerContainer.addEventListener('mouseover', () => { showToggleButton(); startHideButtonTimer(); }, false);
                        playerContainer.addEventListener('mouseout', () => { startHideButtonTimer(HIDE_BUTTON_DELAY_FAST); }, false);
                        togglePanelButton.addEventListener('mouseover', () => { showToggleButton(); });
                        if(panel) panel.addEventListener('mouseover', () => { showToggleButton(); });

                        if(isPanelVisible) showToggleButton(); else hideToggleButton();
                    }
                    if (apiKeyInput && apiKey) { apiKeyInput.value = apiKey; fetchAndPopulateModels(); }
                    else { populateModelDropdown([]); }
                    updateStatus("Summarizer ready (Fallback Init). " + (isPanelVisible ? "Panel is visible." : ""), false);
                 } else if (!playerContainer) {
                    console.error(SCRIPT_PREFIX + "FALLBACK: Player container NOT FOUND.");
                 }
            }
        }, 15000);
    }

    function main() {
        init();
    }

    if (document.readyState === 'complete' || document.readyState === 'interactive') {
        main();
    } else {
        window.addEventListener('DOMContentLoaded', main, { once: true });
    }

})();