/* ========================================================================== Annotations tab — skin scoped under .annotations-skin. Built on the app's minimal tokens (globals.css): surfaces, hairlines, fills, type, radii and motion all come from there, so the tab reads as part of the product in both themes. The only private values are the semantic role colours (task aug cyan, subtask yellow, plan blue, memory purple, interjection red, vqa green, speech orange), tuned to sit on white and on near-black. Private names carry the --anno- prefix so they never shadow an app token for components rendered inside the tab (playback bar, video tiles, menus). ========================================================================== */ /* Marks drawn on the video canvas (video-overlay-canvas.tsx reads these with getComputedStyle). Video always sits on --media, so one vivid set serves both themes: saved VQA marks in the vqa green, the in-progress draw in the system blue, labels on a dark frosted chip. */ :root { --anno-overlay-mark: #30d158; --anno-overlay-draft: #0a84ff; --anno-overlay-chip: rgba(12, 12, 14, 0.72); --anno-overlay-chip-fg: #ffffff; } .annotations-skin { /* Role colours, light: a solid (dots, ticks, bars) and a text shade that holds 4.5:1 on white and on its own tint. */ --anno-task-aug: #00a8cc; --anno-task-aug-fg: #00718a; --anno-subtask: #f2b600; --anno-subtask-fg: #8a5d00; --anno-plan: #5856d6; --anno-plan-fg: #4c4ac4; --anno-memory: #af52de; --anno-memory-fg: #8e3bbd; --anno-interjection: #ff3b30; --anno-interjection-fg: #d70015; --anno-vqa: #34c759; --anno-vqa-fg: #1f7f37; --anno-speech: #ff7a00; --anno-speech-fg: #b24a00; /* Tint strengths for pills and timeline segments. */ --anno-tint: 12%; --anno-seg-tint: 16%; --anno-seg-tint-hover: 24%; } :root.dark .annotations-skin { --anno-task-aug: #5ac8f5; --anno-task-aug-fg: #7dd6fa; --anno-subtask: #ffd60a; --anno-subtask-fg: #ffd60a; --anno-plan: #7d7aff; --anno-plan-fg: #9d9bff; --anno-memory: #bf5af2; --anno-memory-fg: #d08cf7; --anno-interjection: #ff453a; --anno-interjection-fg: #ff6961; --anno-vqa: #30d158; --anno-vqa-fg: #4cdb72; --anno-speech: #ff9f0a; --anno-speech-fg: #ffb340; --anno-tint: 18%; --anno-seg-tint: 24%; --anno-seg-tint-hover: 32%; } /* Role classes only set variables, so they are safe on any element. Pills, segments and ticks read --role / --role-fg. Speech comes after interjection: a speech tick on the shared dialogue lane carries both. */ .annotations-skin .task_aug { --role: var(--anno-task-aug); --role-fg: var(--anno-task-aug-fg); } .annotations-skin .subtask { --role: var(--anno-subtask); --role-fg: var(--anno-subtask-fg); } .annotations-skin .plan { --role: var(--anno-plan); --role-fg: var(--anno-plan-fg); } .annotations-skin .memory { --role: var(--anno-memory); --role-fg: var(--anno-memory-fg); } .annotations-skin .interjection { --role: var(--anno-interjection); --role-fg: var(--anno-interjection-fg); } .annotations-skin .vqa, .annotations-skin .kind-pill { --role: var(--anno-vqa); --role-fg: var(--anno-vqa-fg); } .annotations-skin .speech { --role: var(--anno-speech); --role-fg: var(--anno-speech-fg); } /* ----- Style pills and dots ----- */ .annotations-skin .style-pill, .annotations-skin .kind-pill { display: inline-flex; flex: none; align-items: center; height: 20px; padding: 0 8px; border: 0; border-radius: 999px; background: color-mix( in srgb, var(--role, var(--fg-tertiary)) var(--anno-tint), transparent ); color: var(--role-fg, var(--fg-secondary)); font-size: 11px; font-weight: 500; line-height: 1; letter-spacing: 0; white-space: nowrap; } .annotations-skin .kind-pill { text-transform: capitalize; } .annotations-skin .style-dot { display: inline-block; flex: none; width: 8px; height: 8px; border-radius: 999px; background: var(--fg-tertiary); } .annotations-skin .dot-subtask { background: var(--anno-subtask); } .annotations-skin .dot-task-aug, .annotations-skin .dot-task_aug { background: var(--anno-task-aug); } .annotations-skin .dot-plan { background: var(--anno-plan); } .annotations-skin .dot-memory { background: var(--anno-memory); } .annotations-skin .dot-interjection { background: var(--anno-interjection); } .annotations-skin .dot-vqa { background: var(--anno-vqa); } .annotations-skin .dot-speech { background: var(--anno-speech); } /* ----- Shared type ----- */ .annotations-skin .section-kicker { display: inline-flex; color: var(--fg); font-size: 15px; font-weight: 600; line-height: 20px; letter-spacing: -0.011em; } .annotations-skin .field-label { display: block; margin-bottom: 6px; color: var(--fg-secondary); font-size: 13px; font-weight: 500; line-height: 18px; } .annotations-skin .ts-pill { display: inline-flex; flex: none; align-items: center; height: 24px; padding: 0 10px; border-radius: 999px; background: var(--fill); color: var(--fg-secondary); font-size: 12px; font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; } /* ----- Cards: one recipe for the whole tab (hairline, 16px, flat) ----- */ .annotations-skin .tl, .annotations-skin .annotation-composer, .annotations-skin .rail, .annotations-skin .editor { background: var(--surface); border: 1px solid var(--separator); border-radius: var(--radius-lg); box-shadow: var(--shadow-card); } /* ----- Workbench: header row, composer, list + inspector ----- */ .annotations-skin .annotation-workbench { display: flex; flex-direction: column; gap: 16px; } /* The header is a plain row, not a box: title, state, actions. */ .annotations-skin .annotation-actionbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 8px 2px 0; } .annotations-skin .annotation-actionbar h3 { display: flex; align-items: center; gap: 10px; margin: 0; color: var(--fg); font-size: 15px; font-weight: 600; line-height: 20px; letter-spacing: -0.011em; } .annotations-skin .annotation-actionbar p, .annotations-skin .annotation-composer p, .annotations-skin .list-head p { margin: 2px 0 0; color: var(--fg-secondary); font-size: 13px; line-height: 18px; } .annotations-skin .actionbar-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; } .annotations-skin .dirty-pill { display: inline-flex; align-items: center; gap: 6px; height: 20px; padding: 0 8px; border-radius: 999px; background: var(--warning-soft); color: var(--warning); font-size: 11px; font-weight: 500; letter-spacing: 0; } .annotations-skin .dirty-pill::before { content: ""; width: 6px; height: 6px; border-radius: 999px; background: currentColor; } .annotations-skin .backend-offline, .annotations-skin .save-status { color: var(--fg-secondary); font-size: 13px; line-height: 18px; } .annotations-skin .save-status { padding: 0 2px; overflow-wrap: anywhere; } /* ----- Composer: add a text annotation at the playhead ----- */ .annotations-skin .annotation-composer { display: grid; grid-template-columns: minmax(180px, 260px) 1fr; align-items: center; gap: 16px 24px; padding: 16px 20px; } .annotations-skin .quick-add { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; } .annotations-skin .annotation-composer .quick-add { justify-content: flex-end; } .annotations-skin .quick-add .grow { flex: 1; min-width: 200px; } .annotations-skin .quick-add .ts-pill { height: 32px; padding: 0 12px; font-size: 13px; } /* ----- Grounded VQA note (markup in episode-viewer.tsx) ----- */ .annotations-skin .grounding-intro { display: flex; flex-direction: column; gap: 6px; padding: 14px 18px; border-radius: var(--radius-lg); background: var(--surface-muted); } .annotations-skin .grounding-intro .section-kicker { font-size: 13px; line-height: 18px; letter-spacing: -0.006em; } .annotations-skin .grounding-intro ul { display: flex; flex-direction: column; gap: 4px; margin: 0; padding-left: 18px; color: var(--fg-secondary); font-size: 13px; line-height: 1.5; } .annotations-skin .grounding-intro li::marker { color: var(--fg-tertiary); } /* Same look as ui.tsx . */ .annotations-skin .grounding-intro kbd { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 6px; background: var(--fill-hover); color: var(--fg-secondary); font-family: inherit; font-size: 11px; font-weight: 500; line-height: 1; vertical-align: 1px; } /* ----- Timeline ----- */ .annotations-skin .tl { padding: 16px 20px 18px; } .annotations-skin .tl-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; color: var(--fg); font-size: 15px; font-weight: 600; line-height: 20px; letter-spacing: -0.011em; } .annotations-skin .tl-head .ts-display { color: var(--fg-secondary); font-size: 13px; font-weight: 500; font-variant-numeric: tabular-nums; letter-spacing: 0; } /* Geometry contract with annotations-timeline.tsx: label column 84px (LABEL_WIDTH) + 10px gap = the 94px ruler offset, so the ruler, tracks and playhead share one x-axis. */ .annotations-skin .tl-ruler { position: relative; height: 18px; margin-left: 94px; margin-bottom: 8px; border-bottom: 1px solid var(--separator); cursor: pointer; } .annotations-skin .tl-ruler .tick-mark { position: absolute; top: 0; bottom: 0; padding-left: 4px; border-left: 1px solid var(--separator); color: var(--fg-tertiary); font-size: 11px; line-height: 14px; font-variant-numeric: tabular-nums; white-space: nowrap; } /* Persistent / Events sections (timeline and list). */ .annotations-skin .tl-section { margin-bottom: 10px; } .annotations-skin .tl-section-head, .annotations-skin .rail-column-head { display: flex; align-items: baseline; gap: 8px; margin: 0; padding: 4px 0 6px; } .annotations-skin .tl-section-title, .annotations-skin .rail-column-title { color: var(--fg); font-size: 13px; font-weight: 600; line-height: 18px; } .annotations-skin .tl-section-sub, .annotations-skin .rail-column-sub { min-width: 0; overflow: hidden; color: var(--fg-secondary); font-size: 11px; line-height: 16px; text-overflow: ellipsis; white-space: nowrap; } .annotations-skin .tl-row { display: flex; align-items: center; gap: 10px; height: 26px; margin-bottom: 4px; } .annotations-skin .tl-row .label { display: flex; flex: none; align-items: center; gap: 8px; width: 84px; overflow: hidden; color: var(--fg-secondary); font-size: 12px; font-weight: 500; line-height: 16px; white-space: nowrap; } .annotations-skin .tl-row .track { position: relative; flex: 1; height: 22px; border-radius: 6px; background: var(--fill); cursor: pointer; } /* Drags on the subtask track (create, resize) own the touch: without this the browser turns a finger drag into a page scroll and cancels the pointer mid-drag. A scroll that starts on this 22px strip is the trade-off. */ .annotations-skin .tl-row .track.editable { cursor: crosshair; touch-action: none; } .annotations-skin .tl-row .track.creating { outline: 1px dashed var(--accent); outline-offset: 0; } /* Spans: a soft role tint with a role-coloured start bar; the label stays in the text colour so it reads on every tint. */ .annotations-skin .tl-seg { position: absolute; top: 2px; bottom: 2px; display: flex; align-items: center; gap: 6px; padding: 0 8px; overflow: hidden; border-radius: 5px; background: color-mix( in srgb, var(--role, var(--fg-tertiary)) var(--anno-seg-tint), transparent ); box-shadow: inset 2px 0 0 var(--role, var(--fg-tertiary)); color: var(--fg); font-size: 11px; font-weight: 500; line-height: 18px; white-space: nowrap; cursor: pointer; user-select: none; transition: background-color var(--dur-fast) var(--ease-out); } .annotations-skin .tl-seg:hover { background: color-mix( in srgb, var(--role, var(--fg-tertiary)) var(--anno-seg-tint-hover), transparent ); } /* The span's own text colour, softened: fg-secondary drops under 3:1 on the brighter dark-mode tints (subtask yellow). */ .annotations-skin .tl-seg-index { flex: none; color: color-mix(in srgb, var(--fg) 75%, transparent); font-size: 11px; font-variant-numeric: tabular-nums; } .annotations-skin .tl-seg-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .annotations-skin .tl-seg.dragging { opacity: 0.9; outline: 1.5px solid var(--accent); outline-offset: 0; } .annotations-skin .tl-seg.task_aug .aug-count { display: inline-flex; flex: none; align-items: center; height: 16px; margin-left: auto; padding: 0 6px; border-radius: 999px; background: color-mix(in srgb, var(--role) 22%, transparent); /* Main text colour: the role text shade falls under 4:1 on this doubled tint in both themes. */ color: var(--fg); font-size: 11px; font-weight: 600; line-height: 16px; font-variant-numeric: tabular-nums; } /* Resize edges: invisible 6px hit areas with a grip that fades in. */ .annotations-skin .tl-seg .resize { position: absolute; top: 0; bottom: 0; z-index: 2; width: 6px; cursor: ew-resize; touch-action: none; } .annotations-skin .tl-seg .resize.l { left: 0; } .annotations-skin .tl-seg .resize.r { right: 0; } .annotations-skin .tl-seg .resize::after { content: ""; position: absolute; top: 4px; bottom: 4px; left: 2px; width: 2px; border-radius: 1px; background: var(--fg); opacity: 0; transition: opacity var(--dur-fast) var(--ease-out); } .annotations-skin .tl-seg:hover .resize::after { opacity: 0.22; } .annotations-skin .tl-seg .resize:hover::after, .annotations-skin .tl-seg.dragging .resize::after { opacity: 0.6; } /* No hover on touch screens: keep the grips visible there. */ @media (hover: none) { .annotations-skin .tl-seg .resize::after { opacity: 0.22; } } .annotations-skin .tl-create-preview { position: absolute; top: 2px; bottom: 2px; z-index: 4; border: 1px dashed var(--accent); border-radius: 5px; background: var(--accent-soft); pointer-events: none; } /* Point-in-time markers. */ .annotations-skin .tl-tick { position: absolute; top: 3px; bottom: 3px; width: 4px; border-radius: 2px; background: var(--role, var(--fg-secondary)); transform: translateX(-2px); cursor: pointer; transition: box-shadow var(--dur-fast) var(--ease-out); } .annotations-skin .tl-tick:hover { box-shadow: 0 0 0 3px color-mix(in srgb, var(--role, var(--fg-secondary)) 28%, transparent); } /* Playhead: a neutral 2px line with one round head (the drag handle). */ .annotations-skin .tl-playhead { position: absolute; top: 0; bottom: 0; z-index: 5; width: 2px; margin-left: -1px; border-radius: 1px; background: var(--playhead); pointer-events: none; } .annotations-skin .tl-playhead-handle { position: absolute; top: -6px; z-index: 6; width: 14px; height: 14px; border: 2px solid var(--surface); border-radius: 999px; background: var(--playhead); transform: translate(-7px, 0); cursor: ew-resize; pointer-events: auto; /* A finger drag scrubs instead of scrolling the page. */ touch-action: none; transition: transform var(--dur-fast) var(--ease-out); } /* Invisible hit pad: the 14px head becomes a 30 x 24px target (insets are measured from inside the 2px border). It stops at the ruler's bottom edge, so clicks on the ruler still seek. The drag keeps the grab offset, so grabbing the pad's edge doesn't make the playhead jump. */ .annotations-skin .tl-playhead-handle::before { content: ""; position: absolute; inset: -4px -10px -10px; border-radius: 999px; background: transparent; } .annotations-skin .tl-playhead-handle:hover, .annotations-skin .tl-playhead-handle:active { transform: translate(-7px, 0) scale(1.15); } /* Hover tooltip: small frosted card. */ .annotations-skin .tl-tooltip { position: fixed; z-index: 1000; max-width: 320px; padding: 8px 12px; border-radius: var(--radius); background: var(--surface-raised); -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px); box-shadow: var(--shadow-float); color: var(--fg); font-size: 13px; line-height: 18px; white-space: pre-line; pointer-events: none; animation: fadeIn var(--dur-fast) var(--ease-out) both; } .annotations-skin .tl-tooltip .meta { margin-bottom: 2px; color: var(--fg-secondary); font-size: 11px; line-height: 16px; font-variant-numeric: tabular-nums; } /* ----- Popovers: label a new box / point / subtask span ----- */ /* Motion comes from the shared .t-pop (globals.css): grows from the anchor set in each popup's layout effect, shrinks back on close as an inert copy. */ .annotations-skin .quick-popup { position: absolute; z-index: 30; display: flex; flex-direction: column; gap: 8px; min-width: 240px; padding: 10px; border-radius: var(--radius-xl); background: var(--surface-raised); -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px); box-shadow: var(--shadow-float); color: var(--fg); pointer-events: auto; } /* A dismissed popup still fading out never takes the pointer: the next draw or drag goes straight through to the video / track underneath. */ .annotations-skin .quick-popup[data-state="closing"] { pointer-events: none; } .annotations-skin .quick-popup-head { display: flex; align-items: center; gap: 8px; min-height: 28px; padding-left: 2px; color: var(--fg-secondary); font-size: 12px; } .annotations-skin .quick-popup-time { margin-left: auto; padding-right: 4px; font-variant-numeric: tabular-nums; } .annotations-skin .quick-popup-actions { display: flex; justify-content: flex-end; gap: 6px; } /* On glass, the muted input fill matches the popup in dark mode; use a translucent fill instead (states restated: this rule is unlayered). */ .annotations-skin .quick-popup .field { background: var(--fill-hover); } .annotations-skin .quick-popup .field:hover { background: var(--fill-press); } .annotations-skin .quick-popup .field:focus { background: var(--surface); } /* ----- Workspace: annotation list + inspector ----- */ .annotations-skin .workspace { display: grid; grid-template-columns: 280px 1fr; align-items: start; gap: 16px; } .annotations-skin .workspace.inspector-workspace { grid-template-columns: minmax(300px, 34%) minmax(0, 1fr); } .annotations-skin .rail { max-height: 60vh; padding: 8px; overflow-y: auto; } .annotations-skin .rail.annotation-list { max-height: min(60vh, 560px); padding: 0; overscroll-behavior: contain; } .annotations-skin .list-head { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 16px 12px; border-bottom: 1px solid var(--separator); background: color-mix(in srgb, var(--surface) 86%, transparent); -webkit-backdrop-filter: saturate(180%) blur(20px); backdrop-filter: saturate(180%) blur(20px); } .annotations-skin .rail-empty { padding: 32px 16px; color: var(--fg-secondary); font-size: 13px; line-height: 20px; text-align: center; } .annotations-skin .rail-column { padding: 8px 8px 4px; } .annotations-skin .rail-column + .rail-column { border-top: 1px solid var(--separator); } .annotations-skin .rail-column-head { padding: 6px 8px 4px; } .annotations-skin .rail-group, .annotations-skin .rail.annotation-list .rail-group { margin: 0 0 6px; } .annotations-skin .rail-group-head { display: flex; align-items: center; justify-content: space-between; padding: 6px 8px 4px; color: var(--fg-secondary); font-size: 12px; font-weight: 500; line-height: 16px; } .annotations-skin .rail-group-head .count { color: var(--fg-tertiary); font-size: 11px; font-variant-numeric: tabular-nums; } /* Rows: quiet hover fill, monochrome selection, a hairline ring for the row under the playhead. */ .annotations-skin .rail-row { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border: 1px solid transparent; border-radius: var(--radius-sm); color: var(--fg); font-size: 13px; line-height: 18px; cursor: pointer; transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out); } .annotations-skin .rail-row:hover { background: var(--fill); } .annotations-skin .rail-row:active { background: var(--fill-press); } .annotations-skin .rail-row.selected, .annotations-skin .rail.annotation-list .rail-row.selected { background: var(--fill-hover); border-color: transparent; box-shadow: none; font-weight: 500; } .annotations-skin .rail-row.active-now, .annotations-skin .rail.annotation-list .rail-row.active-now:not(.selected) { border-color: var(--separator-strong); outline: none; } .annotations-skin .rail-row .ts { flex: none; width: 56px; color: var(--fg-secondary); font-size: 12px; font-weight: 400; line-height: 18px; font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; } .annotations-skin .rail-row.active-now .ts { color: var(--fg); } .annotations-skin .rail-row .body { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .annotations-skin .rail.annotation-list .rail-row { align-items: flex-start; padding: 7px 8px; } .annotations-skin .rail.annotation-list .rail-row .body { overflow: visible; overflow-wrap: anywhere; text-overflow: clip; white-space: normal; } /* ----- Inspector ----- */ .annotations-skin .editor { padding: 20px; } .annotations-skin .inspector { position: sticky; top: 8px; } .annotations-skin .editor-empty { padding: 40px 16px; color: var(--fg-secondary); font-size: 13px; line-height: 18px; text-align: center; } .annotations-skin .inspector .editor-empty { display: grid; place-content: center; justify-items: center; gap: 6px; min-height: 220px; } .annotations-skin .inspector .editor-empty p { max-width: 360px; margin: 0; } .annotations-skin .inspector-body { display: flex; flex-direction: column; gap: 16px; } .annotations-skin .editor-head { display: flex; align-items: center; gap: 8px; padding-bottom: 14px; border-bottom: 1px solid var(--separator); } .annotations-skin .inspector-head { align-items: flex-start; } .annotations-skin .editor-head .right { display: flex; gap: 4px; margin-left: auto; } .annotations-skin .inspector-title { display: flex; align-items: flex-start; gap: 10px; min-width: 0; } .annotations-skin .inspector-title strong { display: block; color: var(--fg); font-size: 15px; font-weight: 600; line-height: 20px; letter-spacing: -0.011em; font-variant-numeric: tabular-nums; } .annotations-skin .inspector-title span:not(.style-pill) { display: block; color: var(--fg-secondary); font-size: 13px; line-height: 18px; } .annotations-skin .editor-field > input, .annotations-skin .editor-field > select, .annotations-skin .editor-field > textarea { width: 100%; } .annotations-skin .editor-field > textarea { height: auto; min-height: 74px; padding-top: 8px; padding-bottom: 8px; line-height: 1.45; resize: vertical; } .annotations-skin .editor .ts-row { display: flex; align-items: center; gap: 8px; } .annotations-skin .editor .ts-row input { width: 120px; font-variant-numeric: tabular-nums; } /* ----- Narrow layouts ----- */ @media (max-width: 900px) { .annotations-skin .annotation-actionbar { flex-direction: column; align-items: flex-start; } .annotations-skin .actionbar-actions { justify-content: flex-start; } .annotations-skin .annotation-composer, .annotations-skin .workspace, .annotations-skin .workspace.inspector-workspace { grid-template-columns: 1fr; } .annotations-skin .annotation-composer .quick-add { justify-content: flex-start; } .annotations-skin .inspector { position: static; } }