diff --git a/web/src/coaster/AccelerationStripsPanel.module.css b/web/src/coaster/AccelerationStripsPanel.module.css
index 3c03966..c9dd9f4 100644
--- a/web/src/coaster/AccelerationStripsPanel.module.css
+++ b/web/src/coaster/AccelerationStripsPanel.module.css
@@ -1,9 +1,5 @@
.panel {
- position: fixed;
- right: 16px;
- top: 60px;
- z-index: 600;
- width: 280px;
+ width: 340px;
background: rgba(8, 8, 12, 0.84);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
@@ -57,7 +53,7 @@
.stripRow {
display: flex;
align-items: center;
- gap: 6px;
+ gap: 5px;
margin-bottom: 6px;
font-size: 12px;
}
@@ -66,37 +62,17 @@
color: rgba(245, 158, 11, 0.9);
font-weight: 600;
min-width: 44px;
+ flex-shrink: 0;
}
-.stripRange {
- color: rgba(255, 255, 255, 0.38);
- font-size: 11px;
- min-width: 56px;
-}
-
-.accelInput {
- width: 50px;
- background: rgba(255, 255, 255, 0.07);
- border: 1px solid rgba(255, 255, 255, 0.14);
- border-radius: 6px;
- color: #fff;
- font-size: 13px;
- font-weight: 600;
- padding: 2px 5px;
- text-align: right;
-}
-.accelInput:focus {
- outline: none;
- border-color: rgba(245, 158, 11, 0.5);
-}
-
-.stripUnit {
+.rangeSep {
color: rgba(255, 255, 255, 0.28);
font-size: 11px;
}
.stripDelete {
margin-left: auto;
+ flex-shrink: 0;
width: 20px;
height: 20px;
border-radius: 4px;
diff --git a/web/src/coaster/AccelerationStripsPanel.tsx b/web/src/coaster/AccelerationStripsPanel.tsx
index ef695f8..28e6a00 100644
--- a/web/src/coaster/AccelerationStripsPanel.tsx
+++ b/web/src/coaster/AccelerationStripsPanel.tsx
@@ -1,16 +1,16 @@
import { useState, useEffect } from 'react'
import type { AccelerationStrip } from '../types/api'
+import { BlenderInput } from '../ui/BlenderInput'
import styles from './AccelerationStripsPanel.module.css'
interface Props {
strips: AccelerationStrip[]
onRemoveStrip: (id: string) => void
onUpdateStrip: (id: string, accel_ms2: number) => void
+ onUpdateStripFrac: (id: string, startFrac: number, endFrac: number) => void
}
-function pct(v: number) { return `${(v * 100).toFixed(0)}%` }
-
-export function AccelerationStripsPanel({ strips, onRemoveStrip, onUpdateStrip }: Props) {
+export function AccelerationStripsPanel({ strips, onRemoveStrip, onUpdateStrip, onUpdateStripFrac }: Props) {
const [open, setOpen] = useState(true)
// Auto-open when a strip is added
@@ -31,19 +31,45 @@ export function AccelerationStripsPanel({ strips, onRemoveStrip, onUpdateStrip }
: strips.map((s, i) => (
Strip {i + 1}
-
- {pct(s.startFrac)}–{pct(s.endFrac)}
-
-
{
+ const sf = Math.max(0, Math.min(v / 100, s.endFrac - 0.001))
+ onUpdateStripFrac(s.id, sf, s.endFrac)
+ }}
+ min={0}
+ max={s.endFrac * 100 - 0.1}
+ step={0.2}
+ decimals={1}
+ suffix="%"
+ />
+
+
–
+
+
{
+ const ef = Math.min(100, Math.max(v / 100, s.startFrac + 0.001))
+ onUpdateStripFrac(s.id, s.startFrac, ef)
+ }}
+ min={s.startFrac * 100 + 0.1}
+ max={100}
+ step={0.2}
+ decimals={1}
+ suffix="%"
+ />
+
+ onUpdateStrip(s.id, v)}
min={-50}
max={50}
- value={s.accel_ms2}
- onChange={e => onUpdateStrip(s.id, Number(e.target.value))}
- className={styles.accelInput}
+ step={0.1}
+ decimals={1}
+ suffix="m/s²"
/>
- m/s²
+