Files
Learn_System/frontend/css/phys9-flagships.css
T
Maxim Dolgolyov 4bcc47e5be feat(phys9 flagships): инфраструктура + F1 траектория + F2 гонка (Wave A pilot)
Phase 1 + Wave A пилоты — большие интерактивы Физики 9.

frontend/css/phys9-flagships.css — стили карточек флагманов
(.flag-card с бейджем «★ ФЛАГМАН», .flag-canvas, .flag-controls,
.flag-stats, .flag-sliders, .flag-feedback). Тёмная тема поддержана.

frontend/js/flagships/phys9_flag_base.js — общая инфраструктура:
- register(id, def) — регистрация флагмана
- mount/unmount/unmountAll — управление жизненным циклом
- makeCard(secId, title, desc, body) — создание карточки
- initCanvas(id) — высокий-DPI canvas
- startLoop(id, canvas, tick) — RAF с IntersectionObserver
  (авто-пауза если canvas за экраном)
- arrow(ctx, ...) — стрелка на canvas
- saveRecord/getRecord — сохранение в localStorage
- хук на goTo: unmountAll при смене параграфа

Флагман F1. Конструктор траектории (§5):
- Canvas 600×320, рисуется мышкой/пальцем (touch support)
- Real-time расчёт пути s и перемещения |Δr|
- Шаблоны: прямая / полуокружность / замкнутая окружность
- Feedback: «прямая → s=|Δr|», «замкнутая → |Δr|→0», «кривая → s>|Δr|»
- Кнопка «Замкнуть петлю» соединяет начало и конец

Флагман F2. Гонка двух тел (§9):
- Двухпанельный canvas 640×360 (трасса слева, графики справа)
- 5 slider'ов: v₀₁, a₁, x₀₂, v₀₂, a₂
- Запуск/Пауза/Сброс/Случайный сценарий
- Реальная физика равноуск. движения, симуляция Эйлером (4 шага/кадр)
- Real-time графики x₁(t) и x₂(t), пересечение = встреча
- Автоматическое определение момента встречи (квадратное уравнение)
- При встрече — звёздочка на пересечении графиков + feedback с t и x

В physics_9_ch1.html:
- Подключены CSS + 3 JS
- Расширен хук ensureBuilt: на p5 → mount('F1','p5'), на p9 → mount('F2','p9')

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 10:06:37 +03:00

194 lines
4.6 KiB
CSS

/* phys9-flagships.css — стили для крупных интерактивов Физики 9 (флагманы F1-F19). */
.flag-card{
background: linear-gradient(135deg, var(--card,#fff), var(--sec-acc-soft,#dbeafe));
border: 2px solid var(--sec-acc,#2563eb);
border-radius: 16px;
padding: 18px 20px;
margin: 18px 0;
box-shadow: 0 4px 14px rgba(15,23,42,.08);
position: relative;
overflow: hidden;
}
.flag-card::before{
content: '★ ФЛАГМАН';
position: absolute; top: 10px; right: 14px;
font-family: 'Unbounded', sans-serif;
font-size: .68rem; font-weight: 800;
color: #fff;
background: linear-gradient(135deg, #fbbf24, #f59e0b);
padding: 4px 10px;
border-radius: 99px;
letter-spacing: .06em;
}
.flag-title{
font-family: 'Unbounded', sans-serif;
font-size: 1.18rem;
font-weight: 800;
color: var(--sec-acc-d, #1d4ed8);
margin-bottom: 4px;
padding-right: 90px;
}
.flag-desc{
font-size: .92rem;
color: var(--text);
opacity: .85;
margin-bottom: 14px;
line-height: 1.5;
}
.flag-canvas{
display: block;
width: 100%;
max-width: 720px;
height: auto;
background: var(--bg-subtle, #f8fafc);
border: 1.5px solid var(--border, #e2e8f0);
border-radius: 12px;
margin-bottom: 12px;
touch-action: none;
}
.flag-svg{
display: block;
width: 100%;
max-width: 720px;
height: auto;
background: var(--bg-subtle, #f8fafc);
border: 1.5px solid var(--border, #e2e8f0);
border-radius: 12px;
margin-bottom: 12px;
}
.flag-controls{
display: flex;
gap: 8px;
flex-wrap: wrap;
margin: 10px 0;
align-items: center;
}
.flag-btn{
padding: 8px 16px;
border-radius: 9px;
border: 1.5px solid var(--sec-acc, #2563eb);
background: var(--card, #fff);
color: var(--sec-acc-d, #1d4ed8);
font-weight: 700;
font-size: .88rem;
cursor: pointer;
transition: transform .1s, background .15s;
font-family: inherit;
display: inline-flex;
align-items: center;
gap: 6px;
}
.flag-btn:hover{ background: var(--sec-acc-soft, #dbeafe); }
.flag-btn:active{ transform: scale(.96); }
.flag-btn:disabled{ opacity: .5; cursor: not-allowed; }
.flag-btn.primary{
background: linear-gradient(135deg, var(--sec-acc,#2563eb), var(--sec-acc-d,#1d4ed8));
color: #fff;
border-color: transparent;
}
.flag-btn.primary:hover{ filter: brightness(1.1); }
.flag-btn.success{
background: linear-gradient(135deg, #10b981, #059669);
color: #fff;
border-color: transparent;
}
.flag-btn.danger{
background: var(--card,#fff);
color: var(--fail,#dc2626);
border-color: var(--fail,#dc2626);
}
.flag-stats{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 10px;
padding: 12px 14px;
background: var(--sec-acc-soft, #dbeafe);
border-radius: 11px;
margin: 10px 0;
}
.flag-stat{
font-size: .85rem;
color: var(--text);
display: flex;
flex-direction: column;
gap: 2px;
}
.flag-stat .lbl{
font-size: .72rem;
font-weight: 700;
color: var(--muted);
text-transform: uppercase;
letter-spacing: .05em;
}
.flag-stat .val{
font-family: 'JetBrains Mono', monospace;
font-size: 1.05rem;
font-weight: 800;
color: var(--sec-acc-d, #1d4ed8);
}
.flag-sliders{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 10px;
margin: 10px 0;
}
.flag-sliders label{
display: block;
font-size: .88rem;
color: var(--muted);
background: var(--card, #fff);
padding: 8px 12px;
border-radius: 8px;
border: 1px solid var(--border, #e2e8f0);
}
.flag-sliders label b{
font-family: 'JetBrains Mono', monospace;
color: var(--sec-acc-d, #1d4ed8);
margin-left: 4px;
}
.flag-sliders input[type="range"]{
display: block;
width: 100%;
margin-top: 6px;
accent-color: var(--sec-acc, #2563eb);
}
.flag-feedback{
padding: 10px 14px;
border-radius: 9px;
font-weight: 600;
font-size: .9rem;
margin-top: 10px;
display: none;
}
.flag-feedback.show{ display: block; }
.flag-feedback.ok{
background: var(--ok-bg, #d1fae5);
color: #065f46;
border-left: 4px solid var(--ok, #10b981);
}
.flag-feedback.warn{
background: var(--warn-bg, #fef3c7);
color: #78350f;
border-left: 4px solid var(--warn, #f59e0b);
}
.flag-feedback.fail{
background: var(--fail-bg, #fee2e2);
color: #7f1d1d;
border-left: 4px solid var(--fail, #dc2626);
}
.flag-medal{
display: inline-block;
padding: 4px 11px;
background: linear-gradient(135deg, #fbbf24, #f59e0b);
color: #fff;
border-radius: 99px;
font-family: 'Unbounded', sans-serif;
font-size: .76rem;
font-weight: 800;
letter-spacing: .04em;
text-transform: uppercase;
}
html.dark .flag-canvas, html.dark .flag-svg{ background: #1a1f2e; border-color: #374151; }