Files
Hulumath-Web/backend/templates/index.html
T

474 lines
30 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% load static %}
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="葫芦数学:发现你的数学人格,经历属于你的数学人生。">
<title>葫芦数学 · 数学人生宇宙</title>
<link rel="stylesheet" href="{% static 'css/app.css' %}">
<link rel="stylesheet" href="{% static 'vendor/katex/katex.min.css' %}">
</head>
<body>
<div class="ambient ambient-one"></div>
<div class="ambient ambient-two"></div>
<div class="app-shell">
<aside class="sidebar">
<a class="brand" href="/" aria-label="葫芦数学首页">
<span class="brand-mark">H</span>
<span><strong>葫芦数学</strong><small>HULU MATH</small></span>
</a>
<nav class="nav" aria-label="主导航">
<button class="nav-item active" data-view="home"><span>01</span>首页</button>
<button class="nav-item" data-view="life"><span>02</span>数学人生</button>
<button class="nav-item" data-view="contest"><span>03</span>比赛</button>
<button class="nav-item" data-view="toolbox"><span>04</span>工具箱</button>
<button class="nav-item" data-view="discover"><span>05</span>探索发现</button>
<button class="nav-item" data-view="profile"><span>06</span>我的</button>
</nav>
<div class="sidebar-foot">
<div class="system-status"><i></i>系统在线</div>
<button id="auth-button" class="ghost-button">登录 / 注册</button>
</div>
</aside>
<main class="main">
<header class="topbar">
<p id="eyebrow">今日坐标 · 数学人生宇宙</p>
<div class="topbar-actions">
<a id="admin-entry" class="admin-entry" href="/admin/" hidden>
<span>运营后台</span><b></b>
</a>
<div class="user-chip" id="user-chip"><span class="avatar"></span><span>游客</span></div>
</div>
</header>
<section class="view active" id="view-home">
<div class="hero-grid">
<article class="hero">
<div>
<span class="kicker">YOUR MATHEMATICAL LIFE</span>
<h1>你会成为怎样的<br><em>数学人?</em></h1>
<p>从一次人格选择开始,走进真实骨架与虚构剧情交织的数学人生。你的判断、关系和机会,将共同写下答案。</p>
</div>
<div class="hero-actions">
<button class="primary-button" id="start-mathbti">开始 MathBTI <b></b></button>
<button class="text-button" data-jump="life">暂不测试,自由选择人生</button>
</div>
<div class="hero-index"></div>
</article>
<article class="daily-card">
<span class="card-label">TODAY'S MOVE</span>
<div class="pulse-orbit"><span>60</span><small></small></div>
<h2>今日口算对决</h2>
<p>同一组题,不同的判断速度。正式成绩完全由服务端记录。</p>
<button class="dark-button" data-jump="contest">进入比赛</button>
</article>
</div>
<section class="section">
<div class="section-heading">
<div><span class="kicker">FOUR SPIRITS</span><h2>四种数学精神</h2></div>
<p>不锁定路线,只提供更适合你的第一站。</p>
</div>
<div class="spirit-grid">
<article class="spirit believer"><b>01</b><h3>信仰者</h3><p>当答案还不存在,你是否仍愿意相信推理?</p><span>严谨 · 纯粹 · 求真</span></article>
<article class="spirit communicator"><b>02</b><h3>传播者</h3><p>你会守住发现,还是让更多人理解它?</p><span>表达 · 教育 · 联结</span></article>
<article class="spirit practitioner"><b>03</b><h3>应用者</h3><p>数字进入现实之后,谁来承担模型的代价?</p><span>建模 · 决策 · 责任</span></article>
<article class="spirit intuitive"><b>04</b><h3>直觉者</h3><p>当形式尚未成形,你敢不敢追随结构感?</p><span>想象 · 洞察 · 创造</span></article>
</div>
</section>
<section class="section home-match-history" id="home-match-history" hidden>
<div class="section-heading">
<div><span class="kicker">RECENT MATCHES</span><h2>最近对局</h2></div>
<button class="text-button" data-jump="profile">查看完整数学档案</button>
</div>
<div id="home-match-list" class="match-history-list"></div>
</section>
</section>
<section class="view" id="view-life">
<div class="life-hub" id="life-hub">
<div class="page-title"><span class="kicker">MATH LIFE HALL</span><h1>数学人生大厅</h1><p>四条旗舰人生对应四种数学精神,人物 Skill 包持续扩展真实人生样本。</p></div>
<div class="life-map" id="life-map">
<div class="life-map-canvas">
<svg class="life-map-lines" viewBox="0 0 1200 520" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
<path d="M600 260 Q400 120 220 180" fill="none" stroke="rgba(25,101,72,.12)" stroke-width="2" stroke-dasharray="10 12"/>
<path d="M600 260 Q800 120 980 180" fill="none" stroke="rgba(25,101,72,.12)" stroke-width="2" stroke-dasharray="10 12"/>
<path d="M600 260 Q400 400 220 420" fill="none" stroke="rgba(25,101,72,.12)" stroke-width="2" stroke-dasharray="10 12"/>
<path d="M600 260 Q800 400 980 420" fill="none" stroke="rgba(25,101,72,.12)" stroke-width="2" stroke-dasharray="10 12"/>
</svg>
<article class="route-card route-believer" data-clan="believer" data-route="believer">
<span class="route-index">01</span>
<div class="route-spirit">
<b>信仰者</b><small>BELIEVER</small>
</div>
<p class="route-conflict">当答案还不存在,你是否仍愿意相信推理?</p>
<div class="route-mathematicians" data-mathematicians="believer"></div>
<div class="route-meta"><span class="route-status">旗舰人生 · 约 120 分钟</span></div>
<button class="route-enter" data-route-enter="believer">进入信仰者人生 →</button>
</article>
<article class="route-card route-spreader" data-clan="spreader" data-route="spreader">
<span class="route-index">02</span>
<div class="route-spirit">
<b>传播者</b><small>SPREADER</small>
</div>
<p class="route-conflict">你会守住发现,还是让更多人理解它?</p>
<div class="route-mathematicians" data-mathematicians="spreader"></div>
<div class="route-meta"><span class="route-status">即将开放 · 序章可试</span></div>
<button class="route-enter" data-route-enter="spreader">进入传播者人生 →</button>
</article>
<article class="route-card route-applier" data-clan="applier" data-route="applier">
<span class="route-index">03</span>
<div class="route-spirit">
<b>应用者</b><small>APPLIER</small>
</div>
<p class="route-conflict">数字进入现实之后,谁来承担模型的代价?</p>
<div class="route-mathematicians" data-mathematicians="applier"></div>
<div class="route-meta"><span class="route-status">即将开放 · 序章可试</span></div>
<button class="route-enter" data-route-enter="applier">进入应用者人生 →</button>
</article>
<article class="route-card route-seer" data-clan="seer" data-route="seer">
<span class="route-index">04</span>
<div class="route-spirit">
<b>直觉者</b><small>SEER</small>
</div>
<p class="route-conflict">当形式尚未成形,你敢不敢追随结构感?</p>
<div class="route-mathematicians" data-mathematicians="seer"></div>
<div class="route-meta"><span class="route-status">即将开放 · 序章可试</span></div>
<button class="route-enter" data-route-enter="seer">进入直觉者人生 →</button>
</article>
</div>
</div>
<div class="alumni-entry" id="alumni-entry">
<div class="alumni-entry-content">
<div>
<span class="kicker">ALUMNI INTERVIEW</span>
<h2>数学校友访谈</h2>
<p>我们采访真实的数学校友,把他们的关键人生抉择浓缩为 20 分钟可体验的数学人生。</p>
</div>
<div class="alumni-entry-action">
<span id="alumni-count">读取中…</span>
<button class="primary-button" id="enter-alumni">进入访谈大厅 <b></b></button>
</div>
</div>
</div>
</div>
<div class="life-skills hidden" id="life-skills">
<div class="page-title">
<button class="back-button" id="back-to-hub">← 返回数学人生大厅</button>
<span class="kicker">ALUMNI INTERVIEW</span><h1>数学校友访谈</h1><p>每位校友的数学人生,浓缩为约 20 分钟的关键抉择体验。</p>
</div>
<div id="skill-list" class="skill-grid loading">正在读取校友人生…</div>
</div>
</section>
<section class="view" id="view-contest">
<div class="page-title"><span class="kicker">CONTEST ARENA</span><h1>比赛</h1><p>不再按难度拆分玩家池。选择玩法后即可随机匹配或用联机码约战。</p></div>
<div class="match-mode-switch" id="match-mode-switch" aria-label="实时比赛玩法">
<button class="active" data-match-mode="quiz"><b>口算竞速</b><small>同题抢分</small></button>
<button data-match-mode="sudoku"><b>数独 Timerun</b><small>正确完成者比时间</small></button>
<button data-match-mode="twenty_four"><b>24 点竞速</b><small>最先组出 24</small></button>
</div>
<section class="challenge-panel">
<div>
<span class="kicker">FRIEND CHALLENGE</span>
<h2>联机码约战</h2>
<p>创建 6 位联机码发给朋友,或输入朋友的联机码加入同一场对局。</p>
</div>
<div class="challenge-actions">
<button id="challenge-create" class="primary-button">创建口算竞速约战</button>
<form id="challenge-join-form">
<input id="challenge-code-input" maxlength="6" autocomplete="off" placeholder="输入 6 位联机码" aria-label="联机码">
<button class="dark-button" type="submit">加入约战</button>
</form>
</div>
</section>
<div id="contest-list" class="content-grid loading">正在读取比赛…</div>
<section class="math-games-section">
<div class="section-heading">
<div><span class="kicker">MATH PLAYGROUND</span><h2>数学玩法</h2></div>
<p>短局推理,成绩由服务端校验并记录。</p>
</div>
<div id="math-game-list" class="game-card-grid"></div>
</section>
</section>
<section class="view" id="view-toolbox">
<div class="page-title"><span class="kicker">MATHEMATICAL WORKBENCH</span><h1>工具箱</h1><p>计算、查询、绘图与表达,把想法直接变成可以继续工作的对象。</p></div>
<div class="tool-grid" id="tool-grid">
<button class="tool-card" data-tool="mental"><span></span><b>口算竞技</b><small>限时挑战你的心算速度</small></button>
<button class="tool-card active" data-tool="calculator"><span>123</span><b>数学计算工作台</b><small>代数、微积分、矩阵与统计</small></button>
<button class="tool-card" data-tool="symbols"><span>Σ</span><b>数学符号查询</b><small>含义、读法与 LaTeX 写法</small></button>
<button class="tool-card" data-tool="graph"><span></span><b>函数图形绘制</b><small>多函数、参数、导数与分析</small></button>
<button class="tool-card" data-tool="whiteboard"><span>✎△</span><b>数学画板</b><small>白板、几何、联机展示与你画我猜</small></button>
<button class="tool-card" data-tool="latex"><span>TeX</span><b>LaTeX Lab</b><small>编辑、预览、课程与公式库</small></button>
</div>
<div class="tool-workspace active" id="tool-calculator">
<div class="workspace-heading"><div><span class="kicker">COMPUTATION STUDIO</span><h2>数学计算工作台</h2></div><p>精确值、方程、微积分、矩阵、统计与进制转换由受限数学内核计算。</p></div>
<div class="calculator-shell advanced-calculator">
<div class="calculator-controls">
<label>计算类型
<select id="calc-operation">
<option value="calculate">精确计算</option>
<option value="simplify">表达式化简</option>
<option value="expand">代数展开</option>
<option value="factor">因式分解</option>
<option value="solve">解方程</option>
<option value="derivative">求导</option>
<option value="integral">积分</option>
<option value="limit">极限</option>
<option value="matrix_det">矩阵行列式</option>
<option value="matrix_inverse">逆矩阵</option>
<option value="matrix_rref">矩阵行最简形</option>
<option value="matrix_transpose">矩阵转置</option>
<option value="statistics">描述统计</option>
<option value="base">进制转换</option>
<option value="unit">单位换算</option>
</select>
</label>
<label>变量
<select id="calc-variable"><option>x</option><option>y</option><option>z</option><option>a</option><option>b</option><option>t</option><option>n</option></select>
</label>
<label class="calc-field" data-calc-field="order">阶数<input id="calc-order" type="number" min="1" max="5" value="1"></label>
<label class="calc-field" data-calc-field="bounds">下限<input id="calc-lower" placeholder="可留空"></label>
<label class="calc-field" data-calc-field="bounds">上限<input id="calc-upper" placeholder="可留空"></label>
<label class="calc-field" data-calc-field="point">趋近值<input id="calc-point" value="0"></label>
<label class="calc-field" data-calc-field="base">原进制<input id="calc-from-base" type="number" min="2" max="36" value="10"></label>
<label class="calc-field" data-calc-field="base">目标进制<input id="calc-to-base" type="number" min="2" max="36" value="2"></label>
<label class="calc-field" data-calc-field="unit">原单位<select id="calc-from-unit"><option>mm</option><option>cm</option><option selected>m</option><option>km</option><option>in</option><option>ft</option><option>g</option><option>kg</option><option>lb</option><option>s</option><option>min</option><option>h</option><option>deg</option><option>rad</option></select></label>
<label class="calc-field" data-calc-field="unit">目标单位<select id="calc-to-unit"><option>mm</option><option selected>cm</option><option>m</option><option>km</option><option>in</option><option>ft</option><option>g</option><option>kg</option><option>lb</option><option>s</option><option>min</option><option>h</option><option>deg</option><option>rad</option></select></label>
</div>
<label class="calculator-expression-label">表达式或数据
<textarea id="calc-input" class="formula-input" autocomplete="off" aria-label="计算表达式">sqrt(2) + 1/3</textarea>
</label>
<div class="calculator-actions calc-examples">
<button data-calc-operation="solve" data-calc-example="x^2 - 5*x + 6 = 0">解方程</button>
<button data-calc-operation="derivative" data-calc-example="sin(x) + x^3">求导</button>
<button data-calc-operation="integral" data-calc-example="x^2">积分</button>
<button data-calc-operation="matrix_inverse" data-calc-example="1,2;3,4">逆矩阵</button>
<button data-calc-operation="statistics" data-calc-example="12,15,18,21,24">统计</button>
<button data-calc-operation="unit" data-calc-example="1.75">单位换算</button>
<button id="calc-run" class="primary-button">开始计算</button>
</div>
<div class="calculator-result" aria-live="polite">
<div class="calculator-display"><small id="calc-history">准备计算</small><output id="calc-output">0</output></div>
<div class="calc-result-grid">
<div><span>近似值</span><code id="calc-decimal">0</code></div>
<div><span>LaTeX</span><code id="calc-latex">0</code></div>
</div>
<ol id="calc-steps" class="calc-steps"></ol>
</div>
</div>
</div>
<div class="tool-workspace" id="tool-symbols">
<div class="workspace-heading"><div><span class="kicker">SYMBOL ATLAS</span><h2>数学符号查询</h2></div><input id="symbol-search" class="search-input" placeholder="搜索:积分、集合、约等于…"></div>
<div id="symbol-list" class="symbol-grid"></div>
</div>
<div class="tool-workspace" id="tool-graph">
<div class="workspace-heading"><div><span class="kicker">FUNCTION PLOTTER</span><h2>函数图形绘制</h2></div><p>每行一个函数;支持参数 a、数值导数、积分区域和曲线分析。</p></div>
<div class="graph-shell">
<div class="graph-controls">
<details class="function-syntax-help" open>
<summary>函数书写规则</summary>
<p>每行一个表达式,直接写右侧:<code>sin(x)</code><code>x^2 - 2*x + 1</code><code>sqrt(abs(x))</code>。乘法必须写 <code>*</code>,幂可写 <code>^</code>,参数仅支持 <code>a</code></p>
</details>
<label>函数列表<textarea id="graph-expression" class="formula-input">sin(x) + a*x/3&#10;0.08*x^2 - 2</textarea></label>
<label>X 范围<input id="graph-range" type="range" min="5" max="30" value="10"><span id="graph-range-label">10 到 10</span></label>
<label>参数 a<input id="graph-parameter" type="range" min="-5" max="5" step="0.1" value="1"><span id="graph-parameter-label">a = 1</span></label>
<label class="check-row"><input id="graph-derivative" type="checkbox"> 绘制第一条函数的导数</label>
<label class="check-row"><input id="graph-integral" type="checkbox"> 填充第一条函数与 x 轴区域</label>
<button id="graph-run" class="primary-button">绘制函数</button>
<p id="graph-error"></p>
<div id="graph-analysis" class="graph-analysis"></div>
</div>
<canvas id="graph-canvas" width="900" height="480" aria-label="函数曲线图"></canvas>
</div>
</div>
<div class="tool-workspace" id="tool-whiteboard">
<div class="workspace-heading"><div><span class="kicker">MATH BOARD</span><h2>统一数学画板</h2></div><p>在白板与几何构造之间切换,可用联机码同步展示或发起数学你画我猜。</p></div>
<div class="board-mode-switch">
<button class="active" data-board-pane-toggle="whiteboard">自由白板</button>
<button data-board-pane-toggle="geometry">几何构造</button>
</div>
<section class="board-online-panel">
<div>
<select id="board-session-mode" aria-label="画板联机模式">
<option value="collaborate">协作展示</option>
<option value="draw_guess">数学你画我猜</option>
</select>
<button id="board-create" class="primary-button">创建联机码</button>
</div>
<form id="board-join-form">
<input id="board-code-input" maxlength="6" autocomplete="off" placeholder="输入 6 位联机码" aria-label="画板联机码">
<button type="submit">加入画板</button>
</form>
<p id="board-session-status">当前为本地画板,创建或加入后开始实时同步。</p>
<strong id="board-target" hidden></strong>
<form id="board-guess-form" hidden>
<input id="board-guess-input" maxlength="40" placeholder="猜一个数学对象">
<button type="submit">提交猜测</button>
</form>
</section>
<div class="board-pane active" data-board-pane="whiteboard">
<div class="drawing-toolbar" id="whiteboard-toolbar">
<button class="active" data-whiteboard-tool="pen">画笔</button>
<button data-whiteboard-tool="line">直线</button>
<button data-whiteboard-tool="rect">矩形</button>
<button data-whiteboard-tool="text">文字 / 公式</button>
<button data-whiteboard-tool="eraser">橡皮</button>
<input id="whiteboard-text" class="toolbar-text-input" placeholder="输入文字或公式">
<label>颜色<input id="whiteboard-color" type="color" value="#17211b"></label>
<label>粗细<input id="whiteboard-size" type="range" min="2" max="24" value="4"></label>
<button id="whiteboard-grid">添加坐标纸</button>
<label class="file-tool">导入图片<input id="whiteboard-image" type="file" accept="image/*"></label>
<button id="whiteboard-undo">撤销</button>
<button id="whiteboard-clear">清空</button>
<button id="whiteboard-export" class="primary-button">导出 PNG</button>
</div>
<div class="canvas-stage"><canvas id="whiteboard-canvas" width="1200" height="700" aria-label="数学白板"></canvas></div>
</div>
<div class="board-pane" data-board-pane="geometry">
<div class="drawing-toolbar" id="geometry-toolbar">
<button class="active" data-geometry-tool="point"></button>
<button data-geometry-tool="segment">线段</button>
<button data-geometry-tool="circle"></button>
<button data-geometry-tool="midpoint">中点</button>
<button data-geometry-tool="move">拖动</button>
<label class="check-row"><input id="geometry-labels" type="checkbox" checked> 坐标与测量</label>
<button id="geometry-undo">撤销</button>
<button id="geometry-clear">清空</button>
<button id="geometry-export" class="primary-button">导出 PNG</button>
</div>
<div class="canvas-stage geometry-stage"><canvas id="geometry-canvas" width="1200" height="700" aria-label="几何画板"></canvas></div>
<p id="geometry-hint" class="canvas-hint">点击画布创建第一个点。</p>
</div>
</div>
<div class="tool-workspace" id="tool-latex">
<div class="workspace-heading"><div><span class="kicker">LATEX LAB</span><h2>数学表达实验室</h2></div><p>源码、实时预览与版本保存。</p></div>
<div class="editor-shell">
<div class="editor-pane"><label for="latex-source">LaTeX 源码</label><textarea id="latex-source" spellcheck="false">\int_{0}^{1} x^2\,dx = \frac{1}{3}</textarea></div>
<div class="preview-pane"><span>实时预览</span><div id="latex-preview" role="status" aria-live="polite"></div><button id="save-formula" class="primary-button">保存到我的公式</button></div>
</div>
</div>
</section>
<section class="view" id="view-discover">
<div class="page-title discover-title"><span class="kicker">DISCOVER THROUGH VIDEO</span><h1>探索发现</h1><p>Hello there. 这里收集来自各专业志愿者的数学科普视频,也连接你的五维成长。</p></div>
<section class="ability-map">
<div class="map-heading"><div><h2>五维能力地图</h2><p>观看视频,点亮数学精灵的五种能力</p></div><div id="ability-legend" class="ability-legend"></div></div>
<div class="map-stage">
<svg class="map-lines" viewBox="0 0 1000 360" preserveAspectRatio="none" aria-hidden="true">
<path d="M500 178 L500 42 M500 178 L825 80 M500 178 L735 305 M500 178 L260 305 M500 178 L175 80"/>
<path d="M500 42 L825 80 L735 305 L260 305 L175 80 Z"/>
</svg>
<button class="ability-node node-vision" data-ability="vision"><span></span><b>数学眼光</b><small>0</small></button>
<button class="ability-node node-humanities" data-ability="humanities"><span></span><b>数学人文</b><small>0</small></button>
<button class="ability-node node-detection" data-ability="detection"><span></span><b>数学侦探</b><small>0</small></button>
<button class="ability-node node-modeling" data-ability="modeling"><span></span><b>数学建模</b><small>0</small></button>
<button class="ability-node node-connection" data-ability="connection"><span></span><b>数学联结</b><small>0</small></button>
<div class="pet-node"><b></b><span>数学精灵</span></div>
</div>
<p class="map-hint">点击地图节点,进入对应维度的视频流</p>
</section>
<section class="video-browser">
<div class="filter-row">
<div class="filter-dropdown" id="ability-filter">
<button class="filter-dropdown-toggle" id="ability-toggle" aria-expanded="false" aria-haspopup="listbox">
<span id="ability-label">全部维度</span><b></b>
</button>
<div class="filter-dropdown-panel hidden" id="ability-panel" role="listbox"></div>
</div>
<div class="filter-dropdown" id="discipline-filter">
<button class="filter-dropdown-toggle" id="discipline-toggle" aria-expanded="false" aria-haspopup="listbox">
<span id="discipline-label">全部专业</span><b></b>
</button>
<div class="filter-dropdown-panel hidden" id="discipline-panel" role="listbox"></div>
</div>
</div>
<div class="video-section-heading"><div><span class="kicker">VIDEO STREAM</span><h2 id="video-stream-title">全部视频</h2></div><span id="video-result-count">0 条内容</span></div>
<div id="video-list" class="video-grid loading">正在读取视频流…</div>
</section>
</section>
<section class="view" id="view-profile">
<div class="page-title"><span class="kicker">MY ARCHIVE</span><h1>我的数学档案</h1><p>身份、五维能力、人生路径、比赛和表达记录都在这里。</p></div>
<div id="profile-panel" class="profile-panel"><p>登录后查看完整档案。</p><button class="primary-button" data-open-auth>登录 / 注册</button></div>
</section>
</main>
</div>
<section id="story-experience" class="story-experience hidden" aria-label="数学人生体验">
<header class="story-experience-header">
<div>
<span class="kicker">MATHEMATICAL LIFE</span>
<h1 id="story-experience-title">信仰者人生</h1>
</div>
<button id="story-experience-close" class="ghost-button">保存并返回大厅</button>
</header>
<div class="story-chapter-bar">
<div><span id="story-chapter-number">第 1 章</span><b id="story-chapter-title">人生起点</b></div>
<div class="quiz-progress"><i id="story-chapter-progress"></i></div>
</div>
<div class="story-experience-layout">
<main id="story-experience-content" class="story-scene-panel"></main>
<aside class="story-mark-panel">
<div><span class="kicker">MARK ARCHIVE</span><h2>数学印记</h2></div>
<div id="story-domain-counts" class="story-domain-counts"></div>
<div id="story-mark-list" class="story-mark-list"></div>
</aside>
</div>
</section>
<dialog id="auth-dialog">
<button class="dialog-close" aria-label="关闭">×</button>
<div class="dialog-tabs"><button class="active" data-auth-tab="login">登录</button><button data-auth-tab="register">邀请码注册</button></div>
<form id="login-form" class="auth-form">
<h2>继续你的数学人生</h2>
<label>用户名<input name="username" autocomplete="username" required></label>
<label>密码<input type="password" name="password" autocomplete="current-password" required></label>
<button class="primary-button" type="submit">登录</button>
</form>
<form id="register-form" class="auth-form hidden">
<h2>建立数学档案</h2>
<label>邀请码<input name="invite_code" required></label>
<label>用户名<input name="username" pattern="[A-Za-z0-9_]{3,30}" required></label>
<label>昵称<input name="nickname" maxlength="40" required></label>
<label>密码<input type="password" name="password" minlength="8" required></label>
<label>当前赛道<select name="track"><option value="beginner">入门</option><option value="standard" selected>标准</option><option value="advanced">进阶</option></select></label>
<button class="primary-button" type="submit">注册并进入</button>
</form>
<p id="auth-error" class="form-error"></p>
</dialog>
<dialog id="experience-dialog" class="experience-dialog">
<button class="dialog-close" aria-label="关闭">×</button>
<div id="experience-content"></div>
</dialog>
<dialog id="video-dialog" class="video-dialog">
<button class="dialog-close" aria-label="关闭">×</button>
<div id="video-dialog-content"></div>
</dialog>
<div class="toast" id="toast" role="status"></div>
<div class="csrf-token">{% csrf_token %}</div>
<script src="{% static 'vendor/katex/katex.min.js' %}" defer></script>
<script src="{% static 'js/toolbox.js' %}" defer></script>
<script src="{% static 'js/games.js' %}" defer></script>
<script src="{% static 'js/realtime.js' %}" defer></script>
<script src="{% static 'js/app.js' %}" defer></script>
</body>
</html>