6cff327e88
Новый отдельный модуль /exam9 в стиле LearnSpace: - 80 вариантов × 10 заданий = 800 задач с разбором (KaTeX + SVG) - Сайдбар: пункт «Экзамен 9 класс» (clipboard-check) - Feature flag: feature_exam9_enabled (мигр. 002) - Видим всем авторизованным; рендер на стороне клиента - Прогресс в localStorage: подсветка вариантов (done/partial) - Возобновление последнего варианта при возврате Структура: frontend/exam9.html — страница (LearnSpace layout) frontend/js/exam9/app.js — рендерер frontend/js/exam9/variants/ — 80 файлов с данными frontend/img/exam9/ — 22 PNG/JPG фигур заданий Картинки путей _tmp/ → /img/exam9/ переписаны автоматически. Все маршруты проверены: 200 OK на /exam9, /js/exam9/*, /img/exam9/*.
339 lines
15 KiB
HTML
339 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Экзамен 9 класс — Математика — LearnSpace</title>
|
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
<link href="https://fonts.googleapis.com/css2?family=Unbounded:wght@400;700;800&family=Manrope:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
|
<link rel="stylesheet" href="/css/ls.css" />
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css" />
|
|
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js"></script>
|
|
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" onload="onKatexLoad()"></script>
|
|
<style>
|
|
.sb-content { padding: 0; overflow-y: auto; }
|
|
.ex-wrap { max-width: 920px; margin: 0 auto; padding: 32px 24px 80px; width: 100%; }
|
|
|
|
/* ── Header ── */
|
|
.ex-header { display:flex; align-items:center; gap:14px; margin-bottom:24px; flex-wrap:wrap; }
|
|
.ex-icon {
|
|
width:52px; height:52px; border-radius:14px; flex-shrink:0;
|
|
background: linear-gradient(135deg, rgba(155,93,229,.25), rgba(6,214,224,.18));
|
|
border:1.5px solid rgba(255,255,255,.1);
|
|
display:flex; align-items:center; justify-content:center;
|
|
}
|
|
.ex-icon svg { width:26px; height:26px; stroke:#9B5DE5; stroke-width:1.8; fill:none; }
|
|
.ex-title { font-family:'Unbounded',sans-serif; font-size:1.35rem; font-weight:800; letter-spacing:-.02em; }
|
|
.ex-sub { font-size:.82rem; color:var(--text-2); margin-top:2px; }
|
|
.ex-header-right { margin-left:auto; display:flex; align-items:center; gap:8px; }
|
|
|
|
.ex-picker-btn {
|
|
display:flex; align-items:center; gap:8px;
|
|
padding:9px 16px; border-radius:10px;
|
|
border:1.5px solid var(--border-h); background:var(--surface); color:var(--text);
|
|
font-family:'Manrope',sans-serif; font-size:.88rem; font-weight:700;
|
|
cursor:pointer; transition:all .15s; white-space:nowrap;
|
|
}
|
|
.ex-picker-btn:hover { border-color:var(--violet); color:var(--violet); }
|
|
.ex-picker-btn .ex-chev { width:14px; height:14px; transition:transform .2s; }
|
|
.ex-picker-btn.open .ex-chev { transform:rotate(180deg); }
|
|
|
|
/* ── Picker overlay ── */
|
|
.ex-overlay {
|
|
display:none; position:fixed; inset:0;
|
|
background:rgba(15,23,42,.55); z-index:300;
|
|
align-items:flex-start; justify-content:center; padding-top:80px;
|
|
backdrop-filter:blur(2px);
|
|
}
|
|
.ex-overlay.visible { display:flex; }
|
|
.ex-panel {
|
|
background:var(--surface); border:1.5px solid var(--border);
|
|
border-radius:16px; box-shadow:0 24px 64px rgba(0,0,0,.32);
|
|
width:min(680px, 94vw); max-height:calc(100vh - 120px);
|
|
overflow-y:auto; padding:22px 22px 26px;
|
|
animation: panelIn .18s ease;
|
|
}
|
|
@keyframes panelIn {
|
|
from { opacity:0; transform:translateY(-12px); }
|
|
to { opacity:1; transform:translateY(0); }
|
|
}
|
|
.ex-panel-head {
|
|
display:flex; align-items:center; justify-content:space-between; margin-bottom:18px;
|
|
}
|
|
.ex-panel-head h2 { font-family:'Unbounded',sans-serif; font-size:1rem; font-weight:800; }
|
|
.ex-panel-close {
|
|
width:32px; height:32px; border:none; background:none;
|
|
color:var(--text-2); cursor:pointer; border-radius:8px;
|
|
display:flex; align-items:center; justify-content:center; transition:background .15s;
|
|
}
|
|
.ex-panel-close:hover { background:var(--border); color:var(--text); }
|
|
.ex-panel-close svg { width:18px; height:18px; }
|
|
|
|
/* ── Variants grid ── */
|
|
.ex-grid {
|
|
display:grid; grid-template-columns:repeat(10, 1fr); gap:6px;
|
|
}
|
|
.vg-btn {
|
|
aspect-ratio:1; border:1.5px solid var(--border-h); border-radius:8px;
|
|
background:transparent; color:var(--text-2);
|
|
font-family:'Manrope',sans-serif; font-size:.82rem; font-weight:700;
|
|
cursor:pointer; transition:all .12s; line-height:1;
|
|
}
|
|
.vg-btn:hover { border-color:var(--violet); color:var(--violet); }
|
|
.vg-btn.active { background:var(--violet); border-color:var(--violet); color:#fff; }
|
|
.vg-btn.done { background:rgba(6,214,160,.15); border-color:#06D6A0; color:#06D6A0; }
|
|
.vg-btn.done:hover { background:rgba(6,214,160,.25); }
|
|
.vg-btn.done.active { background:#06D6A0; border-color:#06D6A0; color:#fff; }
|
|
.vg-btn.partial { background:rgba(248,150,30,.13); border-color:#F8961E; color:#F8961E; }
|
|
.vg-btn.partial:hover { background:rgba(248,150,30,.22); }
|
|
|
|
@media (max-width: 540px) {
|
|
.ex-grid { grid-template-columns:repeat(8, 1fr); }
|
|
}
|
|
|
|
/* ── Variant header + tasks ── */
|
|
.variant-title {
|
|
font-family:'Unbounded',sans-serif; font-size:1.45rem; font-weight:800;
|
|
letter-spacing:-.02em; margin-bottom:22px;
|
|
}
|
|
.variant-title small {
|
|
font-family:'Manrope',sans-serif; font-size:.85rem; font-weight:500;
|
|
color:var(--text-2); margin-left:10px;
|
|
}
|
|
|
|
.task-card {
|
|
background:var(--surface); border:1.5px solid var(--border);
|
|
border-radius:14px; margin-bottom:16px; overflow:hidden;
|
|
transition:border-color .15s;
|
|
}
|
|
.task-card:hover { border-color:var(--border-h); }
|
|
|
|
.task-header {
|
|
display:flex; align-items:center; gap:12px;
|
|
padding:12px 22px; background:rgba(155,93,229,.04);
|
|
border-bottom:1.5px solid var(--border);
|
|
}
|
|
.task-num {
|
|
width:30px; height:30px; border-radius:50%;
|
|
background:var(--violet); color:#fff;
|
|
font-family:'Unbounded',sans-serif; font-size:.82rem; font-weight:800;
|
|
display:flex; align-items:center; justify-content:center; flex-shrink:0;
|
|
}
|
|
.task-label {
|
|
font-family:'Unbounded',sans-serif; font-size:.85rem; font-weight:700;
|
|
color:var(--text-2); letter-spacing:.02em;
|
|
}
|
|
|
|
.task-body { padding:20px 26px; font-size:1rem; line-height:1.8; }
|
|
.task-text .katex-display { margin:14px 0 8px; overflow-x:auto; }
|
|
|
|
.opts {
|
|
display:flex; flex-wrap:wrap; gap:10px 32px;
|
|
margin-top:16px; padding-top:14px; border-top:1px solid var(--border);
|
|
align-items:center;
|
|
}
|
|
.opts-vertical {
|
|
display:flex; flex-direction:column; gap:8px;
|
|
margin-top:14px; padding-top:14px; border-top:1px solid var(--border);
|
|
}
|
|
.opt { display:inline-flex; align-items:flex-start; gap:6px; }
|
|
.opt-lbl {
|
|
font-family:'Unbounded',sans-serif; font-weight:800;
|
|
color:var(--violet); font-size:.92rem; white-space:nowrap;
|
|
}
|
|
|
|
.task-figure { margin:14px 0 4px; }
|
|
.task-fig { max-width:100%; height:auto; border-radius:6px; }
|
|
|
|
/* ── Solutions ── */
|
|
.sol-wrap { padding:0 22px 16px; }
|
|
.sol-btn {
|
|
display:inline-flex; align-items:center; gap:7px;
|
|
padding:6px 14px; border:1.5px solid #06D6A0; border-radius:8px;
|
|
background:transparent; color:#06D6A0;
|
|
font-family:'Manrope',sans-serif; font-size:.85rem; font-weight:700;
|
|
cursor:pointer; transition:all .15s;
|
|
}
|
|
.sol-btn:hover { background:rgba(6,214,160,.12); }
|
|
.sol-btn.open { background:#06D6A0; border-color:#06D6A0; color:#fff; }
|
|
.sol-btn svg { width:13px; height:13px; transition:transform .2s; }
|
|
.sol-btn.open svg { transform:rotate(90deg); }
|
|
|
|
.sol-panel {
|
|
display:none; margin-top:14px; padding:18px 22px;
|
|
background:rgba(6,214,160,.06); border-radius:10px;
|
|
border-left:3px solid #06D6A0;
|
|
line-height:1.85; font-size:.96rem;
|
|
}
|
|
.sol-panel.visible { display:block; }
|
|
.sol-ans {
|
|
display:inline-block; margin-top:12px; padding:4px 14px;
|
|
background:rgba(6,214,160,.2); border-radius:6px;
|
|
font-family:'Unbounded',sans-serif; font-weight:800; color:#06D6A0;
|
|
}
|
|
.sol-panel ul { margin:6px 0 6px 22px; }
|
|
.sol-panel li { margin:3px 0; }
|
|
.sol-panel .katex-display { margin:10px 0 6px; overflow-x:auto; }
|
|
|
|
/* Empty state */
|
|
.ex-empty {
|
|
padding:60px 20px; text-align:center; color:var(--text-3);
|
|
}
|
|
.ex-empty svg { width:48px; height:48px; opacity:.5; margin-bottom:14px; stroke:var(--text-3); }
|
|
|
|
@media (max-width: 600px) {
|
|
.ex-wrap { padding:20px 16px 60px; }
|
|
.ex-title { font-size:1.15rem; }
|
|
.task-body { padding:16px 18px; }
|
|
.sol-wrap { padding:0 18px 14px; }
|
|
.sol-panel { padding:14px 16px; }
|
|
.opts { gap:8px 18px; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="app-layout">
|
|
<aside class="sidebar" id="app-sidebar"></aside>
|
|
|
|
<div class="sb-content">
|
|
<div class="ex-wrap">
|
|
|
|
<header class="ex-header">
|
|
<div class="ex-icon">
|
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
<rect x="9" y="2" width="6" height="4" rx="1"/>
|
|
<path d="M9 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-3"/>
|
|
<path d="m9 14 2 2 4-4"/>
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<div class="ex-title">Экзамен 9 класс — Математика</div>
|
|
<div class="ex-sub">2025 · 80 вариантов · решения с разбором</div>
|
|
</div>
|
|
<div class="ex-header-right">
|
|
<button class="ex-picker-btn" id="picker-btn" onclick="togglePicker()">
|
|
<span id="picker-label">Выбрать вариант</span>
|
|
<svg class="ex-chev" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<main id="ex-main">
|
|
<div class="ex-empty">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
|
|
<div>Загрузка вариантов…</div>
|
|
</div>
|
|
</main>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ex-overlay" id="picker-overlay" onclick="onOverlayClick(event)">
|
|
<div class="ex-panel" onclick="event.stopPropagation()">
|
|
<div class="ex-panel-head">
|
|
<h2>Выберите вариант</h2>
|
|
<button class="ex-panel-close" onclick="closePicker()" title="Закрыть">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
|
</button>
|
|
</div>
|
|
<div class="ex-grid" id="variant-grid"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/lucide@0.469.0/dist/umd/lucide.min.js"></script>
|
|
<script src="/js/api.js"></script>
|
|
<script src="/js/sidebar.js"></script>
|
|
<script src="/js/notifications.js"></script>
|
|
<script src="/js/search.js"></script>
|
|
<script src="/js/mobile.js"></script>
|
|
<script>
|
|
LS.initPage();
|
|
LS.showBoardIfAllowed();
|
|
LS.hideDisabledFeatures();
|
|
window.VARIANTS = {};
|
|
</script>
|
|
<script src="/js/exam9/variants/v01.js"></script>
|
|
<script src="/js/exam9/variants/v02.js"></script>
|
|
<script src="/js/exam9/variants/v03.js"></script>
|
|
<script src="/js/exam9/variants/v04.js"></script>
|
|
<script src="/js/exam9/variants/v05.js"></script>
|
|
<script src="/js/exam9/variants/v06.js"></script>
|
|
<script src="/js/exam9/variants/v07.js"></script>
|
|
<script src="/js/exam9/variants/v08.js"></script>
|
|
<script src="/js/exam9/variants/v09.js"></script>
|
|
<script src="/js/exam9/variants/v10.js"></script>
|
|
<script src="/js/exam9/variants/v11.js"></script>
|
|
<script src="/js/exam9/variants/v12.js"></script>
|
|
<script src="/js/exam9/variants/v13.js"></script>
|
|
<script src="/js/exam9/variants/v14.js"></script>
|
|
<script src="/js/exam9/variants/v15.js"></script>
|
|
<script src="/js/exam9/variants/v16.js"></script>
|
|
<script src="/js/exam9/variants/v17.js"></script>
|
|
<script src="/js/exam9/variants/v18.js"></script>
|
|
<script src="/js/exam9/variants/v19.js"></script>
|
|
<script src="/js/exam9/variants/v20.js"></script>
|
|
<script src="/js/exam9/variants/v21.js"></script>
|
|
<script src="/js/exam9/variants/v22.js"></script>
|
|
<script src="/js/exam9/variants/v23.js"></script>
|
|
<script src="/js/exam9/variants/v24.js"></script>
|
|
<script src="/js/exam9/variants/v25.js"></script>
|
|
<script src="/js/exam9/variants/v26.js"></script>
|
|
<script src="/js/exam9/variants/v27.js"></script>
|
|
<script src="/js/exam9/variants/v28.js"></script>
|
|
<script src="/js/exam9/variants/v29.js"></script>
|
|
<script src="/js/exam9/variants/v30.js"></script>
|
|
<script src="/js/exam9/variants/v31.js"></script>
|
|
<script src="/js/exam9/variants/v32.js"></script>
|
|
<script src="/js/exam9/variants/v33.js"></script>
|
|
<script src="/js/exam9/variants/v34.js"></script>
|
|
<script src="/js/exam9/variants/v35.js"></script>
|
|
<script src="/js/exam9/variants/v36.js"></script>
|
|
<script src="/js/exam9/variants/v37.js"></script>
|
|
<script src="/js/exam9/variants/v38.js"></script>
|
|
<script src="/js/exam9/variants/v39.js"></script>
|
|
<script src="/js/exam9/variants/v40.js"></script>
|
|
<script src="/js/exam9/variants/v41.js"></script>
|
|
<script src="/js/exam9/variants/v42.js"></script>
|
|
<script src="/js/exam9/variants/v43.js"></script>
|
|
<script src="/js/exam9/variants/v44.js"></script>
|
|
<script src="/js/exam9/variants/v45.js"></script>
|
|
<script src="/js/exam9/variants/v46.js"></script>
|
|
<script src="/js/exam9/variants/v47.js"></script>
|
|
<script src="/js/exam9/variants/v48.js"></script>
|
|
<script src="/js/exam9/variants/v49.js"></script>
|
|
<script src="/js/exam9/variants/v50.js"></script>
|
|
<script src="/js/exam9/variants/v51.js"></script>
|
|
<script src="/js/exam9/variants/v52.js"></script>
|
|
<script src="/js/exam9/variants/v53.js"></script>
|
|
<script src="/js/exam9/variants/v54.js"></script>
|
|
<script src="/js/exam9/variants/v55.js"></script>
|
|
<script src="/js/exam9/variants/v56.js"></script>
|
|
<script src="/js/exam9/variants/v57.js"></script>
|
|
<script src="/js/exam9/variants/v58.js"></script>
|
|
<script src="/js/exam9/variants/v59.js"></script>
|
|
<script src="/js/exam9/variants/v60.js"></script>
|
|
<script src="/js/exam9/variants/v61.js"></script>
|
|
<script src="/js/exam9/variants/v62.js"></script>
|
|
<script src="/js/exam9/variants/v63.js"></script>
|
|
<script src="/js/exam9/variants/v64.js"></script>
|
|
<script src="/js/exam9/variants/v65.js"></script>
|
|
<script src="/js/exam9/variants/v66.js"></script>
|
|
<script src="/js/exam9/variants/v67.js"></script>
|
|
<script src="/js/exam9/variants/v68.js"></script>
|
|
<script src="/js/exam9/variants/v69.js"></script>
|
|
<script src="/js/exam9/variants/v70.js"></script>
|
|
<script src="/js/exam9/variants/v71.js"></script>
|
|
<script src="/js/exam9/variants/v72.js"></script>
|
|
<script src="/js/exam9/variants/v73.js"></script>
|
|
<script src="/js/exam9/variants/v74.js"></script>
|
|
<script src="/js/exam9/variants/v75.js"></script>
|
|
<script src="/js/exam9/variants/v76.js"></script>
|
|
<script src="/js/exam9/variants/v77.js"></script>
|
|
<script src="/js/exam9/variants/v78.js"></script>
|
|
<script src="/js/exam9/variants/v79.js"></script>
|
|
<script src="/js/exam9/variants/v80.js"></script>
|
|
<script src="/js/exam9/app.js"></script>
|
|
</body>
|
|
</html>
|