mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
a899ea657f
* fix(review): stop the call-flow Lens closing mid-scroll and opening on drive-by hovers The Lens popup scrolls internally but never contained overscroll, so momentum that hit its edge chained to the page; the page scroll moved the anchor, the popup tracked it out from under a stationary pointer, and the resulting mouseleave closed the Lens mid-scroll (worst under Safari rubber-banding). Scrolling the diff also dragged file headers under the cursor, and the zero-delay hover open popped the Lens for every badge that passed. - overscroll-behavior: contain on .call-flow-popover - 100ms hover-intent delay before opening; a pointer that leaves first never opens it - close grace 140ms -> 250ms - while a scroll is in flight, pending hover-closes are held; once it settles the Lens closes only if the pointer really ended up outside Reported by @acewhocares on X (Safari). * ci(guides-show): publish the built viewer manifest as an artifact The viewer build is deterministic per platform but not across platforms, and the committed pin must match the Linux CI build. When the manifest check fails on a PR, a maintainer on macOS previously had no way to obtain the authoritative hashes. The uploaded manifest.json closes that: download, drop into apps/guides-show/dist/viewer/, run sync:manifest, commit. * fix(guides): regenerate viewer pin for the Lens changes; correct the manifest-artifact comment The cross-platform nondeterminism claim in the previous commit was wrong. A clean install builds identical viewer hashes on macOS and Linux; the divergence observed here came from a drifted local bun store carrying stale duplicate package versions (rm -rf node_modules + frozen install reproduces CI exactly, verified against the deploy run's published names). The artifact upload stays: it is the authoritative recovery path when a local environment is the thing that is wrong. Pin regenerated from a verified-clean build for the Lens bundle changes.
2852 lines
74 KiB
CSS
2852 lines
74 KiB
CSS
@import "@fontsource-variable/inter";
|
||
@import "@fontsource-variable/geist-mono";
|
||
@import "tailwindcss";
|
||
@import "dockview-react/dist/styles/dockview.css";
|
||
|
||
@plugin "tailwindcss-animate";
|
||
|
||
/* Tell Tailwind where to scan for classes */
|
||
@source "../ui/components/**/*.tsx";
|
||
@source "../ui/hooks/**/*.ts";
|
||
@source "./*.tsx";
|
||
@source "./components/**/*.tsx";
|
||
@source "../guide-viewer/**/*.tsx";
|
||
@source "./dock/**/*.tsx";
|
||
@source "./utils/**/*.tsx";
|
||
|
||
@import "../ui/theme.css";
|
||
|
||
/* =====================================================
|
||
Code Review Specific Styles
|
||
===================================================== */
|
||
|
||
/* Shared panel header height — keeps file header, sidebar headers, and
|
||
search bar vertically aligned across all three columns. */
|
||
:root {
|
||
--panel-header-h: 33px;
|
||
|
||
/* Code-review-only readable-text bump. `text-xs` is the app's small/body
|
||
tier; Tailwind's default leaves it at 12px, which reads cramped here.
|
||
This stylesheet ships only in the review bundle, so overriding the token
|
||
is scoped to code review — the plan/annotate apps are untouched. Only the
|
||
`text-xs` tier moves; the 10/11px micro-labels (counts, letters, badges,
|
||
eyebrows) are arbitrary escapes and stay as-is. Rollback = delete these
|
||
two lines. */
|
||
--text-xs: 0.8125rem; /* 13px */
|
||
--text-xs--line-height: calc(1 / 0.75); /* reference xs ratio (≈1.33), unitless — holds at 13px */
|
||
}
|
||
|
||
/* =====================================================
|
||
Dockview Theme Bridge
|
||
Maps dockview CSS variables to Plannotator theme tokens
|
||
so tabs, separators, and drag overlays inherit our theme.
|
||
===================================================== */
|
||
|
||
.dockview-theme-dark,
|
||
.dockview-theme-light,
|
||
.dv-dockview {
|
||
--dv-group-view-background-color: var(--background);
|
||
--dv-tabs-and-actions-container-background-color: var(--muted);
|
||
--dv-activegroup-visiblepanel-tab-background-color: var(--background);
|
||
--dv-activegroup-hiddenpanel-tab-background-color: transparent;
|
||
--dv-inactivegroup-visiblepanel-tab-background-color: var(--background);
|
||
--dv-inactivegroup-hiddenpanel-tab-background-color: transparent;
|
||
--dv-tab-divider-color: var(--border);
|
||
--dv-activegroup-visiblepanel-tab-color: var(--foreground);
|
||
--dv-activegroup-hiddenpanel-tab-color: var(--muted-foreground);
|
||
--dv-inactivegroup-visiblepanel-tab-color: var(--foreground);
|
||
--dv-inactivegroup-hiddenpanel-tab-color: var(--muted-foreground);
|
||
--dv-separator-border: var(--border);
|
||
--dv-paneview-header-border-color: var(--border);
|
||
--dv-drag-over-background-color: oklch(from var(--primary) l c h / 0.1);
|
||
--dv-drag-over-border-color: var(--primary);
|
||
--dv-icon-hover-background-color: var(--muted);
|
||
--dv-tabs-and-actions-container-height: 33px;
|
||
--dv-tabs-and-actions-container-font-size: 0.75rem;
|
||
--dv-tab-font-size: 0.75rem;
|
||
font-family: inherit;
|
||
font-size: inherit;
|
||
}
|
||
|
||
/* Remove focus outline from dockview tabs after click */
|
||
.dv-dockview .dv-tab:focus-within::after,
|
||
.dv-dockview .dv-tab:focus::after {
|
||
outline: none !important;
|
||
content: none;
|
||
}
|
||
|
||
/* Dockview custom tab renderer */
|
||
.dv-review-tab {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
padding: 0 0 0 0.75rem;
|
||
width: 100%;
|
||
height: 100%;
|
||
font-size: 0.75rem;
|
||
user-select: none;
|
||
min-width: 0;
|
||
}
|
||
|
||
.dv-review-tab-label {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
min-width: 0;
|
||
}
|
||
|
||
.dv-review-tab-close {
|
||
flex-shrink: 0;
|
||
margin-left: auto;
|
||
margin-right: 0.375rem;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 1rem;
|
||
height: 1rem;
|
||
border-radius: 3px;
|
||
opacity: 0.25;
|
||
color: var(--muted-foreground);
|
||
transition: opacity 150ms, background 150ms, color 150ms;
|
||
}
|
||
|
||
.dv-review-tab:hover .dv-review-tab-close {
|
||
opacity: 1;
|
||
}
|
||
|
||
.dv-review-tab-close:hover {
|
||
opacity: 1;
|
||
background: var(--muted);
|
||
color: var(--foreground);
|
||
}
|
||
|
||
/* Chrome-style dock tabs — rounded top corners with the tabs inset slightly
|
||
into the muted strip. Inactive tabs are transparent (blend into the strip,
|
||
via the --dv-* vars above); the active tab takes the panel background so it
|
||
reads as connected to the content below. This rule handles shape + spacing +
|
||
hover only; the per-state background colors come from the bridge vars. */
|
||
.dv-dockview .dv-tabs-and-actions-container {
|
||
padding: 5px 6px 0;
|
||
}
|
||
|
||
.dv-dockview .dv-tab {
|
||
border-radius: 8px 8px 0 0;
|
||
margin-right: 2px;
|
||
}
|
||
|
||
/* The tab strip's `padding: 5px 6px 0` insets the TABS from the top (so their
|
||
rounded corners connect to the content below). The right-side actions
|
||
(Split/Unified, options, collapse-all) inherit that asymmetric top padding
|
||
and end up ~2.5px below the strip's true vertical center. Lift them by half
|
||
the asymmetry so they center in the full strip. */
|
||
.dv-dockview .dv-right-actions-container {
|
||
align-items: center;
|
||
margin-top: -2.5px;
|
||
}
|
||
|
||
.dv-dockview .dv-tab.dv-inactive-tab:hover {
|
||
background-color: color-mix(in oklch, var(--foreground) 6%, transparent) !important;
|
||
}
|
||
|
||
/* @pierre/diffs theme integration — pass plannotator theme colors into shadow DOM */
|
||
diffs-container {
|
||
--diffs-dark-bg: var(--background);
|
||
--diffs-light-bg: var(--background);
|
||
--diffs-dark: var(--foreground);
|
||
--diffs-light: var(--foreground);
|
||
}
|
||
|
||
/* Review comment thread styling */
|
||
.review-comment {
|
||
position: relative;
|
||
box-sizing: border-box;
|
||
/* Subtract the horizontal margins: box-sizing can't account for margin, so a
|
||
plain width:100% + side margins would overflow the slot (right edge touches
|
||
the container). Keep this in sync with the horizontal margin below. */
|
||
width: calc(100% - 0.5rem);
|
||
max-width: calc(100% - 0.5rem);
|
||
min-width: 0;
|
||
background: var(--popover);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
padding: 0.625rem 0.75rem;
|
||
font-size: 0.8125rem;
|
||
/* Force the app's sans font — without this the card inherits its surroundings,
|
||
which inside the diff is MONOSPACE, making inline comment prose hard to read
|
||
and inconsistent with the sidebar. Code spans opt back into mono explicitly. */
|
||
font-family: var(--font-sans);
|
||
margin: 0.5rem 0.25rem;
|
||
cursor: pointer;
|
||
/* Soft two-layer shadow (close contact + ambient lift) for a card that reads
|
||
as elevated above the diff without a heavy border. */
|
||
box-shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 4px 10px rgb(0 0 0 / 0.04);
|
||
transition: border-color 150ms, box-shadow 150ms, background 150ms;
|
||
}
|
||
|
||
.review-comment:hover {
|
||
border-color: var(--muted-foreground);
|
||
box-shadow: 0 1px 2px rgb(0 0 0 / 0.05), 0 6px 16px rgb(0 0 0 / 0.07);
|
||
}
|
||
|
||
/* Selected state — shared by inline annotations and file-comment cards. A
|
||
primary-colored border + 1px ring mirrors the sidebar's selected row so the
|
||
clicked card and its highlighted diff lines read as one selection. */
|
||
.review-comment.is-selected,
|
||
.review-comment.is-selected:hover {
|
||
border-color: var(--primary);
|
||
box-shadow: 0 0 0 1px var(--primary), 0 4px 12px rgb(0 0 0 / 0.06);
|
||
}
|
||
|
||
.review-comment-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
min-width: 0;
|
||
margin-bottom: 0.25rem;
|
||
font-size: 0.6875rem;
|
||
color: var(--muted-foreground);
|
||
}
|
||
|
||
.review-comment > .review-comment-body {
|
||
min-width: 0;
|
||
color: var(--foreground);
|
||
line-height: 1.5;
|
||
white-space: pre-wrap;
|
||
overflow-wrap: anywhere;
|
||
word-break: break-word;
|
||
}
|
||
|
||
/* Block markdown in the file-comment banner: cancel the pre-wrap used for the
|
||
inline-markdown body so rendered paragraphs/lists don't gain blank lines. */
|
||
.review-comment > .review-comment-body.ai-markdown {
|
||
white-space: normal;
|
||
}
|
||
|
||
/* Finding reasoning — wrap long unbroken tokens (file:line refs, identifiers) so
|
||
they don't bleed past the card's right edge, same as the comment body. */
|
||
.review-comment-reasoning {
|
||
min-width: 0;
|
||
overflow-wrap: anywhere;
|
||
word-break: break-word;
|
||
}
|
||
|
||
/* Inline markdown in review comments */
|
||
.review-comment-body .inline-code,
|
||
.review-comment-markdown .inline-code {
|
||
font-family: var(--font-mono);
|
||
font-size: 0.85em;
|
||
background: var(--muted);
|
||
padding: 0.1em 0.35em;
|
||
border-radius: 0.25rem;
|
||
}
|
||
|
||
.review-comment-body .inline-code-block,
|
||
.review-comment-markdown .inline-code-block {
|
||
font-family: var(--font-mono);
|
||
font-size: 0.75rem;
|
||
line-height: 1.5;
|
||
background: var(--code-bg);
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-sm);
|
||
padding: 0.5rem 0.75rem;
|
||
margin: 0.375rem 0;
|
||
overflow-x: auto;
|
||
white-space: pre;
|
||
}
|
||
|
||
.review-comment-body .inline-code-block code,
|
||
.review-comment-markdown .inline-code-block code {
|
||
font-family: var(--font-mono);
|
||
}
|
||
|
||
.light .review-comment-body .inline-code-block,
|
||
.light .review-comment-markdown .inline-code-block {
|
||
background: var(--code-bg);
|
||
}
|
||
|
||
/* Line selection highlight */
|
||
.line-selected {
|
||
background: oklch(from var(--primary) l c h / 0.3) !important;
|
||
}
|
||
|
||
/* Review-specific file tree states; shared base styles live in theme.css. */
|
||
.file-tree-item.scroll-active {
|
||
background: oklch(from var(--foreground) l c h / 0.06);
|
||
}
|
||
|
||
.file-tree-item.staged {
|
||
background: oklch(from var(--success) l c h / 0.1);
|
||
}
|
||
|
||
.file-tree-item.staged:hover {
|
||
background: var(--muted);
|
||
}
|
||
|
||
.file-tree-item.staged.active {
|
||
background: oklch(from var(--primary) l c h / 0.3);
|
||
}
|
||
|
||
/* Semantic diff terminal view */
|
||
.semantic-diff-panel {
|
||
height: 100%;
|
||
min-width: 0;
|
||
overflow: auto;
|
||
background: var(--background);
|
||
color: var(--foreground);
|
||
}
|
||
|
||
/* Centered terminal column — capped width, auto margins */
|
||
.semantic-diff-terminal {
|
||
width: 100%;
|
||
max-width: 56rem;
|
||
margin: 0 auto;
|
||
padding: 1.5rem;
|
||
font-family: var(--diff-font-override, var(--font-mono));
|
||
font-size: 0.8125rem;
|
||
line-height: 1.55;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
|
||
/* File section — flat, no box; grouping comes from a quiet underlined header */
|
||
.semantic-diff-file {
|
||
margin: 0 0 1.5rem;
|
||
}
|
||
|
||
.semantic-diff-file-header {
|
||
display: flex;
|
||
align-items: baseline;
|
||
min-width: 0;
|
||
padding: 0 0.5rem 0.375rem;
|
||
margin-bottom: 0.25rem;
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.7);
|
||
}
|
||
|
||
.semantic-diff-path {
|
||
min-width: 0;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.semantic-diff-path-dir {
|
||
color: var(--muted-foreground);
|
||
}
|
||
|
||
.semantic-diff-path-name {
|
||
color: var(--foreground);
|
||
font-weight: 600;
|
||
}
|
||
|
||
.semantic-diff-rows {
|
||
padding: 0;
|
||
}
|
||
|
||
.semantic-diff-loading,
|
||
.semantic-diff-empty,
|
||
.semantic-diff-error,
|
||
.semantic-diff-summary {
|
||
color: var(--muted-foreground);
|
||
}
|
||
|
||
.semantic-diff-error {
|
||
color: var(--destructive);
|
||
}
|
||
|
||
/* Entity row — grid-aligned, full-width, rounded hover target */
|
||
.semantic-diff-row {
|
||
display: grid;
|
||
grid-template-columns: 2ch 9ch minmax(0, 1fr) max-content;
|
||
column-gap: 1ch;
|
||
align-items: baseline;
|
||
width: 100%;
|
||
min-height: 1.75rem;
|
||
border: 0;
|
||
border-radius: var(--radius-sm);
|
||
padding: 0.1875rem 0.5rem;
|
||
background: transparent;
|
||
color: var(--foreground);
|
||
font: inherit;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
}
|
||
|
||
|
||
.semantic-diff-retry {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
min-height: 1.75rem;
|
||
margin-top: 0.5rem;
|
||
border: 0;
|
||
padding: 0;
|
||
background: transparent;
|
||
color: var(--foreground);
|
||
font: inherit;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.semantic-diff-row:focus-visible,
|
||
.semantic-diff-retry:focus-visible {
|
||
outline: 1px solid var(--ring);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
@media (hover: hover) {
|
||
.semantic-diff-row:hover,
|
||
.semantic-diff-retry:hover {
|
||
background: oklch(from var(--foreground) l c h / 0.045);
|
||
}
|
||
}
|
||
|
||
/* Nudge the add/remove glyphs up slightly so they read at the weight of the
|
||
modified triangle; line-height pinned so the larger size doesn't grow rows. */
|
||
.semantic-diff-symbol-added,
|
||
.semantic-diff-symbol-deleted {
|
||
font-size: 1.15em;
|
||
line-height: 1;
|
||
}
|
||
|
||
.semantic-diff-symbol-added {
|
||
color: var(--success);
|
||
}
|
||
|
||
.semantic-diff-symbol-deleted {
|
||
color: var(--destructive);
|
||
}
|
||
|
||
.semantic-diff-symbol-modified,
|
||
.semantic-diff-symbol-renamed,
|
||
.semantic-diff-symbol-moved,
|
||
.semantic-diff-symbol-reordered {
|
||
color: var(--primary);
|
||
}
|
||
|
||
.semantic-diff-kind,
|
||
.semantic-diff-status {
|
||
color: var(--muted-foreground);
|
||
}
|
||
|
||
.semantic-diff-name {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.semantic-diff-status {
|
||
justify-self: end;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.semantic-diff-summary {
|
||
margin-top: 0.5rem;
|
||
padding: 0 0.5rem;
|
||
}
|
||
|
||
/* "sem · N" pill in a diff file header. Fixed min-width (and a fixed-width
|
||
count, below) so 1- vs 2-digit counts — and files with no badge at all,
|
||
via the ghost — never skew the header button column across files. */
|
||
.semantic-file-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 0.3125rem;
|
||
height: 1.5rem;
|
||
min-width: 4.125rem;
|
||
padding: 0 0.4375rem;
|
||
border: 0;
|
||
border-radius: var(--radius-sm);
|
||
background: transparent;
|
||
color: var(--muted-foreground);
|
||
font-family: var(--font-mono);
|
||
font-size: 0.6875rem;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
transition: color 120ms ease, background 120ms ease;
|
||
}
|
||
|
||
/* Disabled "sem 0" badge for files with no semantic changes — same footprint
|
||
and structure as the live badge so every header looks consistent, but
|
||
grayed out and inert (no popover, no hover affordance). */
|
||
.semantic-file-badge-disabled {
|
||
cursor: default;
|
||
opacity: 0.45;
|
||
}
|
||
|
||
.semantic-file-badge-disabled .semantic-file-badge-count {
|
||
background: var(--muted);
|
||
color: var(--muted-foreground);
|
||
}
|
||
|
||
.semantic-file-badge:hover,
|
||
.semantic-file-badge[data-popup-open] {
|
||
color: var(--foreground);
|
||
background: var(--muted);
|
||
}
|
||
|
||
.semantic-file-badge:focus-visible {
|
||
outline: 1px solid var(--ring);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
.semantic-file-badge-label {
|
||
font-weight: 600;
|
||
letter-spacing: 0.02em;
|
||
}
|
||
|
||
.semantic-file-badge-count {
|
||
min-width: 1.5em;
|
||
padding: 0.0625rem 0.3125rem;
|
||
border-radius: calc(var(--radius-sm) - 2px);
|
||
background: oklch(from var(--primary) l c h / 0.14);
|
||
color: var(--primary);
|
||
font-variant-numeric: tabular-nums;
|
||
text-align: center;
|
||
}
|
||
|
||
/* Hover popover — same terminal rows as the panel, shadcn surface */
|
||
.semantic-diff-popover {
|
||
width: min(30rem, 90vw);
|
||
max-height: min(24rem, 70vh);
|
||
overflow: auto;
|
||
padding: 0.375rem;
|
||
background: var(--popover);
|
||
color: var(--popover-foreground);
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-lg);
|
||
font-family: var(--diff-font-override, var(--font-mono));
|
||
font-size: 0.8125rem;
|
||
line-height: 1.55;
|
||
font-variant-numeric: tabular-nums;
|
||
outline: none;
|
||
}
|
||
|
||
.semantic-diff-popover-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
padding: 0.25rem 0.5rem 0.375rem;
|
||
margin-bottom: 0.25rem;
|
||
border-bottom: 1px solid var(--border);
|
||
color: var(--muted-foreground);
|
||
}
|
||
|
||
.semantic-diff-popover-path {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
color: var(--foreground);
|
||
}
|
||
|
||
/* Call-flow Dock + file-header Lens */
|
||
.call-flow-panel {
|
||
height: 100%;
|
||
min-width: 0;
|
||
overflow: auto;
|
||
background: var(--background);
|
||
color: var(--foreground);
|
||
}
|
||
|
||
.call-flow-shell {
|
||
width: min(100%, 72rem);
|
||
min-height: 100%;
|
||
margin: 0 auto;
|
||
padding: 1.5rem clamp(1rem, 3vw, 2rem) 3rem;
|
||
font-family: var(--diff-font-override, var(--font-mono));
|
||
font-size: 0.75rem;
|
||
line-height: 1.45;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
|
||
.call-flow-header {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: flex-start;
|
||
justify-content: space-between;
|
||
gap: 1rem;
|
||
padding: 0.25rem 0 1rem;
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.65);
|
||
}
|
||
.call-flow-header > div:first-child { min-width: 0; flex: 1 1 14rem; }
|
||
|
||
.call-flow-eyebrow,
|
||
.call-flow-empty-kicker {
|
||
margin-bottom: 0.25rem;
|
||
color: var(--primary);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.625rem;
|
||
font-weight: 600;
|
||
letter-spacing: 0.1em;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
.call-flow-header h2 {
|
||
margin: 0;
|
||
font-family: var(--font-sans);
|
||
font-size: 1rem;
|
||
font-weight: 600;
|
||
letter-spacing: -0.015em;
|
||
}
|
||
|
||
.call-flow-header p {
|
||
margin: 0.25rem 0 0;
|
||
color: var(--muted-foreground);
|
||
font-size: 0.75rem;
|
||
}
|
||
|
||
.call-flow-header-actions {
|
||
display: flex;
|
||
flex: none;
|
||
align-items: center;
|
||
gap: 0.375rem;
|
||
margin-left: auto;
|
||
}
|
||
|
||
.call-flow-view-switch {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.125rem;
|
||
padding: 0.125rem;
|
||
border-radius: var(--radius-md);
|
||
background: var(--muted);
|
||
font-size: 0.6875rem;
|
||
}
|
||
|
||
.call-flow-view-switch button,
|
||
.call-flow-info,
|
||
.call-flow-languages-trigger {
|
||
min-height: 1.875rem;
|
||
border: 0;
|
||
border-radius: calc(var(--radius-md) - 2px);
|
||
background: transparent;
|
||
color: var(--muted-foreground);
|
||
font: inherit;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.call-flow-view-switch button {
|
||
min-width: 3.25rem;
|
||
padding: 0 0.625rem;
|
||
}
|
||
|
||
.call-flow-view-switch button[aria-pressed="true"] {
|
||
background: var(--background);
|
||
color: var(--foreground);
|
||
box-shadow: 0 1px 2px oklch(from var(--foreground) l c h / 0.08);
|
||
}
|
||
|
||
.call-flow-info {
|
||
display: grid;
|
||
width: 1.875rem;
|
||
place-items: center;
|
||
}
|
||
|
||
.call-flow-languages-trigger {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.375rem;
|
||
padding: 0 0.5rem;
|
||
font-family: var(--font-sans);
|
||
font-size: 0.6875rem;
|
||
font-weight: 550;
|
||
white-space: nowrap;
|
||
}
|
||
.call-flow-languages-trigger-count {
|
||
min-width: 2.5ch;
|
||
color: var(--primary);
|
||
font-family: var(--font-mono);
|
||
font-size: 0.625rem;
|
||
font-variant-numeric: tabular-nums;
|
||
text-align: right;
|
||
}
|
||
.call-flow-languages-trigger[data-popup-open] {
|
||
background: var(--muted);
|
||
color: var(--foreground);
|
||
}
|
||
|
||
.call-flow-view-switch button:focus-visible,
|
||
.call-flow-info:focus-visible,
|
||
.call-flow-languages-trigger:focus-visible,
|
||
.call-flow-raw button:focus-visible {
|
||
outline: 1px solid var(--ring);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
@media (hover: hover) and (pointer: fine) {
|
||
.call-flow-view-switch button:not([aria-pressed="true"]):hover,
|
||
.call-flow-info:hover,
|
||
.call-flow-languages-trigger:hover { color: var(--foreground); }
|
||
}
|
||
|
||
.call-flow-legend {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: 0.5rem 1rem;
|
||
padding: 0.625rem 0.75rem;
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.45);
|
||
color: var(--muted-foreground);
|
||
font-size: 0.6875rem;
|
||
}
|
||
|
||
.call-flow-legend b {
|
||
display: inline-block;
|
||
width: 1.25ch;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.call-flow-legend-hint { margin-left: auto; }
|
||
.call-flow-status-added { color: var(--success); }
|
||
.call-flow-status-removed { color: var(--destructive); }
|
||
|
||
.call-flow-trees {
|
||
display: grid;
|
||
gap: 0.875rem;
|
||
padding-top: 0.875rem;
|
||
}
|
||
|
||
.call-flow-tree-toolbar {
|
||
display: flex;
|
||
min-height: 1.875rem;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 0.625rem;
|
||
color: var(--muted-foreground);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.625rem;
|
||
}
|
||
.call-flow-context-summary { margin-right: auto; }
|
||
.call-flow-tree-actions {
|
||
display: flex;
|
||
min-width: 0;
|
||
margin-left: auto;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
gap: 0.125rem;
|
||
}
|
||
.call-flow-tree-actions-searching { flex: 1 1 24rem; }
|
||
.call-flow-tree-toolbar button {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: 1.875rem;
|
||
border: 0;
|
||
border-radius: var(--radius-sm);
|
||
padding: 0 0.5rem;
|
||
background: transparent;
|
||
color: var(--muted-foreground);
|
||
font: inherit;
|
||
font-weight: 550;
|
||
cursor: pointer;
|
||
}
|
||
.call-flow-tree-toolbar button:disabled {
|
||
opacity: 0.38;
|
||
cursor: default;
|
||
}
|
||
.call-flow-tree-toolbar .call-flow-icon-button {
|
||
width: 1.875rem;
|
||
padding: 0;
|
||
}
|
||
.call-flow-tree-toolbar button:focus-visible {
|
||
outline: 1px solid var(--ring);
|
||
outline-offset: 1px;
|
||
}
|
||
@media (hover: hover) and (pointer: fine) {
|
||
.call-flow-tree-toolbar button:not(:disabled):hover {
|
||
background: var(--muted);
|
||
color: var(--foreground);
|
||
}
|
||
}
|
||
|
||
.call-flow-entry {
|
||
overflow: hidden;
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.6);
|
||
content-visibility: auto;
|
||
contain-intrinsic-block-size: auto 20rem;
|
||
}
|
||
|
||
.call-flow-entry-header {
|
||
display: flex;
|
||
width: 100%;
|
||
align-items: center;
|
||
min-height: 2rem;
|
||
gap: 0.5rem;
|
||
border: 0;
|
||
padding: 0 0.75rem;
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.58);
|
||
background: oklch(from var(--muted) l c h / 0.2);
|
||
color: inherit;
|
||
font: inherit;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.call-flow-entry-mark {
|
||
display: grid;
|
||
width: 1rem;
|
||
place-items: center;
|
||
color: var(--primary);
|
||
}
|
||
.call-flow-entry-label {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
color: var(--foreground);
|
||
font-family: var(--font-sans);
|
||
font-weight: 550;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.call-flow-entry-meta {
|
||
margin-left: auto;
|
||
color: var(--muted-foreground);
|
||
font-size: 0.625rem;
|
||
letter-spacing: 0.04em;
|
||
text-transform: uppercase;
|
||
}
|
||
.call-flow-entry-header:focus-visible {
|
||
outline: 1px solid var(--ring);
|
||
outline-offset: -2px;
|
||
}
|
||
@media (hover: hover) and (pointer: fine) {
|
||
.call-flow-entry-header:hover { background: oklch(from var(--muted) l c h / 0.35); }
|
||
}
|
||
|
||
.call-flow-tree,
|
||
.call-flow-children {
|
||
margin: 0;
|
||
padding: 0;
|
||
list-style: none;
|
||
}
|
||
|
||
.call-flow-row {
|
||
position: relative;
|
||
display: grid;
|
||
grid-template-columns: 1.375rem 1.375rem minmax(12rem, 1fr) minmax(12rem, 24rem);
|
||
align-items: stretch;
|
||
min-height: 2.25rem;
|
||
padding-left: calc(var(--call-flow-depth) * 1.25rem + 0.375rem);
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.35);
|
||
}
|
||
.call-flow-row.call-flow-row-search-current {
|
||
background: oklch(from var(--warning) l c h / 0.08);
|
||
box-shadow: inset 2px 0 0 oklch(from var(--warning) l c h / 0.72);
|
||
}
|
||
.call-flow-tree-match {
|
||
border-radius: 2px;
|
||
padding: 0;
|
||
background: oklch(from var(--warning) l c h / 0.32);
|
||
color: inherit;
|
||
}
|
||
|
||
.call-flow-file-boundary {
|
||
display: grid;
|
||
grid-template-columns: max-content max-content minmax(0, 1fr);
|
||
min-height: 1.75rem;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
padding: 0.25rem 0.75rem 0.25rem calc(var(--call-flow-depth) * 1.25rem + 0.75rem);
|
||
border-top: 1px solid oklch(from var(--border) l c h / 0.65);
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.3);
|
||
background: oklch(from var(--muted) l c h / 0.28);
|
||
}
|
||
.call-flow-file-boundary-label {
|
||
color: var(--muted-foreground);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.5625rem;
|
||
font-weight: 650;
|
||
letter-spacing: 0.08em;
|
||
text-transform: uppercase;
|
||
}
|
||
.call-flow-file-boundary-name {
|
||
overflow: hidden;
|
||
color: var(--foreground);
|
||
font-size: 0.625rem;
|
||
font-weight: 550;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.call-flow-file-boundary-directory {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
color: var(--muted-foreground);
|
||
font-size: 0.625rem;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.call-flow-row-selectable::after {
|
||
content: '';
|
||
position: absolute;
|
||
z-index: 0;
|
||
inset: 0.1875rem;
|
||
border: 1px solid transparent;
|
||
border-radius: var(--radius-sm);
|
||
pointer-events: none;
|
||
transition: border-color 120ms ease, background-color 120ms ease, box-shadow 120ms ease;
|
||
}
|
||
|
||
.call-flow-row-selectable:hover::after,
|
||
.call-flow-row-selectable:focus-within::after {
|
||
border-color: oklch(from var(--primary) l c h / 0.58);
|
||
background: oklch(from var(--primary) l c h / 0.035);
|
||
box-shadow: 0 0 0 1px oklch(from var(--background) l c h / 0.7);
|
||
}
|
||
|
||
.call-flow-row-selected::after,
|
||
.call-flow-row-selected:hover::after {
|
||
border-color: var(--primary);
|
||
background: oklch(from var(--primary) l c h / 0.075);
|
||
box-shadow: 0 0 0 1px oklch(from var(--primary) l c h / 0.12);
|
||
}
|
||
|
||
.call-flow-row > * {
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
|
||
.call-flow-node:last-child > .call-flow-row { border-bottom: 0; }
|
||
.call-flow-row-added { background: oklch(from var(--success) l c h / 0.045); }
|
||
.call-flow-row-removed { background: oklch(from var(--destructive) l c h / 0.04); }
|
||
.call-flow-row-focused {
|
||
box-shadow: inset 2px 0 0 var(--primary);
|
||
background: oklch(from var(--primary) l c h / 0.07);
|
||
}
|
||
|
||
.call-flow-expand {
|
||
display: grid;
|
||
width: 1.375rem;
|
||
min-height: 2.25rem;
|
||
place-items: center;
|
||
border: 0;
|
||
padding: 0;
|
||
background: transparent;
|
||
color: var(--muted-foreground);
|
||
cursor: pointer;
|
||
}
|
||
|
||
.call-flow-status {
|
||
display: grid;
|
||
min-height: 2.25rem;
|
||
place-items: center;
|
||
color: var(--muted-foreground);
|
||
font-weight: 700;
|
||
}
|
||
|
||
.call-flow-status-added { color: var(--success); }
|
||
.call-flow-status-removed { color: var(--destructive); }
|
||
|
||
.call-flow-node-target {
|
||
display: flex;
|
||
align-items: center;
|
||
min-width: 0;
|
||
min-height: 2.25rem;
|
||
gap: 0.625rem;
|
||
border: 0;
|
||
padding: 0 0.75rem 0 0.375rem;
|
||
background: transparent;
|
||
color: inherit;
|
||
font: inherit;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.call-flow-node-target:disabled { cursor: default; }
|
||
.call-flow-node-label {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.call-flow-node-label { font-weight: 450; }
|
||
.call-flow-node-kind {
|
||
padding: 0.0625rem 0.3125rem;
|
||
border-radius: var(--radius-sm);
|
||
background: var(--muted);
|
||
color: var(--muted-foreground);
|
||
font-size: 0.625rem;
|
||
}
|
||
.call-flow-node-location,
|
||
.call-flow-node-location-placeholder {
|
||
min-width: 0;
|
||
min-height: 2.25rem;
|
||
}
|
||
.call-flow-node-location {
|
||
display: grid;
|
||
align-content: center;
|
||
justify-items: start;
|
||
gap: 0.0625rem;
|
||
overflow: hidden;
|
||
border: 0;
|
||
padding: 0.25rem 0.625rem;
|
||
background: transparent;
|
||
color: var(--muted-foreground);
|
||
font: inherit;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
}
|
||
.call-flow-node-location:disabled { cursor: default; }
|
||
.call-flow-node-location-main {
|
||
display: flex;
|
||
min-width: 0;
|
||
max-width: 100%;
|
||
align-items: baseline;
|
||
}
|
||
.call-flow-node-file {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
color: var(--foreground);
|
||
font-size: 0.6875rem;
|
||
font-weight: 500;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.call-flow-node-line {
|
||
flex: none;
|
||
color: var(--primary);
|
||
font-size: 0.625rem;
|
||
}
|
||
.call-flow-node-directory {
|
||
display: block;
|
||
width: 100%;
|
||
overflow: hidden;
|
||
color: var(--muted-foreground);
|
||
font-size: 0.625rem;
|
||
line-height: 1.25;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.call-flow-expand:focus-visible,
|
||
.call-flow-node-target:focus-visible,
|
||
.call-flow-node-location:focus-visible,
|
||
.call-flow-file-badge:focus-visible,
|
||
.call-flow-open-dock:focus-visible {
|
||
outline: 1px solid var(--ring);
|
||
outline-offset: -2px;
|
||
}
|
||
|
||
@media (hover: hover) and (pointer: fine) {
|
||
.call-flow-row:hover {
|
||
background: oklch(from var(--foreground) l c h / 0.045);
|
||
}
|
||
.call-flow-node-location:not(:disabled):hover .call-flow-node-file { color: var(--primary); }
|
||
}
|
||
|
||
.call-flow-empty {
|
||
display: grid;
|
||
justify-items: start;
|
||
/* align-content is load-bearing: this element also carries
|
||
.call-flow-shell's min-height:100%, and without it the auto rows
|
||
stretch across the whole panel, spreading the copy apart and pulling
|
||
the button into a tall rectangle. */
|
||
align-content: start;
|
||
gap: 0.625rem;
|
||
max-width: 34rem;
|
||
padding: clamp(1.75rem, 7vh, 3.5rem) 0.75rem 3rem;
|
||
color: var(--muted-foreground);
|
||
/* Prose, not code: the shell defaults to the mono diff face. */
|
||
font-family: var(--font-sans);
|
||
}
|
||
.call-flow-empty .call-flow-empty-kicker {
|
||
margin-bottom: 0;
|
||
color: var(--muted-foreground);
|
||
font-size: 0.625rem;
|
||
font-weight: 600;
|
||
letter-spacing: 0.09em;
|
||
}
|
||
.call-flow-empty strong {
|
||
color: var(--foreground);
|
||
font-family: var(--font-sans);
|
||
font-size: 1.0625rem;
|
||
font-weight: 600;
|
||
line-height: 1.3;
|
||
letter-spacing: -0.01em;
|
||
text-wrap: balance;
|
||
}
|
||
.call-flow-empty p {
|
||
max-width: 58ch;
|
||
margin: 0;
|
||
font-size: 0.8125rem;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.call-flow-loading {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.875rem;
|
||
min-height: 5rem;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.call-flow-loading div { display: grid; gap: 0.125rem; }
|
||
.call-flow-loading strong { font-family: var(--font-sans); font-size: 0.875rem; }
|
||
.call-flow-loading span:last-child { color: var(--muted-foreground); font-size: 0.6875rem; }
|
||
.call-flow-spinner {
|
||
width: 1rem;
|
||
height: 1rem;
|
||
border: 1.5px solid var(--border);
|
||
border-top-color: var(--primary);
|
||
border-radius: 50%;
|
||
animation: call-flow-spin 750ms linear infinite;
|
||
}
|
||
@keyframes call-flow-spin { to { transform: rotate(360deg); } }
|
||
.call-flow-raw {
|
||
margin-top: 1rem;
|
||
overflow: hidden;
|
||
border: 1px solid oklch(from var(--border) l c h / 0.72);
|
||
border-radius: var(--radius-md);
|
||
background: oklch(from var(--muted) l c h / 0.16);
|
||
}
|
||
|
||
.call-flow-raw-toolbar {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
min-height: 2.25rem;
|
||
gap: 0.25rem;
|
||
padding: 0.1875rem 0.5rem;
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.6);
|
||
color: var(--muted-foreground);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.6875rem;
|
||
}
|
||
.call-flow-raw-hint {
|
||
margin-right: auto;
|
||
color: var(--muted-foreground);
|
||
}
|
||
|
||
.call-flow-raw-toolbar button {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
min-height: 1.875rem;
|
||
gap: 0.375rem;
|
||
border: 0;
|
||
border-radius: var(--radius-sm);
|
||
padding: 0 0.5rem;
|
||
background: transparent;
|
||
color: var(--muted-foreground);
|
||
font: inherit;
|
||
cursor: pointer;
|
||
}
|
||
.call-flow-raw-toolbar button:disabled {
|
||
opacity: 0.38;
|
||
cursor: default;
|
||
}
|
||
.call-flow-raw-toolbar .call-flow-icon-button {
|
||
width: 1.875rem;
|
||
justify-content: center;
|
||
padding: 0;
|
||
}
|
||
|
||
.call-flow-search {
|
||
display: flex;
|
||
min-width: 0;
|
||
flex: 1;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
gap: 0.125rem;
|
||
}
|
||
.call-flow-search-field {
|
||
position: relative;
|
||
display: flex;
|
||
width: min(18rem, 100%);
|
||
min-width: 8rem;
|
||
align-items: center;
|
||
}
|
||
.call-flow-search-field > svg {
|
||
position: absolute;
|
||
left: 0.5rem;
|
||
z-index: 1;
|
||
color: var(--muted-foreground);
|
||
pointer-events: none;
|
||
}
|
||
.call-flow-search input {
|
||
width: 100%;
|
||
min-height: 1.875rem;
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-sm);
|
||
padding: 0 0.5rem 0 1.625rem;
|
||
background: var(--background);
|
||
color: var(--foreground);
|
||
font: inherit;
|
||
outline: none;
|
||
}
|
||
.call-flow-search input::placeholder { color: var(--muted-foreground); }
|
||
.call-flow-search input::-webkit-search-cancel-button { display: none; }
|
||
.call-flow-search input:focus-visible {
|
||
border-color: var(--ring);
|
||
box-shadow: 0 0 0 1px oklch(from var(--ring) l c h / 0.18);
|
||
}
|
||
.call-flow-search-count {
|
||
min-width: 3.5rem;
|
||
color: var(--muted-foreground);
|
||
font-family: var(--font-mono);
|
||
font-size: 0.625rem;
|
||
font-variant-numeric: tabular-nums;
|
||
text-align: center;
|
||
}
|
||
|
||
@media (hover: hover) and (pointer: fine) {
|
||
.call-flow-raw-toolbar button:hover { background: var(--muted); color: var(--foreground); }
|
||
}
|
||
|
||
.call-flow-raw pre {
|
||
max-height: calc(100vh - 14rem);
|
||
margin: 0;
|
||
overflow: auto;
|
||
padding: 0.75rem 0;
|
||
color: var(--foreground);
|
||
font: inherit;
|
||
line-height: 1.6;
|
||
tab-size: var(--diffs-tab-size, 4);
|
||
white-space: pre;
|
||
}
|
||
|
||
.call-flow-raw pre code { display: block; min-width: max-content; }
|
||
.call-flow-raw-line {
|
||
display: block;
|
||
width: 100%;
|
||
min-height: 1.6em;
|
||
min-width: max-content;
|
||
appearance: none;
|
||
border: 0;
|
||
padding: 0 1rem;
|
||
background: transparent;
|
||
color: inherit;
|
||
font: inherit;
|
||
line-height: inherit;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
user-select: text;
|
||
}
|
||
.call-flow-raw-line-added {
|
||
background: oklch(from var(--success) l c h / 0.08);
|
||
color: oklch(from var(--success) 0.78 c h);
|
||
}
|
||
.call-flow-raw-line-removed {
|
||
background: oklch(from var(--destructive) l c h / 0.075);
|
||
color: oklch(from var(--destructive) 0.76 c h);
|
||
}
|
||
@media (hover: hover) and (pointer: fine) {
|
||
.call-flow-raw-line:hover {
|
||
box-shadow: inset 0 0 0 1px oklch(from var(--primary) l c h / 0.38);
|
||
}
|
||
}
|
||
.call-flow-raw-line[aria-pressed="true"] {
|
||
box-shadow:
|
||
inset 2px 0 0 var(--primary),
|
||
inset 0 0 0 1px oklch(from var(--primary) l c h / 0.68);
|
||
}
|
||
.call-flow-raw-line:focus-visible {
|
||
position: relative;
|
||
z-index: 1;
|
||
outline: 1px solid var(--ring);
|
||
outline-offset: -1px;
|
||
}
|
||
.call-flow-raw mark {
|
||
border-radius: 2px;
|
||
padding: 0;
|
||
background: oklch(from var(--warning) l c h / 0.28);
|
||
color: inherit;
|
||
}
|
||
.call-flow-raw mark.call-flow-raw-match-current {
|
||
background: oklch(from var(--warning) l c h / 0.58);
|
||
box-shadow: 0 0 0 1px oklch(from var(--warning) l c h / 0.65);
|
||
}
|
||
|
||
.call-flow-raw pre:focus-visible {
|
||
outline: 1px solid var(--ring);
|
||
outline-offset: -2px;
|
||
}
|
||
|
||
.call-flow-diagnostics {
|
||
margin-top: 1rem;
|
||
padding: 0.625rem 0.75rem;
|
||
border: 1px solid oklch(from var(--warning) l c h / 0.3);
|
||
border-radius: var(--radius-md);
|
||
color: var(--muted-foreground);
|
||
font-size: 0.6875rem;
|
||
}
|
||
.call-flow-diagnostics summary { color: var(--warning); cursor: pointer; }
|
||
.call-flow-diagnostics ul { margin: 0.5rem 0 0; padding-left: 1.25rem; }
|
||
|
||
.call-flow-language-notice {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 0.75rem;
|
||
padding: 0.625rem 0.75rem;
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.55);
|
||
color: var(--muted-foreground);
|
||
font-size: 0.6875rem;
|
||
}
|
||
.call-flow-language-notice button,
|
||
.call-flow-languages-popover button {
|
||
flex: none;
|
||
min-height: 1.75rem;
|
||
border: 0;
|
||
border-radius: var(--radius-sm);
|
||
padding: 0 0.5rem;
|
||
background: transparent;
|
||
color: var(--primary);
|
||
font: inherit;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
}
|
||
.call-flow-language-notice button:disabled,
|
||
.call-flow-languages-popover button:disabled { opacity: 0.55; cursor: default; }
|
||
.call-flow-language-notice .call-flow-language-error { display: block; margin-top: 0.125rem; }
|
||
.call-flow-language-progress {
|
||
display: block;
|
||
margin-top: 0.125rem;
|
||
color: var(--muted-foreground);
|
||
font-variant-numeric: normal;
|
||
}
|
||
.call-flow-languages-popover {
|
||
width: min(24rem, calc(100vw - 2rem));
|
||
max-height: min(32rem, 72vh);
|
||
overflow: hidden;
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-lg);
|
||
background: var(--popover);
|
||
color: var(--popover-foreground);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.6875rem;
|
||
outline: none;
|
||
}
|
||
.call-flow-languages-popover-header {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
justify-content: space-between;
|
||
gap: 1rem;
|
||
padding: 0.75rem;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.call-flow-languages-popover-header div { display: grid; gap: 0.125rem; }
|
||
.call-flow-languages-popover-header strong { color: var(--foreground); font-size: 0.8125rem; font-weight: 600; }
|
||
.call-flow-languages-popover-header span { color: var(--muted-foreground); font-size: 0.625rem; }
|
||
.call-flow-languages-popover-header > span {
|
||
flex: none;
|
||
padding-top: 0.125rem;
|
||
font-family: var(--font-mono);
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.call-flow-languages-popover ul {
|
||
max-height: min(26rem, calc(72vh - 4rem));
|
||
margin: 0;
|
||
overflow: auto;
|
||
padding: 0;
|
||
list-style: none;
|
||
}
|
||
.call-flow-languages-popover li {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
min-height: 3rem;
|
||
gap: 0.75rem;
|
||
padding: 0.5rem 0.75rem;
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.45);
|
||
}
|
||
.call-flow-languages-popover li:last-child { border-bottom: 0; }
|
||
.call-flow-languages-popover li > span { display: grid; min-width: 0; gap: 0.125rem; }
|
||
.call-flow-languages-popover li strong { color: var(--foreground); font-size: 0.75rem; font-weight: 550; }
|
||
.call-flow-languages-popover li small { color: var(--muted-foreground); font-size: 0.625rem; font-variant-numeric: tabular-nums; }
|
||
.call-flow-languages-popover button:focus-visible {
|
||
outline: 1px solid var(--ring);
|
||
outline-offset: 2px;
|
||
}
|
||
.call-flow-language-error { flex-basis: 100%; color: var(--destructive) !important; font-variant-numeric: normal !important; line-height: 1.35; }
|
||
|
||
.call-flow-file-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 0.3125rem;
|
||
height: 1.5rem;
|
||
min-width: 4.375rem;
|
||
padding: 0 0.4375rem;
|
||
border: 0;
|
||
border-radius: var(--radius-sm);
|
||
background: transparent;
|
||
color: var(--muted-foreground);
|
||
font-family: var(--font-mono);
|
||
font-size: 0.6875rem;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
transition: color 120ms ease, background-color 120ms ease;
|
||
}
|
||
.call-flow-file-badge-disabled { cursor: default; opacity: 0.45; }
|
||
.call-flow-file-badge-missing { cursor: pointer; opacity: 0.7; }
|
||
.call-flow-file-badge-error { color: var(--destructive); }
|
||
.call-flow-file-badge-label { font-weight: 650; letter-spacing: 0.02em; }
|
||
.call-flow-file-badge-count {
|
||
min-width: 1.5em;
|
||
padding: 0.0625rem 0.3125rem;
|
||
border-radius: calc(var(--radius-sm) - 2px);
|
||
background: oklch(from var(--primary) l c h / 0.14);
|
||
color: var(--primary);
|
||
font-variant-numeric: tabular-nums;
|
||
text-align: center;
|
||
}
|
||
.call-flow-file-badge-disabled .call-flow-file-badge-count { background: var(--muted); color: var(--muted-foreground); }
|
||
.call-flow-file-badge-error .call-flow-file-badge-count { background: oklch(from var(--destructive) l c h / 0.12); color: var(--destructive); }
|
||
@media (hover: hover) and (pointer: fine) {
|
||
.call-flow-file-badge:not(:disabled):hover,
|
||
.call-flow-file-badge[data-popup-open] { background: var(--muted); color: var(--foreground); }
|
||
}
|
||
|
||
.call-flow-popover {
|
||
width: min(38rem, 94vw);
|
||
max-height: min(30rem, 78vh);
|
||
overflow: auto;
|
||
/* Momentum scroll that hits the Lens's edge must not chain to the page:
|
||
the page scroll moves the anchor, drags the popup out from under the
|
||
pointer, and hover-closes the Lens (worst under Safari rubber-banding). */
|
||
overscroll-behavior: contain;
|
||
padding: 0;
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-lg);
|
||
background: var(--popover);
|
||
color: var(--popover-foreground);
|
||
font-family: var(--diff-font-override, var(--font-mono));
|
||
font-size: 0.75rem;
|
||
outline: none;
|
||
}
|
||
.call-flow-popover-header {
|
||
position: sticky;
|
||
z-index: 2;
|
||
top: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.75rem;
|
||
min-height: 2.5rem;
|
||
padding: 0.3125rem 0.5rem 0.3125rem 0.625rem;
|
||
border-bottom: 1px solid var(--border);
|
||
background: var(--popover);
|
||
}
|
||
.call-flow-popover-title {
|
||
display: grid;
|
||
min-width: 0;
|
||
flex: 1;
|
||
gap: 0.0625rem;
|
||
}
|
||
.call-flow-popover-path {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
color: var(--foreground);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.75rem;
|
||
font-weight: 600;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.call-flow-popover-meta {
|
||
overflow: hidden;
|
||
color: var(--muted-foreground);
|
||
font-size: 0.5625rem;
|
||
font-variant-numeric: tabular-nums;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.call-flow-popover-view-switch {
|
||
display: inline-flex;
|
||
flex: none;
|
||
gap: 0.125rem;
|
||
padding: 0.125rem;
|
||
border-radius: var(--radius-sm);
|
||
background: var(--muted);
|
||
}
|
||
.call-flow-popover-view-switch button {
|
||
min-height: 1.625rem;
|
||
border: 0;
|
||
border-radius: calc(var(--radius-sm) - 2px);
|
||
padding: 0 0.5rem;
|
||
background: transparent;
|
||
color: var(--muted-foreground);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.625rem;
|
||
font-weight: 550;
|
||
cursor: pointer;
|
||
}
|
||
.call-flow-popover-view-switch button[aria-pressed="true"] {
|
||
background: var(--popover);
|
||
color: var(--foreground);
|
||
box-shadow: 0 1px 2px oklch(from var(--foreground) l c h / 0.08);
|
||
}
|
||
.call-flow-popover-view-switch button:focus-visible {
|
||
outline: 1px solid var(--ring);
|
||
outline-offset: 1px;
|
||
}
|
||
|
||
.call-flow-trees-compact {
|
||
gap: 0.375rem;
|
||
padding: 0 0.375rem 0.375rem;
|
||
font-size: 0.6875rem;
|
||
}
|
||
|
||
.call-flow-trees-compact .call-flow-entry-header {
|
||
min-height: 1.75rem;
|
||
padding-inline: 0.5rem;
|
||
}
|
||
|
||
.call-flow-trees-compact .call-flow-entry-meta { display: none; }
|
||
.call-flow-trees-compact .call-flow-row {
|
||
grid-template-columns: 1.375rem 1.375rem minmax(9rem, 1fr) minmax(8rem, 14rem);
|
||
min-height: 1.875rem;
|
||
padding-left: calc(var(--call-flow-depth) * 1rem + 0.25rem);
|
||
}
|
||
.call-flow-trees-compact .call-flow-expand,
|
||
.call-flow-trees-compact .call-flow-status,
|
||
.call-flow-trees-compact .call-flow-node-target,
|
||
.call-flow-trees-compact .call-flow-node-location,
|
||
.call-flow-trees-compact .call-flow-node-location-placeholder {
|
||
min-height: 1.875rem;
|
||
}
|
||
.call-flow-trees-compact .call-flow-node-target {
|
||
gap: 0.375rem;
|
||
padding-right: 0.375rem;
|
||
}
|
||
.call-flow-trees-compact .call-flow-node-location {
|
||
padding: 0.125rem 0.375rem;
|
||
}
|
||
.call-flow-trees-compact .call-flow-file-boundary {
|
||
min-height: 1.5rem;
|
||
padding-block: 0.125rem;
|
||
padding-left: calc(var(--call-flow-depth) * 1rem + 0.625rem);
|
||
}
|
||
.call-flow-trees-compact .call-flow-tree-toolbar {
|
||
position: sticky;
|
||
z-index: 2;
|
||
top: 2.5rem;
|
||
min-height: 1.75rem;
|
||
gap: 0.25rem;
|
||
margin-inline: -0.375rem;
|
||
padding: 0.125rem 0.375rem;
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.6);
|
||
background: var(--popover);
|
||
}
|
||
.call-flow-trees-compact .call-flow-tree-toolbar button {
|
||
min-height: 1.625rem;
|
||
padding-inline: 0.375rem;
|
||
}
|
||
.call-flow-trees-compact .call-flow-tree-toolbar .call-flow-icon-button {
|
||
width: 1.625rem;
|
||
}
|
||
.call-flow-open-dock {
|
||
position: sticky;
|
||
z-index: 2;
|
||
bottom: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
min-height: 2rem;
|
||
border: 0;
|
||
border-top: 1px solid var(--border);
|
||
padding: 0 0.625rem;
|
||
background: var(--popover);
|
||
color: var(--primary);
|
||
font: inherit;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.call-flow-raw-sections { min-width: 0; }
|
||
.call-flow-raw-section-title {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 1;
|
||
overflow: hidden;
|
||
padding: 0.25rem 0.625rem;
|
||
border-bottom: 1px solid oklch(from var(--border) l c h / 0.45);
|
||
background: var(--popover);
|
||
color: var(--muted-foreground);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.5625rem;
|
||
font-weight: 600;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.call-flow-raw-section + .call-flow-raw-section {
|
||
border-top: 1px solid var(--border);
|
||
}
|
||
.call-flow-raw-compact {
|
||
margin: 0;
|
||
overflow: visible;
|
||
border: 0;
|
||
border-radius: 0;
|
||
background: transparent;
|
||
}
|
||
.call-flow-raw-compact .call-flow-raw-toolbar {
|
||
position: sticky;
|
||
z-index: 2;
|
||
top: 2.5rem;
|
||
min-height: 1.875rem;
|
||
padding: 0.125rem 0.375rem;
|
||
background: var(--popover);
|
||
}
|
||
.call-flow-raw-compact .call-flow-raw-toolbar button {
|
||
min-height: 1.625rem;
|
||
}
|
||
.call-flow-raw-compact pre {
|
||
max-height: none;
|
||
padding: 0.375rem 0;
|
||
font-size: 0.6875rem;
|
||
line-height: 1.5;
|
||
}
|
||
.call-flow-raw-compact .call-flow-raw-line {
|
||
padding-inline: 0.625rem;
|
||
}
|
||
.call-flow-raw-compact .call-flow-raw-section-title { top: 4.375rem; }
|
||
|
||
.call-flow-retry {
|
||
min-height: 1.875rem;
|
||
margin-top: 0.25rem;
|
||
padding: 0 0.625rem;
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-sm);
|
||
background: var(--background);
|
||
color: var(--foreground);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.6875rem;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: background-color 140ms ease, border-color 140ms ease;
|
||
}
|
||
|
||
.call-flow-retry:hover { background: var(--muted); }
|
||
.call-flow-retry:focus-visible { outline: 1px solid var(--ring); outline-offset: 2px; }
|
||
|
||
/* Background runtime setup (runtime-missing advert only). */
|
||
|
||
/* Keep the explicit recovery action separate from the failure explanation. */
|
||
.call-flow-install-action {
|
||
display: grid;
|
||
justify-items: start;
|
||
gap: 0.75rem;
|
||
width: 100%;
|
||
margin-top: 0.75rem;
|
||
padding-top: 1.125rem;
|
||
border-top: 1px solid oklch(from var(--border) l c h / 0.55);
|
||
}
|
||
|
||
.call-flow-install-cta {
|
||
min-height: 2rem;
|
||
padding: 0 0.9375rem;
|
||
border: 1px solid transparent;
|
||
border-radius: var(--radius-sm);
|
||
background: var(--primary);
|
||
color: var(--primary-foreground);
|
||
font-family: var(--font-sans);
|
||
font-size: 0.75rem;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: filter 140ms ease, transform 100ms ease;
|
||
}
|
||
.call-flow-install-cta:hover { filter: brightness(1.1); }
|
||
/* Feedback on press, not on release. */
|
||
.call-flow-install-cta:active { transform: scale(0.97); }
|
||
.call-flow-install-cta:focus-visible { outline: 1px solid var(--ring); outline-offset: 2px; }
|
||
|
||
.call-flow-install-disclosure {
|
||
max-width: 58ch;
|
||
color: var(--muted-foreground);
|
||
font-size: 0.75rem;
|
||
line-height: 1.55;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.call-flow-install-disclosure strong {
|
||
color: var(--foreground);
|
||
font-size: inherit;
|
||
font-weight: 600;
|
||
}
|
||
.call-flow-install-detail { font-size: 0.6875rem; }
|
||
.call-flow-install-stages {
|
||
display: grid;
|
||
gap: 0.5rem;
|
||
margin: 0.75rem 0 0.25rem;
|
||
padding: 0;
|
||
list-style: none;
|
||
font-family: var(--font-sans);
|
||
font-size: 0.75rem;
|
||
}
|
||
.call-flow-install-stages li {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
color: var(--muted-foreground);
|
||
}
|
||
.call-flow-install-stages li[data-stage-state='active'] { color: var(--foreground); font-weight: 600; }
|
||
.call-flow-install-stages li[data-stage-state='complete'] { color: var(--foreground); }
|
||
.call-flow-install-stages li[data-stage-state='complete'] svg { color: var(--primary); }
|
||
.call-flow-install-stage-dot {
|
||
width: 0.8125rem;
|
||
height: 0.8125rem;
|
||
border: 1.5px solid var(--border);
|
||
border-radius: 50%;
|
||
}
|
||
.call-flow-spinner-small {
|
||
width: 0.8125rem;
|
||
height: 0.8125rem;
|
||
border-width: 1.5px;
|
||
flex: none;
|
||
}
|
||
|
||
.panel-utility-button {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex: none;
|
||
}
|
||
.panel-utility-button:focus-visible {
|
||
outline: 1px solid color-mix(in srgb, var(--primary) 65%, transparent);
|
||
outline-offset: 1px;
|
||
}
|
||
|
||
@media (pointer: coarse) {
|
||
.panel-utility-button {
|
||
min-width: 2.75rem;
|
||
min-height: 2.75rem;
|
||
}
|
||
.call-flow-row { grid-template-columns: 2.75rem 1.375rem minmax(0, 1fr) minmax(10rem, 20rem); }
|
||
.call-flow-expand,
|
||
.call-flow-node-target,
|
||
.call-flow-node-location,
|
||
.call-flow-file-badge,
|
||
.call-flow-open-dock,
|
||
.call-flow-view-switch button,
|
||
.call-flow-info,
|
||
.call-flow-languages-trigger,
|
||
.call-flow-languages-popover button,
|
||
.call-flow-tree-toolbar button,
|
||
.call-flow-raw-toolbar button,
|
||
.call-flow-search input { min-height: 2.75rem; }
|
||
.call-flow-search input { font-size: 1rem; }
|
||
.call-flow-expand { width: 2.75rem; }
|
||
}
|
||
|
||
@media (max-width: 42rem) {
|
||
.call-flow-header { align-items: stretch; flex-direction: column; }
|
||
.call-flow-header-actions { align-self: stretch; justify-content: space-between; margin-left: 0; }
|
||
.call-flow-legend-hint { width: 100%; margin-left: 0; }
|
||
.call-flow-row { grid-template-columns: 1.375rem 1.375rem minmax(0, 1fr); }
|
||
.call-flow-node-kind { display: none; }
|
||
.call-flow-node-location,
|
||
.call-flow-node-location-placeholder {
|
||
grid-column: 3;
|
||
min-height: 1.75rem;
|
||
padding-top: 0;
|
||
}
|
||
.call-flow-node-directory { display: none; }
|
||
.call-flow-file-boundary-directory { display: none; }
|
||
}
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.call-flow-spinner { animation: none; }
|
||
.call-flow-file-badge { transition: none; }
|
||
.call-flow-popover.popover-enter { animation: none; }
|
||
.call-flow-retry { transition: none; }
|
||
.call-flow-install-cta { transition: none; }
|
||
.call-flow-install-cta:active { transform: none; }
|
||
.call-flow-row-selectable::after { transition: none; }
|
||
}
|
||
|
||
/* =====================================================
|
||
Conventional Comments — Diagnostic-style labels
|
||
Visual language: VS Code severity indicators.
|
||
Monospace, lowercase, theme-native semantic colors.
|
||
===================================================== */
|
||
|
||
.cc-picker {
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
|
||
/* Label row — single line, no wrap, compact diagnostic tags */
|
||
.cc-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 1px;
|
||
}
|
||
|
||
/* Individual label tag — monospace, tight, code-native */
|
||
.cc-tag {
|
||
font-family: var(--font-mono);
|
||
font-size: 0.5625rem;
|
||
font-weight: 500;
|
||
line-height: 1;
|
||
letter-spacing: 0.01em;
|
||
padding: 0.1875rem 0.375rem;
|
||
border-radius: calc(var(--radius-sm) - 1px);
|
||
border: 1px solid transparent;
|
||
color: var(--muted-foreground);
|
||
background: transparent;
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
transition: color 0ms, background 0ms, border-color 0ms;
|
||
user-select: none;
|
||
}
|
||
|
||
/* Hover: instant on */
|
||
.cc-tag:hover {
|
||
color: var(--foreground);
|
||
background: var(--muted);
|
||
}
|
||
|
||
/* Ease off on leave */
|
||
.cc-tag:not(:hover) {
|
||
transition: color 150ms ease-out, background 150ms ease-out, border-color 150ms ease-out;
|
||
}
|
||
|
||
/* Active press feedback */
|
||
.cc-tag:active {
|
||
transform: scale(0.97);
|
||
}
|
||
|
||
/* --- Semantic tone colors (active state only) --- */
|
||
|
||
.cc-tag.active {
|
||
font-weight: 600;
|
||
border-color: oklch(from var(--muted-foreground) l c h / 0.2);
|
||
}
|
||
|
||
.cc-tag.cc-tone-danger.active {
|
||
color: var(--destructive);
|
||
background: oklch(from var(--destructive) l c h / 0.1);
|
||
border-color: oklch(from var(--destructive) l c h / 0.2);
|
||
}
|
||
|
||
.cc-tag.cc-tone-warn.active {
|
||
color: var(--warning);
|
||
background: oklch(from var(--warning) l c h / 0.1);
|
||
border-color: oklch(from var(--warning) l c h / 0.2);
|
||
}
|
||
|
||
.cc-tag.cc-tone-success.active {
|
||
color: var(--success);
|
||
background: oklch(from var(--success) l c h / 0.1);
|
||
border-color: oklch(from var(--success) l c h / 0.2);
|
||
}
|
||
|
||
.cc-tag.cc-tone-info.active {
|
||
color: var(--primary);
|
||
background: oklch(from var(--primary) l c h / 0.1);
|
||
border-color: oklch(from var(--primary) l c h / 0.2);
|
||
}
|
||
|
||
.cc-tag.cc-tone-neutral.active {
|
||
color: var(--foreground);
|
||
background: var(--muted);
|
||
border-color: var(--border);
|
||
}
|
||
|
||
/* --- Blocking toggle (only for issue & suggestion) --- */
|
||
|
||
.cc-blocking-toggle {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.3125rem;
|
||
margin-left: 0.25rem;
|
||
padding: 0.125rem 0.375rem 0.125rem 0.25rem;
|
||
font-family: var(--font-mono);
|
||
font-size: 0.5625rem;
|
||
font-weight: 500;
|
||
letter-spacing: 0.01em;
|
||
line-height: 1;
|
||
color: var(--muted-foreground);
|
||
background: transparent;
|
||
border: none;
|
||
border-left: 1px solid var(--border);
|
||
border-radius: 0;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
transition: color 150ms ease-out;
|
||
}
|
||
|
||
.cc-blocking-toggle:hover {
|
||
color: var(--foreground);
|
||
}
|
||
|
||
/* Mini toggle track */
|
||
.cc-toggle-track {
|
||
position: relative;
|
||
width: 1.125rem;
|
||
height: 0.625rem;
|
||
border-radius: 9999px;
|
||
background: var(--muted);
|
||
border: 1px solid var(--border);
|
||
flex-shrink: 0;
|
||
transition: background 150ms ease-out, border-color 150ms ease-out;
|
||
}
|
||
|
||
.cc-toggle-thumb {
|
||
position: absolute;
|
||
top: 1px;
|
||
left: 1px;
|
||
width: 0.375rem;
|
||
height: 0.375rem;
|
||
border-radius: 9999px;
|
||
background: var(--muted-foreground);
|
||
transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1), background 150ms ease-out;
|
||
}
|
||
|
||
/* Blocking ON state */
|
||
.cc-blocking-toggle.is-blocking .cc-toggle-track {
|
||
background: oklch(from var(--destructive) l c h / 0.15);
|
||
border-color: oklch(from var(--destructive) l c h / 0.3);
|
||
}
|
||
|
||
.cc-blocking-toggle.is-blocking .cc-toggle-thumb {
|
||
transform: translateX(0.4375rem);
|
||
background: var(--destructive);
|
||
}
|
||
|
||
.cc-blocking-toggle.is-blocking {
|
||
color: var(--destructive);
|
||
}
|
||
|
||
/* Generic ON state for cc-toggle (non-destructive) */
|
||
.cc-blocking-toggle.is-on .cc-toggle-track {
|
||
background: oklch(from var(--accent) l c h / 0.20);
|
||
border-color: oklch(from var(--accent) l c h / 0.40);
|
||
}
|
||
|
||
.cc-blocking-toggle.is-on .cc-toggle-thumb {
|
||
transform: translateX(0.4375rem);
|
||
background: var(--accent);
|
||
}
|
||
|
||
.cc-blocking-toggle.is-on {
|
||
color: var(--accent);
|
||
}
|
||
|
||
/* --- Inline badge on rendered annotation comments --- */
|
||
|
||
.cc-inline-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.25rem;
|
||
font-family: var(--font-mono);
|
||
font-size: 0.5625rem;
|
||
font-weight: 600;
|
||
letter-spacing: 0.01em;
|
||
line-height: 1;
|
||
padding: 0.125rem 0.3125rem;
|
||
border-radius: 2px;
|
||
border-left: 2px solid;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.cc-inline-badge.cc-tone-danger {
|
||
color: var(--destructive);
|
||
background: oklch(from var(--destructive) l c h / 0.08);
|
||
border-left-color: var(--destructive);
|
||
}
|
||
|
||
.cc-inline-badge.cc-tone-warn {
|
||
color: var(--warning);
|
||
background: oklch(from var(--warning) l c h / 0.08);
|
||
border-left-color: var(--warning);
|
||
}
|
||
|
||
.cc-inline-badge.cc-tone-success {
|
||
color: var(--success);
|
||
background: oklch(from var(--success) l c h / 0.08);
|
||
border-left-color: var(--success);
|
||
}
|
||
|
||
.cc-inline-badge.cc-tone-info {
|
||
color: var(--primary);
|
||
background: oklch(from var(--primary) l c h / 0.08);
|
||
border-left-color: var(--primary);
|
||
}
|
||
|
||
.cc-inline-badge.cc-tone-neutral {
|
||
color: var(--muted-foreground);
|
||
background: oklch(from var(--muted-foreground) l c h / 0.08);
|
||
border-left-color: var(--muted-foreground);
|
||
}
|
||
|
||
.cc-inline-dec {
|
||
opacity: 0.6;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.cc-inline-dec::before {
|
||
content: '·';
|
||
margin-right: 0.125rem;
|
||
opacity: 0.4;
|
||
}
|
||
|
||
.cc-inline-dec.cc-inline-dec-blocking {
|
||
opacity: 0.9;
|
||
color: var(--destructive);
|
||
}
|
||
|
||
/* Annotation toolbar for code review */
|
||
.review-toolbar {
|
||
position: absolute;
|
||
z-index: 100;
|
||
background: var(--popover);
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius);
|
||
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.2), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
|
||
padding: 0.5rem;
|
||
}
|
||
|
||
.review-toolbar-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.375rem;
|
||
padding: 0.375rem 0.625rem;
|
||
border-radius: var(--radius-sm);
|
||
font-size: 0.75rem;
|
||
font-weight: 500;
|
||
color: var(--foreground);
|
||
background: transparent;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.review-toolbar-btn:hover {
|
||
background: var(--muted);
|
||
}
|
||
|
||
.review-toolbar-btn.primary {
|
||
background: var(--primary);
|
||
color: var(--primary-foreground);
|
||
}
|
||
|
||
.review-toolbar-btn.primary:hover {
|
||
background: oklch(0.70 0.20 280);
|
||
}
|
||
|
||
/* Export modal code blocks */
|
||
.export-code-block {
|
||
font-family: var(--font-mono);
|
||
font-size: 0.75rem;
|
||
background: var(--muted);
|
||
border-radius: var(--radius-sm);
|
||
padding: 0.75rem;
|
||
overflow-x: auto;
|
||
white-space: pre-wrap;
|
||
word-break: break-word;
|
||
}
|
||
|
||
/* Suggested code input - code editor style */
|
||
.suggested-code-input {
|
||
width: 100%;
|
||
font-family: var(--font-mono);
|
||
font-size: 0.6875rem;
|
||
line-height: 1.6;
|
||
color: var(--foreground);
|
||
background: var(--code-bg);
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-sm);
|
||
padding: 0.625rem 0.75rem;
|
||
resize: vertical;
|
||
tab-size: 2;
|
||
white-space: pre;
|
||
overflow-wrap: normal;
|
||
overflow-x: auto;
|
||
}
|
||
|
||
.suggested-code-input::placeholder {
|
||
color: var(--muted-foreground);
|
||
opacity: 0.5;
|
||
}
|
||
|
||
.suggested-code-input:focus {
|
||
outline: none;
|
||
border-color: var(--success);
|
||
box-shadow: 0 0 0 1px oklch(from var(--success) l c h / 0.3);
|
||
}
|
||
|
||
.light .suggested-code-input {
|
||
background: var(--code-bg);
|
||
}
|
||
|
||
/* GitHub-style suggestion block. The colored header is the sole identity
|
||
marker; no left accent bar on the card body. */
|
||
.suggestion-block {
|
||
border: 1px solid oklch(from var(--success) l c h / 0.3);
|
||
border-radius: var(--radius-sm);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.suggestion-block-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.375rem;
|
||
padding: 0.25rem 0.625rem;
|
||
font-size: 0.625rem;
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.03em;
|
||
color: var(--success);
|
||
background: oklch(from var(--success) l c h / 0.08);
|
||
border-bottom: 1px solid oklch(from var(--success) l c h / 0.15);
|
||
}
|
||
|
||
.suggestion-block-code {
|
||
margin: 0;
|
||
font-size: 0.6875rem;
|
||
line-height: 1.6;
|
||
background: var(--code-bg);
|
||
padding: 0.5rem 0.75rem;
|
||
overflow-x: auto;
|
||
}
|
||
|
||
.suggestion-block-code code {
|
||
font-family: var(--font-mono);
|
||
background: transparent !important;
|
||
padding: 0 !important;
|
||
}
|
||
|
||
.suggestion-block.compact .suggestion-block-code {
|
||
max-height: 3rem;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.light .suggestion-block-code {
|
||
background: var(--code-bg);
|
||
}
|
||
|
||
.light .suggestion-block {
|
||
border-color: oklch(from var(--success) l c h / 0.3);
|
||
}
|
||
|
||
.light .suggestion-block-header {
|
||
background: oklch(from var(--success) l c h / 0.06);
|
||
border-bottom-color: oklch(from var(--success) l c h / 0.12);
|
||
}
|
||
|
||
/* Suggestion modal original code pane */
|
||
.suggestion-modal-original {
|
||
font-family: var(--font-mono);
|
||
background: var(--code-bg);
|
||
}
|
||
|
||
.suggestion-modal-original code {
|
||
font-family: var(--font-mono);
|
||
background: transparent !important;
|
||
padding: 0 !important;
|
||
}
|
||
|
||
.light .suggestion-modal-original {
|
||
background: var(--code-bg);
|
||
}
|
||
|
||
/* Suggestion diff (original vs suggested) */
|
||
.suggestion-diff {
|
||
font-family: var(--font-mono);
|
||
font-size: 0.6875rem;
|
||
line-height: 1.5;
|
||
overflow-x: auto;
|
||
}
|
||
|
||
.suggestion-diff-inner {
|
||
width: fit-content;
|
||
min-width: 100%;
|
||
}
|
||
|
||
.suggestion-diff-line {
|
||
display: flex;
|
||
padding: 0 0.625rem;
|
||
min-height: 1.25rem;
|
||
}
|
||
|
||
.suggestion-diff-line.removed {
|
||
background: oklch(from var(--destructive) l c h / 0.15);
|
||
}
|
||
|
||
.suggestion-diff-line.added {
|
||
background: oklch(from var(--success) l c h / 0.15);
|
||
}
|
||
|
||
.suggestion-diff-indicator {
|
||
flex-shrink: 0;
|
||
width: 1rem;
|
||
text-align: center;
|
||
user-select: none;
|
||
}
|
||
|
||
.suggestion-diff-line.removed .suggestion-diff-indicator {
|
||
color: var(--destructive);
|
||
}
|
||
|
||
.suggestion-diff-line.added .suggestion-diff-indicator {
|
||
color: var(--success);
|
||
}
|
||
|
||
.suggestion-diff-content {
|
||
white-space: pre;
|
||
}
|
||
|
||
.light .suggestion-diff-line.removed {
|
||
background: oklch(from var(--destructive) l c h / 0.1);
|
||
}
|
||
|
||
.light .suggestion-diff-line.added {
|
||
background: oklch(from var(--success) l c h / 0.1);
|
||
}
|
||
|
||
/* Search result highlight in sidebar */
|
||
.search-match-highlight {
|
||
background: oklch(from var(--warning) l c h / 0.25);
|
||
color: var(--foreground);
|
||
border-radius: 2px;
|
||
padding: 0 1px;
|
||
}
|
||
|
||
.light .search-match-highlight {
|
||
background: oklch(from var(--warning) l c h / 0.3);
|
||
}
|
||
|
||
/* Toast animations */
|
||
@keyframes fade-in {
|
||
from { opacity: 0; }
|
||
to { opacity: 1; }
|
||
}
|
||
|
||
@keyframes slide-in-from-bottom-2 {
|
||
from { transform: translateY(0.5rem) translateX(-50%); }
|
||
to { transform: translateY(0) translateX(-50%); }
|
||
}
|
||
|
||
.animate-in {
|
||
animation-duration: 200ms;
|
||
animation-timing-function: ease-out;
|
||
animation-fill-mode: both;
|
||
}
|
||
|
||
.fade-in {
|
||
animation-name: fade-in;
|
||
}
|
||
|
||
.slide-in-from-bottom-2 {
|
||
animation-name: slide-in-from-bottom-2;
|
||
}
|
||
|
||
/* AI Chat — toolbar divider, bubbles, line references, streaming cursor */
|
||
|
||
.ai-ask-divider {
|
||
border-top: 1px solid var(--border);
|
||
margin-top: 0.5rem;
|
||
opacity: 0.5;
|
||
}
|
||
|
||
.ai-line-ref {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0.25rem;
|
||
font-family: var(--font-mono);
|
||
font-size: 0.625rem;
|
||
background: var(--muted);
|
||
color: var(--muted-foreground);
|
||
padding: 0.125rem 0.375rem;
|
||
border-radius: var(--radius-sm);
|
||
cursor: pointer;
|
||
transition: color 150ms, background 150ms;
|
||
border: none;
|
||
}
|
||
|
||
.ai-line-ref:hover {
|
||
background: oklch(from var(--primary) l c h / 0.1);
|
||
color: var(--primary);
|
||
}
|
||
|
||
.ai-streaming-cursor {
|
||
display: inline-block;
|
||
width: 0.375rem;
|
||
height: 0.75rem;
|
||
background: var(--primary);
|
||
border-radius: 1px;
|
||
animation: ai-blink 1s step-end infinite;
|
||
vertical-align: text-bottom;
|
||
}
|
||
|
||
@keyframes ai-blink {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0; }
|
||
}
|
||
|
||
.ai-preview-link {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.375rem;
|
||
width: 100%;
|
||
margin-top: 0.5rem;
|
||
padding: 0.375rem 0.5rem;
|
||
border-radius: var(--radius-sm);
|
||
background: oklch(from var(--primary) l c h / 0.05);
|
||
border: 1px solid oklch(from var(--primary) l c h / 0.12);
|
||
font-size: 0.625rem;
|
||
color: var(--muted-foreground);
|
||
cursor: pointer;
|
||
transition: background 150ms, border-color 150ms;
|
||
text-align: left;
|
||
}
|
||
|
||
.ai-preview-link:hover {
|
||
background: oklch(from var(--primary) l c h / 0.1);
|
||
border-color: oklch(from var(--primary) l c h / 0.2);
|
||
}
|
||
|
||
/* AI inline markers in diff */
|
||
.ai-marker {
|
||
color: var(--muted-foreground);
|
||
border-left: 2px solid oklch(from var(--primary) l c h / 0.3);
|
||
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
|
||
transition: background 0ms, border-color 0ms;
|
||
}
|
||
|
||
.ai-marker:hover {
|
||
background: oklch(from var(--primary) l c h / 0.08);
|
||
border-left-color: var(--primary);
|
||
transition: background 150ms ease, border-color 150ms ease;
|
||
}
|
||
|
||
.ai-marker-answered .ai-marker-icon {
|
||
color: var(--primary);
|
||
}
|
||
|
||
/* AI markdown — rendered responses from marked */
|
||
.ai-markdown {
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.ai-markdown p {
|
||
margin: 0.25rem 0;
|
||
}
|
||
|
||
.ai-markdown p:first-child {
|
||
margin-top: 0;
|
||
}
|
||
|
||
.ai-markdown p:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.ai-markdown h1, .ai-markdown h2, .ai-markdown h3,
|
||
.ai-markdown h4, .ai-markdown h5, .ai-markdown h6 {
|
||
font-weight: 600;
|
||
margin: 0.5rem 0 0.25rem;
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.ai-markdown h1 { font-size: 0.875rem; }
|
||
.ai-markdown h2 { font-size: 0.8125rem; }
|
||
.ai-markdown h3 { font-size: 0.75rem; }
|
||
|
||
.ai-markdown ul, .ai-markdown ol {
|
||
padding-left: 1.25rem;
|
||
margin: 0.25rem 0;
|
||
}
|
||
|
||
.ai-markdown li {
|
||
margin: 0.125rem 0;
|
||
}
|
||
|
||
.ai-markdown ul { list-style: disc; }
|
||
.ai-markdown ol { list-style: decimal; }
|
||
|
||
.ai-markdown code {
|
||
font-family: var(--font-mono);
|
||
font-size: 0.6875rem;
|
||
background: var(--muted);
|
||
padding: 0.125rem 0.25rem;
|
||
border-radius: var(--radius-sm);
|
||
}
|
||
|
||
.ai-markdown pre {
|
||
margin: 0.375rem 0;
|
||
padding: 0.5rem;
|
||
background: var(--muted);
|
||
border-radius: var(--radius-sm);
|
||
overflow-x: auto;
|
||
}
|
||
|
||
.ai-markdown pre code {
|
||
background: none;
|
||
padding: 0;
|
||
font-size: 0.6875rem;
|
||
}
|
||
|
||
.ai-markdown hr {
|
||
border: none;
|
||
border-top: 1px solid var(--border);
|
||
margin: 0.5rem 0;
|
||
}
|
||
|
||
.ai-markdown strong {
|
||
font-weight: 600;
|
||
}
|
||
|
||
.ai-markdown a {
|
||
color: var(--primary);
|
||
}
|
||
|
||
.ai-markdown a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.ai-markdown blockquote {
|
||
border-left: 2px solid var(--border);
|
||
padding-left: 0.625rem;
|
||
margin: 0.375rem 0;
|
||
color: var(--muted-foreground);
|
||
}
|
||
|
||
/* AI sidebar — file group flash highlight (on marker click) */
|
||
.ai-file-group-highlight {
|
||
animation: ai-file-flash 1.2s ease-out;
|
||
}
|
||
|
||
@keyframes ai-file-flash {
|
||
0% { background: transparent; }
|
||
10% { background: var(--muted); }
|
||
30% { background: transparent; }
|
||
45% { background: var(--muted); }
|
||
65% { background: transparent; }
|
||
100% { background: transparent; }
|
||
}
|
||
|
||
/* AI config bar — custom dropdown menus */
|
||
.ai-config-menu {
|
||
position: absolute;
|
||
bottom: calc(100% + 4px);
|
||
left: 0;
|
||
min-width: 140px;
|
||
max-height: min(320px, 50vh);
|
||
display: flex;
|
||
flex-direction: column;
|
||
background: var(--popover);
|
||
border: 1px solid var(--border);
|
||
border-radius: var(--radius-sm);
|
||
padding: 3px;
|
||
box-shadow: 0 4px 12px oklch(0 0 0 / 0.15);
|
||
z-index: 50;
|
||
animation: ai-menu-in 120ms ease-out;
|
||
}
|
||
|
||
.ai-config-menu-scroll {
|
||
overflow-y: auto;
|
||
flex: 1;
|
||
min-height: 0;
|
||
}
|
||
|
||
.ai-config-menu-search {
|
||
padding: 4px;
|
||
margin-bottom: 2px;
|
||
border-bottom: 1px solid var(--border);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.ai-config-menu-search input {
|
||
width: 100%;
|
||
background: var(--muted);
|
||
border: 1px solid var(--border);
|
||
border-radius: calc(var(--radius-sm) - 2px);
|
||
padding: 3px 6px;
|
||
font-size: 0.6875rem;
|
||
color: var(--foreground);
|
||
outline: none;
|
||
}
|
||
|
||
.ai-config-menu-search input::placeholder {
|
||
color: var(--muted-foreground);
|
||
}
|
||
|
||
.ai-config-menu-search input:focus {
|
||
border-color: var(--primary);
|
||
}
|
||
|
||
.ai-config-menu-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
width: 100%;
|
||
padding: 0.375rem 0.5rem;
|
||
border-radius: calc(var(--radius-sm) - 2px);
|
||
font-size: 0.6875rem;
|
||
color: var(--foreground);
|
||
background: transparent;
|
||
border: none;
|
||
cursor: pointer;
|
||
transition: background 100ms;
|
||
text-align: left;
|
||
}
|
||
|
||
.ai-config-menu-item:hover {
|
||
background: var(--muted);
|
||
}
|
||
|
||
.ai-config-menu-item-active {
|
||
color: var(--primary);
|
||
}
|
||
|
||
@keyframes ai-menu-in {
|
||
from { opacity: 0; transform: translateY(4px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
/* Custom diff font overrides — user-level, must come last to win over element styles.
|
||
Variables are set on :root by App.tsx when the user picks a custom font/size. */
|
||
.review-comment-markdown .inline-code,
|
||
.review-comment-body .inline-code,
|
||
.review-comment-markdown .inline-code-block,
|
||
.review-comment-body .inline-code-block,
|
||
.review-comment-markdown .inline-code-block code,
|
||
.review-comment-body .inline-code-block code,
|
||
.export-code-block,
|
||
.suggestion-block-code code,
|
||
.suggestion-modal-original,
|
||
.suggestion-modal-original code,
|
||
.suggestion-diff,
|
||
.ai-markdown code {
|
||
font-family: var(--diff-font-override, var(--font-mono)) !important;
|
||
}
|
||
|
||
/* Font size override — only takes effect when --diff-font-size-override is set on :root */
|
||
:root[style*="--diff-font-size-override"] .review-comment-markdown .inline-code,
|
||
:root[style*="--diff-font-size-override"] .review-comment-body .inline-code,
|
||
:root[style*="--diff-font-size-override"] .review-comment-markdown .inline-code-block,
|
||
:root[style*="--diff-font-size-override"] .review-comment-body .inline-code-block,
|
||
:root[style*="--diff-font-size-override"] .review-comment-markdown .inline-code-block code,
|
||
:root[style*="--diff-font-size-override"] .review-comment-body .inline-code-block code,
|
||
:root[style*="--diff-font-size-override"] .export-code-block,
|
||
:root[style*="--diff-font-size-override"] .suggestion-block-code code,
|
||
:root[style*="--diff-font-size-override"] .suggestion-modal-original,
|
||
:root[style*="--diff-font-size-override"] .suggestion-modal-original code,
|
||
:root[style*="--diff-font-size-override"] .suggestion-diff,
|
||
:root[style*="--diff-font-size-override"] .ai-markdown code {
|
||
font-size: var(--diff-font-size-override) !important;
|
||
}
|
||
|
||
/* =====================================================
|
||
Code Tour
|
||
===================================================== */
|
||
|
||
/* --- Dialog overlay + card entrance / exit --- */
|
||
@keyframes tour-dialog-overlay-in {
|
||
from { opacity: 0; }
|
||
to { opacity: 1; }
|
||
}
|
||
|
||
@keyframes tour-dialog-overlay-out {
|
||
from { opacity: 1; }
|
||
to { opacity: 0; }
|
||
}
|
||
|
||
@keyframes tour-dialog-content-in {
|
||
from { opacity: 0; transform: scale(0.97); }
|
||
to { opacity: 1; transform: scale(1); }
|
||
}
|
||
|
||
@keyframes tour-dialog-content-out {
|
||
from { opacity: 1; transform: scale(1); }
|
||
to { opacity: 0; transform: scale(0.98); }
|
||
}
|
||
|
||
.tour-dialog-overlay {
|
||
animation: tour-dialog-overlay-in 150ms cubic-bezier(0.33, 1, 0.68, 1) both;
|
||
}
|
||
|
||
.tour-dialog-content {
|
||
animation: tour-dialog-content-in 250ms cubic-bezier(0.16, 1, 0.3, 1) both;
|
||
}
|
||
|
||
.tour-dialog-overlay-closing {
|
||
animation: tour-dialog-overlay-out 160ms cubic-bezier(0.33, 1, 0.68, 1) forwards;
|
||
}
|
||
|
||
.tour-dialog-content-closing {
|
||
animation: tour-dialog-content-out 180ms cubic-bezier(0.33, 1, 0.68, 1) forwards;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* --- Stop card reveal (applied by parent wrapper, staggered via animation-delay) --- */
|
||
@keyframes tour-stop-reveal {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(10px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
.tour-stop-reveal {
|
||
animation: tour-stop-reveal 280ms cubic-bezier(0.16, 1, 0.3, 1) both;
|
||
will-change: transform, opacity;
|
||
}
|
||
|
||
/* --- Intro page exit: lifts up and fades out, then stops page reveals --- */
|
||
@keyframes tour-intro-exit {
|
||
0% { opacity: 1; transform: translateY(0) scale(1); }
|
||
30% { opacity: 0.8; transform: translateY(-4px) scale(0.99); }
|
||
100% { opacity: 0; transform: translateY(-20px) scale(0.97); }
|
||
}
|
||
|
||
.tour-intro-exit {
|
||
animation: tour-intro-exit 320ms cubic-bezier(0.33, 1, 0.68, 1) forwards;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* --- Stops section label entrance (after intro exits) --- */
|
||
@keyframes tour-section-enter {
|
||
from { opacity: 0; transform: translateY(8px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
.tour-section-enter {
|
||
animation: tour-section-enter 280ms cubic-bezier(0.16, 1, 0.3, 1) both;
|
||
}
|
||
|
||
/* --- Page slide transitions (stops ↔ checklist) --- */
|
||
@keyframes tour-slide-out-left {
|
||
from { opacity: 1; transform: translateX(0); }
|
||
to { opacity: 0; transform: translateX(-48px); }
|
||
}
|
||
|
||
@keyframes tour-slide-in-right {
|
||
from { opacity: 0; transform: translateX(48px); }
|
||
to { opacity: 1; transform: translateX(0); }
|
||
}
|
||
|
||
@keyframes tour-slide-out-right {
|
||
from { opacity: 1; transform: translateX(0); }
|
||
to { opacity: 0; transform: translateX(48px); }
|
||
}
|
||
|
||
@keyframes tour-slide-in-left {
|
||
from { opacity: 0; transform: translateX(-48px); }
|
||
to { opacity: 1; transform: translateX(0); }
|
||
}
|
||
|
||
.tour-page-exit-fwd {
|
||
animation: tour-slide-out-left 220ms cubic-bezier(0.33, 1, 0.68, 1) forwards;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.tour-page-enter-fwd {
|
||
animation: tour-slide-in-right 260ms cubic-bezier(0.16, 1, 0.3, 1) both;
|
||
}
|
||
|
||
.tour-page-exit-bwd {
|
||
animation: tour-slide-out-right 220ms cubic-bezier(0.33, 1, 0.68, 1) forwards;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.tour-page-enter-bwd {
|
||
animation: tour-slide-in-left 260ms cubic-bezier(0.16, 1, 0.3, 1) both;
|
||
}
|
||
|
||
/* --- Checkbox transition (ease for color changes — elegant, per the easing blueprint) --- */
|
||
.tour-checkbox {
|
||
transition: background-color 150ms ease, border-color 150ms ease;
|
||
}
|
||
|
||
|
||
|
||
/* --- Reduced motion: disable all tour animations --- */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.tour-dialog-overlay,
|
||
.tour-dialog-overlay-closing,
|
||
.tour-dialog-content,
|
||
.tour-dialog-content-closing,
|
||
.tour-stop-reveal,
|
||
.tour-intro-exit,
|
||
.tour-section-enter,
|
||
.tour-page-exit-fwd,
|
||
.tour-page-enter-fwd,
|
||
.tour-page-exit-bwd,
|
||
.tour-page-enter-bwd {
|
||
animation: none !important;
|
||
}
|
||
.tour-checkbox {
|
||
transition: none !important;
|
||
}
|
||
}
|
||
|
||
/* Popover animation */
|
||
@keyframes popover-in {
|
||
from { opacity: 0; transform: scale(0.97) translateY(-4px); }
|
||
to { opacity: 1; transform: scale(1) translateY(0); }
|
||
}
|
||
.popover-enter { animation: popover-in 0.12s ease-out; }
|
||
|
||
/* =====================================================
|
||
PR Switch Loading Indicators
|
||
===================================================== */
|
||
|
||
@keyframes shimmer-slide {
|
||
0% { transform: translateX(-100%); }
|
||
100% { transform: translateX(400%); }
|
||
}
|
||
|
||
.pr-switch-shimmer {
|
||
height: 2px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.pr-switch-shimmer::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
width: 25%;
|
||
background: linear-gradient(90deg, transparent, oklch(from var(--accent) l c h / 0.8), transparent);
|
||
animation: shimmer-slide 1.2s ease-in-out infinite;
|
||
}
|
||
|
||
/* 3×3 grid — one lit block chases clockwise around the perimeter.
|
||
DOM order: 1 2 3 / 4 5 6 / 7 8 9 (5 = center, hidden)
|
||
Chase order: 0 1 2 / 7 · 3 / 6 5 4 */
|
||
|
||
@keyframes block-chase {
|
||
0%, 12% { opacity: 1; }
|
||
13%, 100% { opacity: 0.1; }
|
||
}
|
||
|
||
.pr-switch-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 6px);
|
||
grid-template-rows: repeat(3, 6px);
|
||
gap: 3px;
|
||
}
|
||
|
||
.pr-switch-grid > span {
|
||
width: 6px;
|
||
height: 6px;
|
||
border-radius: 1px;
|
||
background: oklch(from var(--accent) l c h);
|
||
opacity: 0.1;
|
||
animation: block-chase 1s linear infinite;
|
||
}
|
||
|
||
.pr-switch-grid > span:nth-child(5) { opacity: 0.1; animation: none; }
|
||
|
||
.pr-switch-grid > span:nth-child(1) { animation-delay: 0s; }
|
||
.pr-switch-grid > span:nth-child(2) { animation-delay: 0.125s; }
|
||
.pr-switch-grid > span:nth-child(3) { animation-delay: 0.25s; }
|
||
.pr-switch-grid > span:nth-child(6) { animation-delay: 0.375s; }
|
||
.pr-switch-grid > span:nth-child(9) { animation-delay: 0.5s; }
|
||
.pr-switch-grid > span:nth-child(8) { animation-delay: 0.625s; }
|
||
.pr-switch-grid > span:nth-child(7) { animation-delay: 0.75s; }
|
||
.pr-switch-grid > span:nth-child(4) { animation-delay: 0.875s; }
|
||
|
||
@keyframes overlay-fade-in {
|
||
from { opacity: 0; }
|
||
to { opacity: 1; }
|
||
}
|
||
|
||
.pr-switch-overlay {
|
||
animation: overlay-fade-in 0.15s ease-out both;
|
||
}
|
||
|
||
/* Code navigation peek panel — strip the syntax theme's block background */
|
||
.code-nav-peek code,
|
||
.code-nav-peek .pn-code {
|
||
background: transparent !important;
|
||
}
|
||
|
||
/* =====================================================
|
||
Scroll-fade
|
||
Soft mask fade on the top/bottom edges of a scroll container so
|
||
content dissolves into the surface instead of hard-cutting at the
|
||
edge. Applied directly to the scrolling element (OverlayScrollArea
|
||
renders the scroll node), e.g. the PR Overview panel regions.
|
||
|
||
Scroll-aware where supported (top crisp at the start, bottom crisp
|
||
at the end, both faded mid-scroll); falls back to a static both-edge
|
||
fade otherwise. The mask is painted on the viewport box, so it stays
|
||
pinned to the edges while content scrolls underneath.
|
||
===================================================== */
|
||
@property --sf-top {
|
||
syntax: "<length-percentage>";
|
||
inherits: false;
|
||
initial-value: 0px;
|
||
}
|
||
@property --sf-bottom {
|
||
syntax: "<length-percentage>";
|
||
inherits: false;
|
||
initial-value: 0px;
|
||
}
|
||
|
||
.scroll-fade {
|
||
--sf-size: min(2.5rem, 12%);
|
||
/* Fallback (no scroll-driven animations): static fade on both edges. */
|
||
--sf-top: var(--sf-size);
|
||
--sf-bottom: var(--sf-size);
|
||
-webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 var(--sf-top), #000 calc(100% - var(--sf-bottom)), transparent 100%);
|
||
mask-image: linear-gradient(to bottom, transparent 0, #000 var(--sf-top), #000 calc(100% - var(--sf-bottom)), transparent 100%);
|
||
}
|
||
|
||
@supports (animation-timeline: scroll()) {
|
||
.scroll-fade {
|
||
--sf-top: 0px;
|
||
--sf-bottom: var(--sf-size);
|
||
animation: sf-fade-top linear both, sf-fade-bottom linear both;
|
||
animation-timeline: scroll(self y), scroll(self y);
|
||
animation-range: 0 var(--sf-reveal, 96px), calc(100% - var(--sf-reveal, 96px)) 100%;
|
||
}
|
||
@keyframes sf-fade-top { to { --sf-top: var(--sf-size); } }
|
||
@keyframes sf-fade-bottom { to { --sf-bottom: 0px; } }
|
||
}
|
||
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.scroll-fade {
|
||
animation: none;
|
||
--sf-top: var(--sf-size);
|
||
--sf-bottom: var(--sf-size);
|
||
}
|
||
}
|
||
|
||
/* =====================================================
|
||
Compact markdown (PR Overview)
|
||
The shared BlockRenderer (RenderedMarkdown) is sized for full-page plans —
|
||
24px headings, 15px body, wide margins. `.md-compact` shrinks it to fit the
|
||
dense PR panel by overriding those inline utilities via specificity, so no
|
||
changes to the shared renderer components are needed.
|
||
===================================================== */
|
||
.md-compact {
|
||
font-size: 0.8125rem; /* 13px base */
|
||
line-height: 1.55;
|
||
}
|
||
.md-compact > :first-child { margin-top: 0; }
|
||
.md-compact h1 { font-size: 0.9375rem; line-height: 1.35; margin: 0.75rem 0 0.375rem; letter-spacing: normal; } /* 15px */
|
||
.md-compact h2 { font-size: 0.875rem; line-height: 1.35; margin: 0.75rem 0 0.25rem; } /* 14px */
|
||
.md-compact h3 { font-size: 0.8125rem; line-height: 1.4; margin: 0.625rem 0 0.25rem; } /* 13px */
|
||
.md-compact h4,
|
||
.md-compact h5,
|
||
.md-compact h6 { font-size: 0.8125rem; line-height: 1.4; margin: 0.5rem 0 0.25rem; }
|
||
.md-compact p { font-size: 0.8125rem; line-height: 1.6; margin-bottom: 0.5rem; } /* 13px */
|
||
/* list items (and other text-sm prose) render at the plan's 14px — bring them
|
||
down to the 13px body and give a matching line-height. */
|
||
.md-compact .text-sm { font-size: 0.8125rem; line-height: 1.55; }
|
||
.md-compact hr { margin: 0.875rem 0; }
|
||
.md-compact blockquote { margin: 0.5rem 0; }
|
||
/* Code blocks: the plan-sized CodeBlock keeps text-[13px] + a 20px my-5 margin,
|
||
so it reads bulky next to the 13px body. Shrink the font below the body and
|
||
tighten the box. `.my-5` is unique to the code-block wrapper in this renderer. */
|
||
.md-compact .my-5 { margin-top: 0.625rem; margin-bottom: 0.625rem; } /* was 20px */
|
||
.md-compact pre { font-size: 0.75rem; } /* 12px, under the body */
|
||
.md-compact pre code.pn-code { padding: 0.5rem 0.625rem; } /* tighter than the 1rem default */
|
||
|
||
/* PR description + comment media: cap wide screenshots/videos to the card width
|
||
(GitHub embeds them at their natural size, e.g. width="1440"), and wrap long
|
||
unbroken tokens (Vercel bot hashes, long URLs) so content never bleeds past
|
||
the card edge. */
|
||
.md-compact img,
|
||
.md-compact video,
|
||
.review-comment-markdown img,
|
||
.review-comment-markdown video {
|
||
max-width: 100%;
|
||
height: auto;
|
||
border-radius: 6px;
|
||
}
|
||
.md-compact,
|
||
.review-comment-markdown {
|
||
overflow-wrap: anywhere;
|
||
}
|