rvlib-shipkit 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- package/package.json +1 -1
- package/src/agent-time/mask.ts +43 -0
- package/src/agent-time/render.ts +187 -0
- package/src/agent-time/report.ts +335 -0
- package/src/agent-time/shape.ts +271 -0
- package/src/agent-time/signals.ts +84 -0
- package/src/agent-time/store.ts +379 -0
- package/src/agent-time/timeline.ts +218 -0
- package/src/agent-time/turns.ts +135 -0
- package/src/assets/kits/identity-kit.ts +5 -2
- package/src/cli/cmd_Commands.ts +9 -0
- package/src/cli/cmd_Review.ts +974 -0
- package/src/cli/cmd_Sound.ts +209 -0
- package/src/cli/cmd_Time.ts +112 -0
- package/src/cli/cmd_Trailer.ts +264 -6
- package/src/cli/kit/verb.ts +22 -4
- package/src/cli.ts +8 -4
- package/src/collections/collection-types.ts +6 -1
- package/src/collections/providers.ts +3 -0
- package/src/collections/review.ts +70 -0
- package/src/core/app-icon.ts +10 -6
- package/src/core/layout.ts +2 -0
- package/src/reflect/prompt-corpus.ts +15 -119
- package/src/reflect/transcript.ts +254 -0
- package/src/repo-config.ts +3 -0
- package/src/review/anim.ts +228 -0
- package/src/review/auto.ts +141 -0
- package/src/review/format.ts +158 -0
- package/src/review/http.ts +23 -0
- package/src/review/marks.ts +43 -0
- package/src/review/media.ts +45 -0
- package/src/review/model.ts +896 -0
- package/src/review/project.ts +126 -0
- package/src/review/role.ts +48 -0
- package/src/review/routes.ts +239 -0
- package/src/review/store.ts +1011 -0
- package/src/review/threads.ts +237 -0
- package/src/review/trailer-desk.ts +385 -0
- package/src/review/trailer-model.ts +183 -0
- package/src/review/trailer-routes.ts +136 -0
- package/src/review/unit.ts +183 -0
- package/src/review/watchers.ts +54 -0
- package/src/serve/embed.ts +35 -0
- package/src/serve/hub-app/activity-view.tsx +1 -1
- package/src/serve/hub-app/activity.css +0 -4
- package/src/serve/hub-app/admin-svc.ts +1 -1
- package/src/serve/hub-app/admin-view.tsx +1 -1
- package/src/serve/hub-app/dock-view.tsx +5 -4
- package/src/serve/hub-app/hash-route.ts +36 -1
- package/src/serve/hub-app/header-bar.tsx +3 -1
- package/src/serve/hub-app/home-st.ts +17 -3
- package/src/serve/hub-app/home-strip.tsx +3 -2
- package/src/serve/hub-app/home.html +1 -0
- package/src/serve/hub-app/hub-app.tsx +80 -11
- package/src/serve/hub-app/hub.css +83 -14
- package/src/serve/hub-app/icons.tsx +15 -0
- package/src/serve/hub-app/index.html +1 -0
- package/src/serve/hub-app/insights-view.tsx +4 -3
- package/src/serve/hub-app/keys.ts +14 -10
- package/src/serve/hub-app/layout-st.ts +63 -2
- package/src/serve/hub-app/md.ts +32 -0
- package/src/serve/hub-app/planned-view.tsx +3 -2
- package/src/serve/hub-app/planned.css +0 -1
- package/src/serve/hub-app/project-list.css +26 -6
- package/src/serve/hub-app/project-list.tsx +46 -10
- package/src/serve/hub-app/projects-svc.ts +7 -2
- package/src/serve/hub-app/repo-sections.ts +15 -3
- package/src/serve/hub-app/repo-st.ts +61 -4
- package/src/serve/hub-app/review/clip-st.ts +258 -0
- package/src/serve/hub-app/review/kind-view.tsx +240 -0
- package/src/serve/hub-app/review/kit.tsx +113 -0
- package/src/serve/hub-app/review/review-answer.tsx +269 -0
- package/src/serve/hub-app/review/review-board.tsx +46 -0
- package/src/serve/hub-app/review/review-list.tsx +156 -0
- package/src/serve/hub-app/review/review-page.tsx +96 -0
- package/src/serve/hub-app/review/review-st.ts +902 -0
- package/src/serve/hub-app/review/review-views.tsx +648 -0
- package/src/serve/hub-app/review/trailer-page.tsx +416 -0
- package/src/serve/hub-app/review/trailer-st.ts +602 -0
- package/src/serve/hub-app/review/trailer-timeline.tsx +207 -0
- package/src/serve/hub-app/review.css +389 -0
- package/src/serve/hub-app/theme-st.ts +56 -0
- package/src/serve/hub-app/tree-build.ts +4 -0
- package/src/serve/hub-app/tree-row.tsx +1 -1
- package/src/serve/hub-app/tree-svc.ts +4 -0
- package/src/serve/hub-app/wiki-st.ts +190 -0
- package/src/serve/hub-app/wikis-view.tsx +134 -5
- package/src/serve/hub-runtime.ts +9 -7
- package/src/serve/project-gutter-route.ts +25 -1
- package/src/serve/project-gutter.ts +1 -1
- package/src/serve/same-origin.ts +5 -1
- package/src/serve/serve-hub.ts +15 -0
- package/src/shipkit-files.ts +9 -5
- package/src/shot/client.ts +17 -5
- package/src/shot/shooter.ts +19 -3
- package/src/shot/shot-ask.ts +9 -1
- package/src/shot/stepped-clip.ts +53 -0
- package/src/trailer/adapter.ts +90 -6
- package/src/trailer/build.ts +459 -59
- package/src/trailer/ffmpeg.ts +22 -0
- package/src/trailer/fonts.ts +55 -0
- package/src/trailer/footage.ts +112 -43
- package/src/trailer/grammar.ts +864 -127
- package/src/trailer/graph.ts +308 -49
- package/src/trailer/holes.ts +72 -0
- package/src/trailer/load-unit.ts +20 -3
- package/src/trailer/look.ts +20 -3
- package/src/trailer/motion.ts +207 -0
- package/src/trailer/passage.ts +129 -0
- package/src/trailer/plan.ts +82 -23
- package/src/trailer/prune.ts +204 -0
- package/src/trailer/score/compose.ts +256 -0
- package/src/trailer/score/dsp.ts +272 -0
- package/src/trailer/score/gm-render.ts +43 -0
- package/src/trailer/score/gm.ts +90 -0
- package/src/trailer/score/midi.ts +143 -0
- package/src/trailer/score/palette.ts +188 -0
- package/src/trailer/score/pattern.ts +98 -0
- package/src/trailer/score/score.ts +228 -0
- package/src/trailer/score/sound.ts +123 -0
- package/src/trailer/score/synth.ts +383 -0
- package/src/trailer/sound/audio.ts +148 -0
- package/src/trailer/sound/brand.ts +42 -0
- package/src/trailer/sound/comfy.ts +38 -0
- package/src/trailer/sound/eleven.ts +72 -0
- package/src/trailer/sound/fluid.ts +71 -0
- package/src/trailer/sound/gen.ts +139 -0
- package/src/trailer/sound/index.ts +60 -0
- package/src/trailer/sound/presets.ts +69 -0
- package/src/trailer/sound/run.ts +189 -0
- package/src/trailer/states.ts +76 -0
- package/src/trailer/stitch.ts +92 -9
- package/src/trailer/titles.ts +471 -150
- package/src/trailer/url.ts +18 -3
- package/src/trailer/vocab.ts +34 -4
- package/src/trailer/words.ts +275 -0
- package/src/wiki/graph-mount.ts +3 -0
- package/src/wiki/graph-page.ts +45 -9
- package/src/wiki/graph-pages.ts +128 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
// the trailer page's timeline: the sections, the shots, the captions and the notes of the render on screen, a
|
|
2
|
+
// playhead, a click or a drag to seek, a hover with the shot's frame from the contact strip; then every shot as a card
|
|
3
|
+
import { observer } from 'mobx-react-lite'
|
|
4
|
+
import { useEffect, useRef, useState, type CSSProperties, type RefObject } from 'react'
|
|
5
|
+
import { clock, shotAt, type ShotSpan, type Timeline } from '../../../review/trailer-model.ts'
|
|
6
|
+
import { captionText, type PlacedNote, type TrailerSt } from './trailer-st.ts'
|
|
7
|
+
|
|
8
|
+
const RULER = 18
|
|
9
|
+
const SECTIONS = 22
|
|
10
|
+
const SHOTS = 46
|
|
11
|
+
const CAPTIONS = 22
|
|
12
|
+
const GAP = 3
|
|
13
|
+
const HEIGHT = RULER + SECTIONS + SHOTS + CAPTIONS + GAP * 3
|
|
14
|
+
const ROW = { ruler: 0, sections: RULER + GAP, shots: RULER + SECTIONS + GAP * 2, captions: RULER + SECTIONS + SHOTS + GAP * 3 }
|
|
15
|
+
|
|
16
|
+
/** a section's hue, one of the page's kind hues by its order: the shot blocks of a section share it */
|
|
17
|
+
export const hueOf = (tl: Timeline, section: string | null): string => {
|
|
18
|
+
const i = section === null ? -1 : tl.sections.findIndex((s) => s.name === section)
|
|
19
|
+
return i < 0 ? 'hue-none' : `hue-k${(i % 6) + 1}`
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** a shot's frame from the render's contact strip, `w` pixels wide; a plain tile when there is no strip */
|
|
23
|
+
export const Thumb = observer(({ st, index, w, style }: { st: TrailerSt; index: number; w: number; style?: CSSProperties }) => {
|
|
24
|
+
const s = st.shown
|
|
25
|
+
const url = st.stripUrl
|
|
26
|
+
const g = s?.strip
|
|
27
|
+
const h = Math.round((w * (s?.timeline.size[1] ?? 9)) / (s?.timeline.size[0] ?? 16))
|
|
28
|
+
const base: CSSProperties = { width: w, height: h, ...style }
|
|
29
|
+
if (!url || !g || !s) return <div className="tr-thumb" style={base} />
|
|
30
|
+
const n = s.timeline.shots.length
|
|
31
|
+
const rows = Math.ceil(n / g.cols)
|
|
32
|
+
const k = w / g.tileW
|
|
33
|
+
const col = index % g.cols
|
|
34
|
+
const row = Math.floor(index / g.cols)
|
|
35
|
+
return (
|
|
36
|
+
<div className="tr-thumb" style={{
|
|
37
|
+
...base,
|
|
38
|
+
backgroundImage: `url(${url})`,
|
|
39
|
+
backgroundSize: `${(g.cols * g.tileW + (g.cols - 1) * g.pad) * k}px ${(rows * g.tileH + (rows - 1) * g.pad) * k}px`,
|
|
40
|
+
backgroundPosition: `${-col * (g.tileW + g.pad) * k}px ${-row * (g.tileH + g.pad) * k}px`,
|
|
41
|
+
}} />
|
|
42
|
+
)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
/** the ruler's step: the smallest that leaves room for a label */
|
|
46
|
+
function stepOf(pps: number): number {
|
|
47
|
+
for (const s of [0.5, 1, 2, 5, 10, 15, 30, 60]) if (s * pps >= 56) return s
|
|
48
|
+
return 120
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export const TrailerTimeline = observer(({ st }: { st: TrailerSt }) => {
|
|
52
|
+
const tl = st.timeline
|
|
53
|
+
const scroller = useRef<HTMLDivElement>(null)
|
|
54
|
+
const [width, setWidth] = useState(800)
|
|
55
|
+
const [hover, setHover] = useState<{ t: number; x: number } | null>(null)
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
const el = scroller.current
|
|
58
|
+
if (!el) return
|
|
59
|
+
const ro = new ResizeObserver(() => setWidth(el.clientWidth))
|
|
60
|
+
ro.observe(el)
|
|
61
|
+
setWidth(el.clientWidth)
|
|
62
|
+
return () => ro.disconnect()
|
|
63
|
+
}, [])
|
|
64
|
+
// a zoom keeps the playhead where the eye is
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
const el = scroller.current
|
|
67
|
+
if (!el || !tl) return
|
|
68
|
+
el.scrollLeft = Math.max(0, (st.time / tl.total) * width * st.zoom - width / 2)
|
|
69
|
+
}, [st.zoom, width, tl, st])
|
|
70
|
+
if (!tl) return null
|
|
71
|
+
const W = Math.max(width, width * st.zoom)
|
|
72
|
+
const xOf = (t: number): number => (t / tl.total) * W
|
|
73
|
+
const tOf = (clientX: number): number => {
|
|
74
|
+
const el = scroller.current
|
|
75
|
+
if (!el) return 0
|
|
76
|
+
const r = el.getBoundingClientRect()
|
|
77
|
+
return Math.max(0, Math.min(tl.total, ((clientX - r.left + el.scrollLeft) / W) * tl.total))
|
|
78
|
+
}
|
|
79
|
+
const step = stepOf(W / tl.total)
|
|
80
|
+
const ticks: number[] = []
|
|
81
|
+
for (let t = 0; t <= tl.total + 1e-6; t += step) ticks.push(t)
|
|
82
|
+
const cur = st.shot
|
|
83
|
+
const lit = new Set(st.captionsKey.split('\n'))
|
|
84
|
+
return (
|
|
85
|
+
<div className="tr-timelinewrap">
|
|
86
|
+
<div ref={scroller} className="tr-timeline"
|
|
87
|
+
onPointerDown={(e) => {
|
|
88
|
+
if ((e.target as Element).closest('[data-note]')) return
|
|
89
|
+
e.currentTarget.setPointerCapture(e.pointerId)
|
|
90
|
+
st.seekPaused(tOf(e.clientX))
|
|
91
|
+
}}
|
|
92
|
+
onPointerMove={(e) => {
|
|
93
|
+
const t = tOf(e.clientX)
|
|
94
|
+
if (e.buttons & 1 && e.currentTarget.hasPointerCapture(e.pointerId)) st.seekPaused(t)
|
|
95
|
+
setHover({ t, x: e.clientX })
|
|
96
|
+
}}
|
|
97
|
+
onPointerLeave={() => setHover(null)}>
|
|
98
|
+
<div className="tr-track" style={{ width: W, height: HEIGHT }}>
|
|
99
|
+
{ticks.map((t) => (
|
|
100
|
+
<div key={t} className="tr-tick" style={{ left: xOf(t), top: ROW.ruler, height: HEIGHT }}>
|
|
101
|
+
<span>{t >= 60 ? `${Math.floor(t / 60)}:${String(Math.floor(t % 60)).padStart(2, '0')}` : `${t}s`}</span>
|
|
102
|
+
</div>
|
|
103
|
+
))}
|
|
104
|
+
{tl.sections.map((s) => (
|
|
105
|
+
<div key={`${s.name}@${s.start}`} className={`tr-section ${hueOf(tl, s.name)}${st.section?.name === s.name ? ' on' : ''}`} title={`${s.name} · ${clock(s.start)} → ${clock(s.end)}`}
|
|
106
|
+
style={{ left: xOf(s.start) + 1, width: Math.max(2, xOf(s.end) - xOf(s.start) - 2), top: ROW.sections, height: SECTIONS, lineHeight: `${SECTIONS}px` }}>
|
|
107
|
+
{s.name}
|
|
108
|
+
</div>
|
|
109
|
+
))}
|
|
110
|
+
{tl.shots.map((s, i) => <ShotBlock key={`${s.name}@${i}`} s={s} i={i} x={xOf(s.start)} w={xOf(s.end) - xOf(s.start)} on={cur === s} hue={hueOf(tl, s.section)} />)}
|
|
111
|
+
{tl.shots.flatMap((s) =>
|
|
112
|
+
s.captions.map((c, j) => (
|
|
113
|
+
<div key={`${s.name}-${j}`} className={`tr-caption${lit.has(`${c.start}|${c.text}`) ? ' on' : ''}`} title={captionText(c)}
|
|
114
|
+
style={{ left: xOf(c.start), width: Math.max(2, xOf(Math.min(c.end, tl.total)) - xOf(c.start)), top: ROW.captions, height: CAPTIONS, lineHeight: `${CAPTIONS}px` }}>
|
|
115
|
+
{captionText(c).replaceAll('\n', ' ')}
|
|
116
|
+
</div>
|
|
117
|
+
)),
|
|
118
|
+
)}
|
|
119
|
+
{st.here.map((n) => <NotePin key={n.note.id} st={st} n={n} x={xOf(n.at ?? 0)} />)}
|
|
120
|
+
{st.draft ? <div className="tr-draftmark" style={{ left: xOf(st.draft.time) - 1, height: HEIGHT }} /> : null}
|
|
121
|
+
<Playhead st={st} W={W} total={tl.total} scroller={scroller} />
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
{hover ? <HoverCard st={st} t={hover.t} x={hover.x} scroller={scroller} /> : null}
|
|
125
|
+
</div>
|
|
126
|
+
)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const ShotBlock = ({ s, i, x, w, on, hue }: { s: ShotSpan; i: number; x: number; w: number; on: boolean; hue: string }) => (
|
|
130
|
+
<div className={`tr-shot ${hue}${on ? ' on' : ''}${i % 2 ? ' odd' : ''}`} title={`${s.name} · ${clock(s.start)} · ${s.length} s`}
|
|
131
|
+
style={{ left: x + 0.5, width: Math.max(1, w - 1), top: ROW.shots, height: SHOTS }}>
|
|
132
|
+
{w > 26 ? s.name : ''}
|
|
133
|
+
{w > 44 ? <div className="tr-shottime">{clock(s.start)}</div> : null}
|
|
134
|
+
</div>
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
const NotePin = observer(({ st, n, x }: { st: TrailerSt; n: PlacedNote; x: number }) => {
|
|
138
|
+
const on = st.selected === n.note.id
|
|
139
|
+
return (
|
|
140
|
+
<>
|
|
141
|
+
<div className={`tr-noteline ns-${n.note.state}${on ? ' on' : ''}`} style={{ left: x, top: ROW.sections, height: HEIGHT - ROW.sections }} />
|
|
142
|
+
<div data-note className={`tr-notepin ns-${n.note.state}${on ? ' on' : ''}`} title={`#${n.note.n} · ${n.note.text}`} style={{ left: x - 8 }}
|
|
143
|
+
onPointerDown={(e) => e.stopPropagation()} onClick={() => st.goTo(n)} />
|
|
144
|
+
</>
|
|
145
|
+
)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
/** the playhead; while it plays, the timeline scrolls to keep it in view */
|
|
149
|
+
const Playhead = observer(({ st, W, total, scroller }: { st: TrailerSt; W: number; total: number; scroller: RefObject<HTMLDivElement | null> }) => {
|
|
150
|
+
const x = (st.time / total) * W
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
const el = scroller.current
|
|
153
|
+
if (!el) return
|
|
154
|
+
if (x < el.scrollLeft + 8 || x > el.scrollLeft + el.clientWidth - 24) el.scrollLeft = Math.max(0, x - el.clientWidth * 0.2)
|
|
155
|
+
}, [x, scroller])
|
|
156
|
+
return <div className="tr-playhead" style={{ left: x - 1, height: HEIGHT }}><div className="tr-playknob" /></div>
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
/** under the mouse: the shot's frame, its name, the time */
|
|
160
|
+
const HoverCard = observer(({ st, t, x, scroller }: { st: TrailerSt; t: number; x: number; scroller: RefObject<HTMLDivElement | null> }) => {
|
|
161
|
+
const tl = st.timeline
|
|
162
|
+
if (!tl) return null
|
|
163
|
+
const s = shotAt(tl, t)
|
|
164
|
+
if (!s) return null
|
|
165
|
+
const i = tl.shots.indexOf(s)
|
|
166
|
+
const top = scroller.current?.getBoundingClientRect().top ?? 0
|
|
167
|
+
return (
|
|
168
|
+
<div className="tr-hover" style={{ left: Math.max(8, Math.min(window.innerWidth - 216, x - 104)), bottom: window.innerHeight - (top - 8) }}>
|
|
169
|
+
<Thumb st={st} index={i} w={192} />
|
|
170
|
+
<div className="tr-hoverrow"><b>{s.name}</b><span>{clock(t)}</span></div>
|
|
171
|
+
<div className="tr-dim">{s.section ?? 'opening'} · shot {i + 1}/{tl.shots.length} · {s.length} s</div>
|
|
172
|
+
</div>
|
|
173
|
+
)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
/** every shot as a card: its frame, its name, its start and length, its open notes; the one on screen lit and kept in
|
|
177
|
+
* view */
|
|
178
|
+
export const ShotCards = observer(({ st }: { st: TrailerSt }) => {
|
|
179
|
+
const tl = st.timeline
|
|
180
|
+
const box = useRef<HTMLDivElement>(null)
|
|
181
|
+
const cur = st.shotIndex
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
const el = box.current
|
|
184
|
+
const card = el?.children[cur] as HTMLElement | undefined
|
|
185
|
+
if (!el || !card) return
|
|
186
|
+
const left = card.offsetLeft - el.offsetLeft
|
|
187
|
+
if (left < el.scrollLeft || left + card.offsetWidth > el.scrollLeft + el.clientWidth) el.scrollTo({ left: left - el.clientWidth / 2 + card.offsetWidth / 2, behavior: 'smooth' })
|
|
188
|
+
}, [cur])
|
|
189
|
+
if (!tl) return null
|
|
190
|
+
const counts = new Map<string, number>()
|
|
191
|
+
for (const n of st.here) if (n.note.state === 'open') counts.set(n.note.shot, (counts.get(n.note.shot) ?? 0) + 1)
|
|
192
|
+
return (
|
|
193
|
+
<div ref={box} className="tr-shotcards">
|
|
194
|
+
{tl.shots.map((s, i) => {
|
|
195
|
+
const n = counts.get(s.name) ?? 0
|
|
196
|
+
return (
|
|
197
|
+
<button type="button" key={`${s.name}@${i}`} className={`tr-shotcard ${hueOf(tl, s.section)}${i === cur ? ' on' : ''}`} onMouseDown={(e) => e.preventDefault()} onClick={() => st.seek(s.start)}>
|
|
198
|
+
<Thumb st={st} index={i} w={136} />
|
|
199
|
+
<div className="tr-shotname"><span className="tr-dim">{i + 1} </span>{s.name}</div>
|
|
200
|
+
<div className="tr-dim tr-small">{clock(s.start)} · {s.length} s{s.captions.length > 0 ? ` · ${s.captions.length} title${s.captions.length > 1 ? 's' : ''}` : ''}</div>
|
|
201
|
+
{n > 0 ? <span className="tr-shotnotes">{n}</span> : null}
|
|
202
|
+
</button>
|
|
203
|
+
)
|
|
204
|
+
})}
|
|
205
|
+
</div>
|
|
206
|
+
)
|
|
207
|
+
})
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
/* the review page and the trailer page (hub-app/review/): pkm-multi's Revue and Trailer tabs on the hub's tokens.
|
|
2
|
+
A status, a reaction, a note state and a section each set --tone or --hue, and the parts read it, so no rule here
|
|
3
|
+
writes a colour (tests/hub-css-invariants.test.ts) */
|
|
4
|
+
.st-pending{--tone:var(--blue)}
|
|
5
|
+
.st-approved,.re-approved{--tone:var(--ok)}
|
|
6
|
+
.st-approved-with-fix,.re-approved-with-fix,.st-raised{--tone:var(--warn)}
|
|
7
|
+
.st-rejected,.re-rejected{--tone:var(--red)}
|
|
8
|
+
.st-archived,.st-superseded,.st-withdrawn,.st-wontfix,.st-rated{--tone:var(--dim)}
|
|
9
|
+
.st-wip{--tone:var(--k2)}
|
|
10
|
+
.st-fixed{--tone:var(--k3)}
|
|
11
|
+
.ns-open{--tone:var(--warn)}
|
|
12
|
+
.ns-done{--tone:var(--ok)}
|
|
13
|
+
.ns-wontfix{--tone:var(--dim)}
|
|
14
|
+
.hue-k1{--hue:var(--k1)}.hue-k2{--hue:var(--k2)}.hue-k3{--hue:var(--k3)}.hue-k4{--hue:var(--k4)}.hue-k5{--hue:var(--k5)}.hue-k6{--hue:var(--k6)}
|
|
15
|
+
.hue-none{--hue:var(--dim)}
|
|
16
|
+
|
|
17
|
+
/* ── the three columns ── */
|
|
18
|
+
.rv-cols{flex:1;min-height:0}
|
|
19
|
+
.rv-pane{height:100%;min-width:0;display:flex;flex-direction:column}
|
|
20
|
+
.rv-scroll{flex:1;min-height:0;overflow-y:auto}
|
|
21
|
+
.rv-dim,.tr-dim{color:var(--dim)}
|
|
22
|
+
.rv-small,.tr-small{font-size:11px}
|
|
23
|
+
.rv-mono,.tr-mono{font:11.5px ui-monospace,Menlo,monospace}
|
|
24
|
+
.rv-pre{white-space:pre-wrap;overflow-wrap:anywhere}
|
|
25
|
+
.rv-center{text-align:center}
|
|
26
|
+
.rv-empty{padding:var(--s3);color:var(--dim);font-size:12.5px;display:flex;gap:var(--s2);align-items:center}
|
|
27
|
+
.rv-err{padding:var(--s1) var(--s3);color:var(--errink);font-size:12px;white-space:pre-wrap}
|
|
28
|
+
.rv-lanehead .sp,.rv-viewhead .sp,.tr-cutrow .sp,.tr-transport .sp,.tr-noteshead .sp,.tr-noteacts .sp{flex:1}
|
|
29
|
+
.rv-divider{display:flex;align-items:center;gap:var(--s2);margin:var(--s2) 0 var(--s1);color:var(--dim);font-size:11px}
|
|
30
|
+
.rv-divider::after{content:'';flex:1;border-top:1px solid var(--line)}
|
|
31
|
+
.rv-cols textarea,.tr-notescol textarea,.rv-phone textarea{min-height:0;font:12.5px/1.45 system-ui,sans-serif;padding:var(--s1) var(--s2)}
|
|
32
|
+
|
|
33
|
+
/* ── the list ── */
|
|
34
|
+
.rv-listcol{height:100%;display:flex;flex-direction:column;min-height:0;background:var(--panel);container-type:inline-size}
|
|
35
|
+
.rv-filters{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s2) var(--s3);border-bottom:1px solid var(--line)}
|
|
36
|
+
.rv-search{background:var(--bg);border:1px solid var(--line);border-radius:4px;color:var(--ink);padding:var(--s1) var(--s2);font-size:12.5px;outline:none}
|
|
37
|
+
.rv-search:focus{border-color:var(--accent)}
|
|
38
|
+
.rv-selects{display:flex;gap:var(--s1)}
|
|
39
|
+
.rv-selects select{flex:1;min-width:0}
|
|
40
|
+
.rv-whose{align-self:flex-start}
|
|
41
|
+
.rv-switches{display:flex;gap:var(--s3);font-size:12px}
|
|
42
|
+
.rv-switch{display:inline-flex;align-items:center;gap:var(--s1);cursor:pointer;color:var(--ink)}
|
|
43
|
+
.rv-count{font-size:11px;color:var(--dim)}
|
|
44
|
+
.rv-listscroll{flex:1;min-height:0;overflow-y:auto;padding:var(--s1) 0 var(--s4)}
|
|
45
|
+
.rv-lanehead{display:flex;align-items:center;gap:var(--s2);margin:var(--s2) var(--s2) var(--s0);padding:var(--s1) var(--s2);border-radius:4px;border-left:4px solid var(--lane,var(--dim));background:var(--panel2);font-size:12px}
|
|
46
|
+
.rv-lanehead b{color:var(--lane,var(--dim))}
|
|
47
|
+
.rv-row{display:flex;gap:var(--s2);align-items:center;margin:var(--s1) var(--s2);padding:var(--s1) var(--s2);border-radius:6px;cursor:pointer;
|
|
48
|
+
border:1px solid color-mix(in srgb,var(--tone) 45%,var(--line));background:color-mix(in srgb,var(--tone) 9%,var(--panel))}
|
|
49
|
+
.rv-row:hover{background:color-mix(in srgb,var(--tone) 16%,var(--panel))}
|
|
50
|
+
.rv-row.on{background:color-mix(in srgb,var(--tone) 22%,var(--panel));box-shadow:inset 3px 0 0 var(--accent)}
|
|
51
|
+
.rv-row.laned,.rv-vrow.laned{border-left:4px solid var(--lane)}
|
|
52
|
+
.rv-row.muted .rv-thumb,.rv-row.muted .rv-rowbody{opacity:.55}
|
|
53
|
+
.rv-thumb{width:56px;height:56px;flex:none;border-radius:4px;overflow:hidden;background:repeating-conic-gradient(var(--chk1) 0 25%,var(--chk2) 0 50%) 0 0/12px 12px}
|
|
54
|
+
.rv-thumb.sm{width:32px;height:32px}
|
|
55
|
+
.rv-thumb.xs{width:36px;height:36px;cursor:pointer}
|
|
56
|
+
.rv-thumbimg{width:100%;height:100%;object-fit:cover;display:block}
|
|
57
|
+
.rv-thumbnone{width:100%;height:100%;display:grid;place-items:center;color:var(--dim);background:var(--panel2)}
|
|
58
|
+
.rv-rowbody{flex:1;min-width:0}
|
|
59
|
+
.rv-rowtitle{font-size:13px;line-height:1.3;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
|
60
|
+
.rv-rowtitle.strong{font-weight:700}
|
|
61
|
+
.rv-unread{display:inline-block;width:8px;height:8px;border-radius:4px;background:var(--blue);margin-right:var(--s1);vertical-align:middle}
|
|
62
|
+
.rv-rowmeta{display:flex;gap:var(--s1);align-items:center;margin-top:var(--s0);min-width:0}
|
|
63
|
+
.rv-badge{flex:none;font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:0 var(--s1);border-radius:3px;line-height:16px;
|
|
64
|
+
color:var(--bg);background:var(--tone,var(--dim));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:120px}
|
|
65
|
+
.rv-badge.outline{background:none;color:var(--ink);border:1px solid var(--line)}
|
|
66
|
+
.rv-about{font-size:11px;color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
|
|
67
|
+
.rv-fold{flex:none;display:grid;place-items:center;width:24px;height:24px;padding:0;border:1px solid var(--line);border-radius:999px;color:var(--dim)}
|
|
68
|
+
.rv-fold .cvt{width:14px;height:14px;transform:rotate(90deg)}
|
|
69
|
+
.rv-fold .cvt.open{transform:rotate(-90deg)}
|
|
70
|
+
.rv-fold:hover{color:var(--ink);border-color:var(--accent)}
|
|
71
|
+
/* a narrow list: the title on its own line on top, a smaller image under it beside the badges */
|
|
72
|
+
@container (max-width:250px){
|
|
73
|
+
.rv-row{display:grid;grid-template-columns:40px minmax(0,1fr) auto;grid-template-areas:"title title fold" "thumb meta meta" "rework rework rework";align-items:center;column-gap:var(--s2);row-gap:var(--s1)}
|
|
74
|
+
.rv-row .rv-rowbody{display:contents}
|
|
75
|
+
.rv-row .rv-rowtitle{grid-area:title}
|
|
76
|
+
.rv-row .rv-thumb{grid-area:thumb;width:40px;height:40px}
|
|
77
|
+
.rv-row .rv-rowmeta{grid-area:meta;flex-wrap:wrap;margin-top:0}
|
|
78
|
+
.rv-row .rv-fold{grid-area:fold}
|
|
79
|
+
.rv-row > .rv-rowbody > :not(.rv-rowtitle):not(.rv-rowmeta){grid-area:rework}
|
|
80
|
+
.rv-row.muted .rv-rowtitle,.rv-row.muted .rv-rowmeta{opacity:.55}
|
|
81
|
+
/* the filters: one select a line, the whose bar across the width, the switches one a line */
|
|
82
|
+
.rv-filters{padding:var(--s2)}
|
|
83
|
+
.rv-selects{flex-direction:column}
|
|
84
|
+
.rv-whose{align-self:stretch}
|
|
85
|
+
.seg.rv-whose button{flex:1 1 auto;justify-content:center;padding:0 var(--s1);font-size:11px;white-space:nowrap}
|
|
86
|
+
.rv-switches{flex-direction:column;gap:var(--s1)}
|
|
87
|
+
}
|
|
88
|
+
.rv-vrow{display:flex;gap:var(--s1);align-items:center;margin:var(--s0) var(--s2) var(--s0) var(--s4);padding:var(--s0) var(--s1);border-radius:4px;cursor:pointer;opacity:.8;
|
|
89
|
+
border:1px solid color-mix(in srgb,var(--tone) 40%,var(--line));background:color-mix(in srgb,var(--tone) 8%,var(--panel));font-size:11.5px}
|
|
90
|
+
.rv-vrow.on{opacity:1;box-shadow:inset 3px 0 0 var(--accent)}
|
|
91
|
+
.rv-vn{flex:none}
|
|
92
|
+
.rv-vtitle{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
93
|
+
.rv-lane{flex:none;font-size:10px;font-weight:700;color:var(--bg);background:var(--lane);border-radius:3px;padding:0 var(--s1);line-height:16px}
|
|
94
|
+
.rv-auto{flex:none;font-size:10px;font-weight:700;color:var(--bg);background:var(--warn);border-radius:3px;padding:0 var(--s1);line-height:16px}
|
|
95
|
+
.rv-reworkrow{display:flex;margin-top:var(--s1)}
|
|
96
|
+
.rv-rework{display:inline-flex;align-items:center;gap:var(--s1);font-size:11px;font-weight:700;color:var(--lane);border:1px solid var(--lane);border-radius:4px;padding:0 var(--s1);white-space:nowrap}
|
|
97
|
+
.rv-spin{width:10px;height:10px;border-radius:50%;border:2px solid var(--lane);border-top-color:transparent;animation:rot 2.4s linear infinite}
|
|
98
|
+
.rv-listen{display:inline-flex;align-items:center;gap:var(--s1);font-size:11px;font-weight:700;color:var(--dim);border:1px solid var(--line);border-radius:10px;padding:0 var(--s2);white-space:nowrap;line-height:18px}
|
|
99
|
+
.rv-listen.on{color:var(--ok);border-color:color-mix(in srgb,var(--ok) 55%,var(--line))}
|
|
100
|
+
|
|
101
|
+
/* ── the views ── */
|
|
102
|
+
.rv-views{display:flex;flex-direction:column;gap:var(--s4);padding:var(--s3)}
|
|
103
|
+
.rv-viewsbar{display:flex;flex-wrap:wrap;gap:var(--s2);justify-content:space-between;align-items:center}
|
|
104
|
+
.rv-viewsctl{display:inline-flex;gap:var(--s2);align-items:center}
|
|
105
|
+
.rv-jumps{display:flex;flex-wrap:wrap;gap:var(--s1);flex:1;min-width:0}
|
|
106
|
+
.rv-jump{font-size:11.5px;padding:var(--s0) var(--s2);border-color:transparent;color:var(--dim);display:inline-flex;align-items:center;gap:var(--s1)}
|
|
107
|
+
.rv-jump.on{color:var(--ink);border-color:var(--line);background:var(--panel2)}
|
|
108
|
+
.rv-jdot{width:8px;height:8px;border-radius:4px;background:var(--tone)}
|
|
109
|
+
.rv-view{scroll-margin-top:8px;padding-left:var(--s2);border-left:4px solid transparent}
|
|
110
|
+
.rv-view.active{border-left-color:var(--line)}
|
|
111
|
+
.rv-view[class*=' re-']{border-left-color:var(--tone)}
|
|
112
|
+
.rv-viewhead{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;margin-bottom:var(--s2)}
|
|
113
|
+
.rv-viewname{font-size:14px}
|
|
114
|
+
.rv-reacts{display:inline-flex;gap:var(--s1)}
|
|
115
|
+
.rv-react{font-size:11.5px;padding:0 var(--s2);line-height:20px;color:var(--tone);border-color:color-mix(in srgb,var(--tone) 45%,var(--line));background:color-mix(in srgb,var(--tone) 10%,transparent)}
|
|
116
|
+
.rv-react.on{color:var(--bg);background:var(--tone);border-color:var(--tone)}
|
|
117
|
+
.rv-react.off{opacity:.45}
|
|
118
|
+
.rv-word{margin-top:var(--s2)}
|
|
119
|
+
.rv-raised{padding:var(--s2) var(--s3);border:1px solid var(--line);border-left:4px solid var(--warn);border-radius:4px;background:var(--panel)}
|
|
120
|
+
.rv-raisedimg{display:block;max-width:100%;max-height:320px;margin-top:var(--s2);border-radius:4px}
|
|
121
|
+
.rv-pairgrid{display:grid;gap:var(--s2)}
|
|
122
|
+
.rv-cell{display:flex;flex-direction:column;align-items:center;gap:var(--s0);min-width:0}
|
|
123
|
+
.rv-frame{position:relative;width:100%;max-width:100%;border-radius:4px;border:1px solid var(--line);overflow:hidden;
|
|
124
|
+
background:repeating-conic-gradient(var(--chk1) 0 25%,var(--chk2) 0 50%) 0 0/16px 16px}
|
|
125
|
+
.rv-frame.swipe{cursor:ew-resize;touch-action:none}
|
|
126
|
+
.rv-fill{position:absolute;inset:0}
|
|
127
|
+
.rv-caption{font-size:11px;color:var(--dim)}
|
|
128
|
+
.rv-caption.mod,.rv-modcap{color:var(--k2)}
|
|
129
|
+
.rv-curtain{position:absolute;top:0;bottom:0;width:2px;transform:translateX(-1px);background:var(--k2);pointer-events:none}
|
|
130
|
+
.rv-modes{position:relative;display:inline-flex;flex-direction:column;gap:var(--s1)}
|
|
131
|
+
.rv-onion{position:absolute;top:100%;left:0;right:0;z-index:3;margin-top:var(--s0)}
|
|
132
|
+
.rv-marks{position:absolute;inset:0;user-select:none}
|
|
133
|
+
.rv-marks.draw{cursor:crosshair}
|
|
134
|
+
.rv-marks.pick{cursor:pointer}
|
|
135
|
+
.rv-markimg,.rv-video{display:block;width:100%;height:100%;pointer-events:none}
|
|
136
|
+
.rv-rings{position:absolute;inset:0;width:100%;height:100%;pointer-events:none}
|
|
137
|
+
.rv-ring{fill:none;stroke:var(--warn);stroke-width:3}
|
|
138
|
+
.rv-ringshade{fill:none;stroke:var(--solid);stroke-opacity:.35;stroke-width:7}
|
|
139
|
+
.rv-rect{position:absolute;border:2px solid var(--warn);box-shadow:0 0 0 1px var(--hi1);background:color-mix(in srgb,var(--warn) 7%,transparent);cursor:pointer}
|
|
140
|
+
.rv-rect.on{border-width:3px;border-color:var(--blue)}
|
|
141
|
+
.rv-rect.faint{border-style:dashed;opacity:.6;box-shadow:none;background:none}
|
|
142
|
+
.rv-rectn{position:absolute;left:-2px;top:-2px;transform:translateY(-100%);padding:0 var(--s1);border-radius:3px;background:var(--warn);color:var(--bg);font-size:11px;font-weight:800;line-height:16px;white-space:nowrap}
|
|
143
|
+
.rv-rect.on .rv-rectn{background:var(--blue)}
|
|
144
|
+
.rv-drag{position:absolute;border:2px dashed var(--warn)}
|
|
145
|
+
.rv-downloads{display:flex;gap:var(--s2);justify-content:flex-end;margin-top:var(--s1)}
|
|
146
|
+
.rv-dl{font-size:11.5px;text-decoration:none}
|
|
147
|
+
.rv-gallery{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:flex-start}
|
|
148
|
+
.rv-tile{display:flex;flex-direction:column;gap:var(--s1);padding:var(--s1);border-radius:6px;border:2px solid var(--line)}
|
|
149
|
+
.rv-tile[class*=' re-']{border-color:var(--tone);background:color-mix(in srgb,var(--tone) 8%,transparent)}
|
|
150
|
+
.rv-tile.big{width:100%}
|
|
151
|
+
.rv-tileimg{border-radius:4px;cursor:zoom-in;width:100%;background:repeating-conic-gradient(var(--chk1) 0 25%,var(--chk2) 0 50%) 0 0/12px 12px}
|
|
152
|
+
.rv-tile.big .rv-tileimg{cursor:zoom-out}
|
|
153
|
+
.rv-tileimg img{display:block;width:100%;height:100%;object-fit:contain}
|
|
154
|
+
.rv-tilelabel{font-size:11px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
155
|
+
.rv-clipbar{display:flex;gap:var(--s1);align-items:center;margin-top:var(--s2)}
|
|
156
|
+
.rv-clipbar button{padding:0 var(--s2);line-height:22px}
|
|
157
|
+
.rv-scrub{flex:1;min-width:60px}
|
|
158
|
+
.rv-sound{display:inline-flex;align-items:center;gap:var(--s1)}
|
|
159
|
+
.rv-sound button{padding:0 var(--s1);line-height:22px}
|
|
160
|
+
.rv-sound input{width:72px}
|
|
161
|
+
.rv-phonepair{display:flex;flex-direction:column;gap:var(--s2)}
|
|
162
|
+
/* options: one thin row a view, one below the other; the row playing or last touched has the line, the picked one its tone */
|
|
163
|
+
.rv-opts{display:flex;flex-direction:column;gap:var(--s1)}
|
|
164
|
+
.rv-opt{scroll-margin-top:8px;padding:var(--s1) var(--s2);border-radius:6px;border:1px solid var(--line);border-left:4px solid transparent;background:var(--panel)}
|
|
165
|
+
.rv-opt.active{border-left-color:var(--accent)}
|
|
166
|
+
.rv-opt[class*=' re-']{border-left-color:var(--tone)}
|
|
167
|
+
.rv-opt.picked{--tone:var(--ok);border-color:var(--tone);border-left-color:var(--tone);background:color-mix(in srgb,var(--tone) 9%,var(--panel))}
|
|
168
|
+
.rv-optrow{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;min-height:32px}
|
|
169
|
+
.rv-optn{flex:none;width:16px;text-align:right;font:600 12px ui-monospace,Menlo,monospace;color:var(--dim)}
|
|
170
|
+
.rv-optplay{flex:none;width:32px;height:28px;padding:0;font-size:13px}
|
|
171
|
+
.rv-optplay.on{color:var(--bg);background:var(--accent);border-color:var(--accent)}
|
|
172
|
+
.rv-optlabel{flex:0 1 auto;min-width:48px;max-width:30%;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
173
|
+
.rv-optthumb{flex:none;height:32px;max-width:72px;border-radius:3px;overflow:hidden;cursor:zoom-in;border:1px solid var(--line);background:var(--panel2)}
|
|
174
|
+
.rv-optthumb.img{width:48px}
|
|
175
|
+
.rv-optthumb img{display:block;width:100%;height:100%;object-fit:cover}
|
|
176
|
+
.rv-strip{position:relative;flex:1 1 140px;min-width:120px;height:28px;border-radius:3px;cursor:pointer;touch-action:none;background:var(--panel2);border:1px solid var(--line);overflow:hidden}
|
|
177
|
+
.rv-stripdone{position:absolute;inset:0 auto 0 0;background:var(--wash)}
|
|
178
|
+
/* a waveform is a mask filled with tokens: --dim to play (5.0:1 on --panel2 light, 5.3:1 dark), --accent played
|
|
179
|
+
(4.9:1 both) */
|
|
180
|
+
.rv-stripwave{position:absolute;inset:0;background:var(--dim)}
|
|
181
|
+
.rv-stripwave.done{background:var(--accent)}
|
|
182
|
+
.rv-stripwave.full{background:var(--accent)}
|
|
183
|
+
.rv-wavebox{position:relative;width:100%;border-radius:4px;background:var(--panel2)}
|
|
184
|
+
.rv-striphead{position:absolute;top:0;bottom:0;width:2px;transform:translateX(-1px);background:var(--accent)}
|
|
185
|
+
.rv-opttime{flex:none;font-size:11px;color:var(--dim)}
|
|
186
|
+
.rv-optacts{flex:none;display:inline-flex;gap:var(--s1);align-items:center;margin-left:auto}
|
|
187
|
+
.rv-optacts > button{padding:0 var(--s1);line-height:22px}
|
|
188
|
+
.rv-optacts > button.on{border-color:var(--accent)}
|
|
189
|
+
.rv-stars{display:inline-flex}
|
|
190
|
+
.rv-stars button{border:0;background:none;padding:0;font-size:16px;line-height:22px;color:var(--dim)}
|
|
191
|
+
.rv-stars button.on{color:var(--warn)}
|
|
192
|
+
.rv-pick{font-weight:700;padding:0 var(--s3)!important;color:var(--ok);border-color:color-mix(in srgb,var(--ok) 55%,var(--line))}
|
|
193
|
+
.rv-pick.on{color:var(--bg);background:var(--ok);border-color:var(--ok)}
|
|
194
|
+
.rv-optnote{margin:var(--s0) 0 0 var(--s4);font-size:12.5px;color:var(--ink)}
|
|
195
|
+
.rv-opt .rv-word{margin:var(--s1) 0 0 var(--s4);width:calc(100% - var(--s4))}
|
|
196
|
+
.rv-optbody{margin-top:var(--s2)}
|
|
197
|
+
|
|
198
|
+
/* ── the answer ── */
|
|
199
|
+
.rv-form{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s3)}
|
|
200
|
+
.rv-title{margin:0;font-size:16px;line-height:1.3;color:var(--ink)}
|
|
201
|
+
/* the card's header: the title, one tight line of state, then what the agent says at full ink; --dim holds 5.6:1 or
|
|
202
|
+
more on --bg and --panel in both themes */
|
|
203
|
+
.rv-head{display:flex;flex-direction:column;gap:var(--s1)}
|
|
204
|
+
.rv-meta{display:flex;flex-wrap:wrap;gap:var(--s1) var(--s2);align-items:center;font-size:12px;color:var(--dim);line-height:18px}
|
|
205
|
+
.rv-meta .rv-badge{font-size:10px;line-height:18px;max-width:none}
|
|
206
|
+
.rv-copyid{font-size:11.5px;padding:0 var(--s1);line-height:18px;color:var(--dim)}
|
|
207
|
+
.rv-copyid:hover{color:var(--ink)}
|
|
208
|
+
.rv-what{font-size:13.5px;line-height:1.45;color:var(--ink)}
|
|
209
|
+
.rv-what ul{margin:var(--s0) 0;padding-left:var(--s4)}
|
|
210
|
+
.rv-what p{margin:var(--s0) 0}
|
|
211
|
+
.rv-why{color:var(--dim);font-size:12px}
|
|
212
|
+
.rv-headverdicts{display:flex;flex-wrap:wrap;gap:var(--s1);align-items:center;margin-top:var(--s1)}
|
|
213
|
+
.rv-headverdicts .rv-verdict{padding:0 var(--s2);line-height:24px;font-size:12.5px}
|
|
214
|
+
.rv-keeps{color:var(--ok);font-size:13px}
|
|
215
|
+
.rv-facts{display:flex;flex-direction:column}
|
|
216
|
+
.rv-fact{display:flex;gap:var(--s2);align-items:center;min-height:22px;font-size:12.5px}
|
|
217
|
+
.rv-factl{width:64px;flex:none;color:var(--dim);font-size:12px}
|
|
218
|
+
.rv-factv{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
219
|
+
.rv-linked{padding:var(--s1) var(--s2);border:1px solid var(--line);border-radius:4px;background:var(--panel)}
|
|
220
|
+
.rv-linkedrow{display:flex;gap:var(--s2);align-items:center;font-size:12px}
|
|
221
|
+
.rv-linkedtitle{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}
|
|
222
|
+
.rv-outgoing,.rv-messages{display:flex;flex-direction:column;gap:var(--s1)}
|
|
223
|
+
.rv-outrow{display:flex;gap:var(--s1);align-items:flex-start}
|
|
224
|
+
.rv-outrow textarea{flex:1;min-height:44px}
|
|
225
|
+
.rv-outbadge{flex:none;max-width:170px;margin-top:var(--s0);font-size:11px;padding:0 var(--s2);line-height:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
|
|
226
|
+
color:var(--tone,var(--ink));border-color:color-mix(in srgb,var(--tone,var(--line)) 50%,var(--line))}
|
|
227
|
+
.rv-outbadge.rect{--tone:var(--warn)}
|
|
228
|
+
.rv-outbadge.rect.on{--tone:var(--blue)}
|
|
229
|
+
.rv-x{flex:none;padding:0 var(--s1);border:0}
|
|
230
|
+
.rv-label{font-size:12px;font-weight:600;margin-top:var(--s1)}
|
|
231
|
+
.rv-listenrow{display:flex;gap:var(--s2);align-items:center;font-size:11px}
|
|
232
|
+
.rv-verdicts{display:flex;flex-direction:column;gap:var(--s1)}
|
|
233
|
+
.rv-verdict{text-align:left;padding:var(--s1) var(--s3);font-size:13px;border-color:color-mix(in srgb,var(--tone) 60%,var(--line))}
|
|
234
|
+
.rv-verdict .rv-vglyph{color:var(--tone);font-weight:800}
|
|
235
|
+
.rv-verdict.chosen{background:var(--tone);color:var(--bg);border-color:var(--tone)}
|
|
236
|
+
.rv-verdict.chosen .rv-vglyph{color:var(--bg)}
|
|
237
|
+
.rv-verdict.off{opacity:.5}
|
|
238
|
+
.rv-msg{max-width:88%;align-self:flex-start;padding:var(--s1) var(--s2);border-radius:6px;border:1px solid var(--line);background:var(--panel2)}
|
|
239
|
+
.rv-msg.mine{align-self:flex-end;border-color:var(--hair);background:var(--wash)}
|
|
240
|
+
.rv-msgimg{display:block;max-width:100%;max-height:160px;margin-top:var(--s1);border-radius:4px}
|
|
241
|
+
.rv-replyrow,.rv-formfoot{display:flex;gap:var(--s2);justify-content:space-between}
|
|
242
|
+
.rv-replyrow{justify-content:flex-end}
|
|
243
|
+
|
|
244
|
+
/* ── the phone: the page covers the hub's panes, one pane at a time, the verdicts under the thumb ── */
|
|
245
|
+
.rv-phone,.tr-phone{position:fixed;inset:0;z-index:30;background:var(--bg)}
|
|
246
|
+
.rv-phone{display:flex;flex-direction:column}
|
|
247
|
+
.rv-phonetop{flex:none;display:flex;gap:var(--s2);align-items:center;padding:var(--s1) var(--s2);border-bottom:1px solid var(--line);background:var(--bg-top);font-size:13px}
|
|
248
|
+
.rv-phonetabs{margin:var(--s2);align-self:stretch;display:flex}
|
|
249
|
+
.rv-phonetabs button{flex:1;font-size:13px;padding:var(--s1) var(--s2)}
|
|
250
|
+
.rv-phonepane{flex:1;min-height:0;overflow-y:auto}
|
|
251
|
+
.rv-verdictbar{flex:none;display:flex;gap:var(--s1);padding:var(--s2);border-top:1px solid var(--line);background:var(--panel)}
|
|
252
|
+
.rv-verdictbar .rv-verdict{flex:1;text-align:center;font-size:14px;padding:var(--s2) var(--s1);color:var(--tone)}
|
|
253
|
+
.rv-verdictbar .rv-verdict.chosen{color:var(--bg)}
|
|
254
|
+
.rv-phone .rv-views{gap:var(--s3)}
|
|
255
|
+
/* a row on a phone: ▶, the label and the time on one line, the strip and the acts under them */
|
|
256
|
+
.rv-phone .rv-optrow{flex-wrap:wrap;row-gap:var(--s1)}
|
|
257
|
+
.rv-phone .rv-optlabel{flex:1;max-width:none}
|
|
258
|
+
.rv-phone .rv-strip{order:5;flex:1 1 100%;height:32px}
|
|
259
|
+
.rv-phone .rv-optthumb{order:4}
|
|
260
|
+
.rv-phone .rv-optacts{order:6;flex:1 1 100%;justify-content:space-between}
|
|
261
|
+
.rv-phone .rv-stars button{font-size:22px;padding:0 var(--s1)}
|
|
262
|
+
.rv-phone .rv-optplay{width:40px;height:34px}
|
|
263
|
+
.rv-phone .rv-optnote,.rv-phone .rv-opt .rv-word{margin-left:0;width:100%}
|
|
264
|
+
|
|
265
|
+
/* ── the trailer page ── */
|
|
266
|
+
.tr-cuts{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s3)}
|
|
267
|
+
.tr-trailername{font-weight:800}
|
|
268
|
+
.tr-cutrows{display:flex;flex-direction:column;gap:var(--s0)}
|
|
269
|
+
.tr-cutrow{display:flex;align-items:center;gap:var(--s1);width:100%;padding:var(--s0) var(--s2);border:0;border-radius:4px;text-align:left;font-size:13px}
|
|
270
|
+
.tr-cutrow:hover{background:var(--panel2)}
|
|
271
|
+
.tr-cutrow.on{background:var(--sel);box-shadow:inset 2px 0 0 var(--accent);font-weight:700}
|
|
272
|
+
.tr-cutrow.unrendered{opacity:.45}
|
|
273
|
+
.tr-cutname{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
274
|
+
.tr-edited{color:var(--warn)}
|
|
275
|
+
.tr-cuterr{color:var(--red);font-weight:800}
|
|
276
|
+
.tr-opencount{flex:none;min-width:16px;padding:0 var(--s1);border-radius:8px;background:var(--warn);color:var(--bg);font-size:10px;font-weight:700;text-align:center;line-height:16px}
|
|
277
|
+
.tr-cutage{flex:none;font-size:11px;color:var(--dim);font-variant-numeric:tabular-nums;white-space:nowrap}
|
|
278
|
+
.tr-keys{margin-top:var(--s3);padding:var(--s2);border:1px solid var(--line);border-radius:6px;background:var(--panel);display:flex;flex-direction:column;gap:var(--s0)}
|
|
279
|
+
.tr-keyshead{font-size:11px;font-weight:700;color:var(--dim)}
|
|
280
|
+
.tr-keyrow{display:flex;gap:var(--s2);align-items:baseline;font-size:11px}
|
|
281
|
+
.tr-keyrow kbd{min-width:44px;text-align:center}
|
|
282
|
+
.tr-player{display:flex;flex-direction:column;gap:var(--s2);padding:var(--s3)}
|
|
283
|
+
.tr-banner{display:flex;gap:var(--s2);align-items:center;justify-content:space-between;padding:var(--s2) var(--s3);border-radius:4px;border:1px solid var(--hair);background:var(--wash);font-size:12.5px}
|
|
284
|
+
.tr-banner.warn{border-color:color-mix(in srgb,var(--warn) 50%,var(--line));background:color-mix(in srgb,var(--warn) 10%,var(--panel))}
|
|
285
|
+
.tr-screen{background:var(--solid);border-radius:8px;padding:var(--s2);display:flex;justify-content:center}
|
|
286
|
+
.tr-frame{position:relative}
|
|
287
|
+
.tr-frame video{display:block;width:100%;height:100%;border-radius:4px;background:var(--solid)}
|
|
288
|
+
.tr-clickzone{position:absolute;inset:0;cursor:crosshair}
|
|
289
|
+
.tr-paused{position:absolute;left:var(--s2);top:var(--s2);padding:var(--s0) var(--s2);border-radius:4px;background:var(--scrim);color:var(--tag);font-size:12px;font-variant-numeric:tabular-nums;pointer-events:none}
|
|
290
|
+
.tr-pin{position:absolute;transform:translate(-50%,-100%);pointer-events:none}
|
|
291
|
+
.tr-pinhead{width:22px;height:22px;border-radius:50% 50% 50% 0;transform:rotate(-45deg);background:var(--tone);border:2px solid var(--tag);box-shadow:0 2px 8px var(--shadow);display:flex;align-items:center;justify-content:center}
|
|
292
|
+
.tr-pinhead.on{width:28px;height:28px}
|
|
293
|
+
.tr-pinhead span{transform:rotate(45deg);color:var(--tag);font-weight:800;font-size:11px}
|
|
294
|
+
.tr-pulse{position:absolute;left:calc(50% - 12px);bottom:-6px;width:24px;height:24px;border-radius:12px;border:2px solid var(--warn);animation:trpulse 1.1s ease-out infinite}
|
|
295
|
+
@keyframes trpulse{from{transform:scale(.6);opacity:1}to{transform:scale(1.8);opacity:0}}
|
|
296
|
+
.tr-transport{display:flex;flex-wrap:wrap;gap:var(--s1);align-items:center}
|
|
297
|
+
.tr-tbtn{width:32px;height:32px;padding:0;border-radius:16px;border-color:transparent;font-size:15px}
|
|
298
|
+
.tr-tbtn.big{width:44px;height:44px;border-radius:22px;background:var(--ink);color:var(--bg);font-size:17px}
|
|
299
|
+
.tr-time{margin-left:var(--s1);line-height:1.15;font-variant-numeric:tabular-nums}
|
|
300
|
+
.tr-timebig{font-size:18px;font-weight:800}
|
|
301
|
+
.tr-timebig span{font-size:12px;font-weight:500}
|
|
302
|
+
.tr-file{font-size:11px;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
303
|
+
.tr-notebtn{color:var(--bg);background:var(--warn);border-color:var(--warn);font-weight:700;padding:var(--s1) var(--s3)}
|
|
304
|
+
.tr-now{display:flex;flex-wrap:wrap;gap:var(--s2);align-items:center;min-height:30px;font-size:12.5px}
|
|
305
|
+
.tr-secbadge{padding:0 var(--s2);border-radius:3px;background:var(--hue);color:var(--bg);font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.04em;line-height:20px}
|
|
306
|
+
.tr-secbadge.small{text-transform:none;letter-spacing:0;line-height:16px;font-size:10.5px}
|
|
307
|
+
.tr-shotnow{font-size:16px}
|
|
308
|
+
.tr-capnow{font-style:italic;padding:0 var(--s2);border-radius:4px;background:color-mix(in srgb,var(--warn) 18%,transparent);white-space:pre-line}
|
|
309
|
+
.tr-timelinewrap{position:relative}
|
|
310
|
+
.tr-timeline{overflow-x:auto;overflow-y:hidden;border-radius:6px;background:var(--bg);border:1px solid var(--line);padding:var(--s1) 0 var(--s2);cursor:col-resize;user-select:none}
|
|
311
|
+
.tr-track{position:relative}
|
|
312
|
+
.tr-tick{position:absolute;border-left:1px solid var(--hi3)}
|
|
313
|
+
.tr-tick span{position:absolute;left:3px;top:1px;font-size:10px;color:var(--dim);font-variant-numeric:tabular-nums;white-space:nowrap}
|
|
314
|
+
.tr-section{position:absolute;border-radius:4px;background:color-mix(in srgb,var(--hue) 55%,var(--bg));color:var(--ink);font-size:11px;font-weight:700;padding-left:var(--s1);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;opacity:.8}
|
|
315
|
+
.tr-section.on{background:var(--hue);color:var(--bg);opacity:1;box-shadow:0 0 0 2px var(--hi1)}
|
|
316
|
+
.tr-shot{position:absolute;border-radius:3px;background:var(--panel2);border-top:3px solid color-mix(in srgb,var(--hue) 60%,var(--bg));color:var(--ink);font-size:11px;font-weight:600;padding:var(--s0) var(--s1) 0;overflow:hidden;white-space:nowrap;opacity:.85}
|
|
317
|
+
.tr-shot.odd{background:var(--panel)}
|
|
318
|
+
.tr-shot.on{background:color-mix(in srgb,var(--hue) 70%,var(--bg));border-top-color:var(--hue);color:var(--bg);font-weight:800;box-shadow:0 0 0 2px var(--ink);opacity:1;z-index:1}
|
|
319
|
+
.tr-shottime{font-size:9px;opacity:.6;font-variant-numeric:tabular-nums}
|
|
320
|
+
.tr-caption{position:absolute;border-radius:3px;background:color-mix(in srgb,var(--warn) 18%,transparent);color:var(--warn);border:1px solid color-mix(in srgb,var(--warn) 35%,transparent);font-size:10px;font-style:italic;padding:0 var(--s1);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
|
|
321
|
+
.tr-caption.on{background:var(--warn);color:var(--bg)}
|
|
322
|
+
.tr-noteline{position:absolute;border-left:1px dashed var(--tone);opacity:.5;pointer-events:none}
|
|
323
|
+
.tr-noteline.on{border-left-style:solid;opacity:.9}
|
|
324
|
+
.tr-notepin{position:absolute;top:0;width:16px;height:16px;border-radius:50% 50% 50% 0;transform:rotate(-45deg);background:var(--tone);border:1px solid var(--shadow);cursor:pointer;z-index:3}
|
|
325
|
+
.tr-notepin.on{border:2px solid var(--tag)}
|
|
326
|
+
.tr-draftmark{position:absolute;top:0;width:2px;background:var(--warn);z-index:3;pointer-events:none}
|
|
327
|
+
.tr-playhead{position:absolute;top:0;width:2px;background:var(--red);z-index:4;pointer-events:none;box-shadow:0 0 6px var(--red)}
|
|
328
|
+
.tr-playknob{position:absolute;left:-5px;top:-2px;width:12px;height:8px;border-radius:3px;background:var(--red)}
|
|
329
|
+
.tr-hover{position:fixed;width:208px;padding:var(--s2);border-radius:6px;background:var(--panel2);border:1px solid var(--line);box-shadow:0 6px 24px var(--shadow);pointer-events:none;z-index:50;font-size:12px}
|
|
330
|
+
.tr-hoverrow{display:flex;justify-content:space-between;margin-top:var(--s1)}
|
|
331
|
+
.tr-thumb{border-radius:4px;background-color:var(--panel2);background-repeat:no-repeat;flex:none}
|
|
332
|
+
.tr-shotcards{display:flex;gap:var(--s2);overflow-x:auto;padding:var(--s1) var(--s0) var(--s2)}
|
|
333
|
+
.tr-shotcard{position:relative;flex:none;width:148px;padding:var(--s1);border-radius:6px;text-align:left;border:1px solid var(--line);background:var(--panel)}
|
|
334
|
+
.tr-shotcard.on{border:2px solid var(--hue);background:color-mix(in srgb,var(--hue) 12%,var(--panel))}
|
|
335
|
+
.tr-shotname{font-size:12px;font-weight:800;margin-top:var(--s1);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
336
|
+
.tr-shotnotes{position:absolute;top:var(--s2);right:var(--s2);min-width:18px;height:18px;border-radius:9px;background:var(--warn);color:var(--bg);font-size:11px;font-weight:800;text-align:center;line-height:18px;padding:0 var(--s1)}
|
|
337
|
+
.tr-montage{display:flex;flex-direction:column;gap:var(--s1);align-items:flex-start}
|
|
338
|
+
.tr-montagebody{width:100%;font-size:12.5px;padding:var(--s2) var(--s3);border:1px solid var(--line);border-radius:4px;background:var(--panel);overflow-x:auto}
|
|
339
|
+
.tr-notescol{height:100%;display:flex;flex-direction:column;min-height:0}
|
|
340
|
+
.tr-noteshead{display:flex;gap:var(--s2);align-items:center;padding:var(--s2) var(--s3);border-bottom:1px solid var(--line)}
|
|
341
|
+
.tr-openbadge{font-size:10px;font-weight:700;text-transform:uppercase;padding:0 var(--s1);border-radius:3px;line-height:16px;color:var(--warn);border:1px solid color-mix(in srgb,var(--warn) 50%,var(--line))}
|
|
342
|
+
.tr-openbadge.on{background:var(--warn);color:var(--bg)}
|
|
343
|
+
.tr-notesscroll{flex:1;min-height:0;overflow-y:auto;padding:var(--s2);display:flex;flex-direction:column;gap:var(--s2)}
|
|
344
|
+
.tr-elsewhere{font-size:11px;font-weight:700;color:var(--dim);margin-top:var(--s3)}
|
|
345
|
+
.tr-draft{padding:var(--s2) var(--s3);border-radius:6px;border:1px solid var(--warn);box-shadow:0 0 0 3px color-mix(in srgb,var(--warn) 18%,transparent);display:flex;flex-direction:column;gap:var(--s1)}
|
|
346
|
+
.tr-drafthead{display:flex;justify-content:space-between;gap:var(--s2);align-items:center;font-size:12.5px}
|
|
347
|
+
.tr-pinned{color:var(--warn);font-size:11px;font-weight:700}
|
|
348
|
+
.tr-draftbtns{display:flex;justify-content:flex-end;gap:var(--s1)}
|
|
349
|
+
.tr-note{border-radius:6px;border:1px solid var(--line);border-left:4px solid var(--tone);padding:var(--s2);background:var(--panel);cursor:pointer;display:flex;flex-direction:column;gap:var(--s1)}
|
|
350
|
+
.tr-note.ns-done:not(.on),.tr-note.ns-wontfix:not(.on){opacity:.72}
|
|
351
|
+
.tr-note.on{border:2px solid var(--tone);border-left-width:5px;background:var(--panel2)}
|
|
352
|
+
.tr-notetop{display:flex;gap:var(--s2)}
|
|
353
|
+
.tr-notebody{flex:1;min-width:0}
|
|
354
|
+
.tr-notemeta{display:flex;flex-wrap:wrap;gap:var(--s1);align-items:center;font-size:12px}
|
|
355
|
+
.tr-statebadge{font-size:10px;font-weight:700;padding:0 var(--s1);border-radius:3px;background:var(--tone);color:var(--bg);line-height:16px}
|
|
356
|
+
.tr-moved{font-size:11px;color:var(--warn)}
|
|
357
|
+
.tr-notetext{font-size:13px;margin-top:var(--s0);white-space:pre-wrap;overflow-wrap:anywhere}
|
|
358
|
+
.tr-notetext.struck{text-decoration:line-through}
|
|
359
|
+
.tr-edit{display:flex;flex-direction:column;gap:var(--s1)}
|
|
360
|
+
.tr-reply{padding:var(--s1) var(--s2);border-radius:4px;border-left:3px solid var(--tone);background:color-mix(in srgb,var(--tone) 10%,var(--panel));font-size:12px}
|
|
361
|
+
.tr-noteacts{display:flex;flex-wrap:wrap;gap:var(--s1);align-items:center}
|
|
362
|
+
.tr-noteacts button{font-size:12px;padding:0 var(--s2);line-height:22px}
|
|
363
|
+
.tr-done{color:var(--ok);border-color:color-mix(in srgb,var(--ok) 50%,var(--line))}
|
|
364
|
+
.tr-delete{color:var(--red);border-color:transparent}
|
|
365
|
+
.tr-delete.sure{background:var(--red);color:var(--bg)}
|
|
366
|
+
.tr-still{position:relative;flex:none}
|
|
367
|
+
.tr-still img{display:block;width:100%;height:100%;object-fit:cover;border-radius:4px;background:var(--panel2)}
|
|
368
|
+
.tr-stillpin{position:absolute;width:12px;height:12px;transform:translate(-50%,-50%);border-radius:6px;background:var(--tone);border:2px solid var(--tag);box-shadow:0 1px 4px var(--shadow)}
|
|
369
|
+
.tr-phone{overflow-y:auto;display:flex;flex-direction:column}
|
|
370
|
+
.tr-phone > *{flex:none}
|
|
371
|
+
.tr-phone .tr-notescol{height:auto}
|
|
372
|
+
/* the dispatcher's board and a kind's data view (review-board.tsx, kind-view.tsx) */
|
|
373
|
+
.rv-board{padding:var(--s2) var(--s3)}
|
|
374
|
+
.rv-boardrow{padding:var(--s2);border:1px solid var(--line);border-radius:4px;margin-bottom:var(--s1);cursor:pointer;font-size:12.5px}
|
|
375
|
+
.rv-boardrow:hover,.rv-boardrow.on{background:var(--panel)}
|
|
376
|
+
.rv-boardrow .rv-linkedtitle{display:block}
|
|
377
|
+
.rv-kindview{display:flex;flex-direction:column;gap:var(--s2);margin:var(--s2) 0}
|
|
378
|
+
.rv-kindtext{font:12px/1.5 ui-monospace,Menlo,monospace;background:var(--panel);border:1px solid var(--line);border-radius:3px;padding:var(--s2) var(--s3);margin:0;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
379
|
+
.rv-part{border:1px solid var(--line);border-radius:4px;padding:var(--s2) var(--s3);margin-top:var(--s2);background:var(--panel)}
|
|
380
|
+
.rv-parthead{display:flex;align-items:center;gap:var(--s2);margin-bottom:var(--s2)}
|
|
381
|
+
.rv-particon{width:20px;height:20px;border-radius:5px;flex:none}
|
|
382
|
+
.rv-partbadge{margin-left:auto;font-size:11px;font-weight:700;border:1px solid;border-radius:3px;padding:0 var(--s1)}
|
|
383
|
+
.rv-partbody{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:var(--s3);align-items:start}
|
|
384
|
+
.rv-partbody img,.rv-partbody video{width:100%;max-height:320px;object-fit:contain;border-radius:6px;display:block}
|
|
385
|
+
.rv-parttext{font-size:13px;line-height:1.45;white-space:pre-wrap;overflow-wrap:anywhere}
|
|
386
|
+
.rv-anim select{font-size:12px}
|
|
387
|
+
/* a sound view (review-views.tsx SoundBody): its waveform over the player, a row a side on a pair */
|
|
388
|
+
.rv-sound{display:flex;flex-direction:column;gap:var(--s2)}
|
|
389
|
+
.rv-soundrow{display:flex;flex-direction:column;gap:var(--s1);background:var(--panel);border:1px solid var(--line);border-radius:4px;padding:var(--s2)}
|