4bcc47e5be
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>
194 lines
4.6 KiB
CSS
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; }
|