diff --git a/frontend/textbooks/algebra_8.html b/frontend/textbooks/algebra_8.html
index 0606b55..fe2eafb 100644
--- a/frontend/textbooks/algebra_8.html
+++ b/frontend/textbooks/algebra_8.html
@@ -2238,7 +2238,7 @@ function buildP2(){
`)}
${widget('Числовая прямая с корнями', 'VISUAL', 'Нажимайте кнопки, чтобы поставить точки √n и π на прямую. Точные десятичные значения — в подсказках.', `
-
+
√2
√3
@@ -2442,25 +2442,54 @@ function initNumLine(){
function nlRender(){
const line = document.getElementById('nl-line');
line.innerHTML = '';
- const w = line.clientWidth;
- // axis 0..15
- const axis = el('div', {style:'position:absolute;top:60px;left:3%;right:3%;height:2px;background:var(--text)'});
+ // axis 0..15 — нижняя часть, чтобы сверху было место под подписи в несколько уровней
+ const AXIS_Y = 100;
+ const axis = el('div', {style:`position:absolute;top:${AXIS_Y}px;left:3%;right:3%;height:2px;background:var(--text)`});
line.appendChild(axis);
// ticks 0..15
const lo = 0, hi = 15;
for(let i = lo; i <= hi; i++){
const x = 3 + (i - lo) / (hi - lo) * 94;
- const t = el('div', {style:`position:absolute;top:54px;left:${x}%;width:2px;height:14px;background:var(--text);transform:translateX(-50%)`});
+ const t = el('div', {style:`position:absolute;top:${AXIS_Y-6}px;left:${x}%;width:2px;height:14px;background:var(--text);transform:translateX(-50%)`});
line.appendChild(t);
- const lab = el('div', {style:`position:absolute;top:72px;left:${x}%;transform:translateX(-50%);font-size:.74rem;font-family:'JetBrains Mono',monospace;color:var(--muted)`}, ''+i);
+ const lab = el('div', {style:`position:absolute;top:${AXIS_Y+12}px;left:${x}%;transform:translateX(-50%);font-size:.74rem;font-family:'JetBrains Mono',monospace;color:var(--muted)`}, ''+i);
line.appendChild(lab);
}
- NL_POINTS.forEach((p,i)=>{
- const x = 3 + (p.v - lo) / (hi - lo) * 94;
- const pt = el('div', {style:`position:absolute;top:54px;left:${x}%;width:14px;height:14px;background:var(--pri);border-radius:50%;transform:translateX(-50%);border:2.5px solid var(--card);box-shadow:0 0 0 2px var(--pri);cursor:pointer;z-index:2`});
+ // Сортируем по x для расчёта уровней без перекрытия
+ const w = line.clientWidth || 600;
+ const labelHalfPxApprox = 22; // полу-ширина подписи в пикселях
+ const placed = []; // {xPct, level}
+ const sorted = NL_POINTS.map((p,i)=>({...p, _i:i})).sort((a,b)=>a.v-b.v);
+ sorted.forEach(p=>{
+ const xPct = 3 + (p.v - lo) / (hi - lo) * 94;
+ // Найти минимальный уровень без перекрытия с placed
+ let level = 0;
+ while(true){
+ const conflict = placed.some(q=>{
+ if(q.level !== level) return false;
+ const dxPx = Math.abs(q.xPct - xPct) / 100 * w;
+ return dxPx < (labelHalfPxApprox * 2 + 4);
+ });
+ if(!conflict) break;
+ level++;
+ if(level > 8) break;
+ }
+ placed.push({xPct, level});
+ p._level = level;
+ });
+ sorted.forEach(p=>{
+ const xPct = 3 + (p.v - lo) / (hi - lo) * 94;
+ const pt = el('div', {style:`position:absolute;top:${AXIS_Y-6}px;left:${xPct}%;width:14px;height:14px;background:var(--pri);border-radius:50%;transform:translateX(-50%);border:2.5px solid var(--card);box-shadow:0 0 0 2px var(--pri);cursor:pointer;z-index:2`});
pt.title = p.lab + ' ≈ ' + p.v.toFixed(4);
line.appendChild(pt);
- const lab = el('div', {style:`position:absolute;top:${20 + (i%3)*12}px;left:${x}%;transform:translateX(-50%);font-size:.78rem;font-weight:700;color:var(--pri);background:var(--card);padding:2px 6px;border-radius:5px;border:1px solid var(--pri);font-family:'JetBrains Mono',monospace`}, p.lab);
+ // Подпись сверху, нескольких уровней; линия-выноска вниз к точке
+ const labY = 4 + p._level * 20;
+ const stemTop = labY + 18;
+ const stemHeight = AXIS_Y - stemTop - 2;
+ if(stemHeight > 0){
+ line.appendChild(el('div', {style:`position:absolute;top:${stemTop}px;left:${xPct}%;width:1px;height:${stemHeight}px;background:var(--pri);opacity:.45;transform:translateX(-50%);z-index:1`}));
+ }
+ const lab = el('div', {style:`position:absolute;top:${labY}px;left:${xPct}%;transform:translateX(-50%);font-size:.78rem;font-weight:700;color:var(--pri);background:var(--card);padding:2px 7px;border-radius:5px;border:1px solid var(--pri);font-family:'JetBrains Mono',monospace;white-space:nowrap;z-index:3;box-shadow:0 1px 4px rgba(0,0,0,.08)`}, p.lab);
line.appendChild(lab);
});
}