@jaeungkim/gantt-chart 0.4.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +192 -53
- package/dist/Gantt.d.ts +5 -0
- package/dist/bars/components/GanttBar.d.ts +20 -0
- package/dist/bars/components/GanttBarsLayer.d.ts +24 -0
- package/dist/bars/components/GanttDragGuides.d.ts +1 -0
- package/dist/bars/hooks/useGanttBarDrag.d.ts +16 -0
- package/dist/bars/hooks/useGanttDrawCreate.d.ts +25 -0
- package/dist/{hooks → bars/hooks}/useGanttProgressDrag.d.ts +3 -8
- package/dist/core/calendar.d.ts +4 -22
- package/dist/core/dates.d.ts +5 -21
- package/dist/core/index.d.ts +1 -14
- package/dist/core/reorder.d.ts +55 -0
- package/dist/core/tree.d.ts +4 -12
- package/dist/core/types.d.ts +4 -37
- package/dist/{components → dependencies/components}/GanttDependencyArrows.d.ts +4 -6
- package/dist/{hooks → dependencies/hooks}/useGanttLinkDrag.d.ts +2 -13
- package/dist/dependencies/utils/arrowPath.d.ts +20 -0
- package/dist/dependencies/utils/link.d.ts +17 -0
- package/dist/detail/components/GanttDetailPanel.d.ts +21 -0
- package/dist/detail/hooks/useGanttDetail.d.ts +42 -0
- package/dist/detail/utils/edit.d.ts +21 -0
- package/dist/gantt-chart.css +1 -1
- package/dist/index.cjs +1 -4
- package/dist/index.d.cts +11 -13
- package/dist/index.d.ts +11 -13
- package/dist/index.js +4071 -5141
- package/dist/interaction/hooks/useGanttInteraction.d.ts +2 -0
- package/dist/interaction/hooks/useGanttKeyboardNav.d.ts +33 -0
- package/dist/interaction/hooks/useGanttSelection.d.ts +12 -0
- package/dist/interaction/utils/a11y.d.ts +84 -0
- package/dist/props.d.ts +121 -0
- package/dist/rows/components/GanttRowsLayer.d.ts +13 -0
- package/dist/rows/hooks/useGanttCollapse.d.ts +18 -0
- package/dist/rows/hooks/useGanttRowModel.d.ts +19 -0
- package/dist/rows/utils/rows.d.ts +21 -0
- package/dist/shared/constants.d.ts +24 -0
- package/dist/{stores → shared}/context.d.ts +1 -7
- package/dist/shared/hooks/useLatestRef.d.ts +2 -0
- package/dist/shared/hooks/useResolvedTheme.d.ts +8 -0
- package/dist/shared/store.d.ts +81 -0
- package/dist/shared/task.d.ts +55 -0
- package/dist/shared/types.d.ts +115 -0
- package/dist/shared/utils/holidays.d.ts +12 -0
- package/dist/shared/utils/i18n.d.ts +5 -0
- package/dist/shared/utils/pointerGesture.d.ts +11 -0
- package/dist/shared/virtual/axis.d.ts +13 -0
- package/dist/shared/virtual/useVirtualWindow.d.ts +16 -0
- package/dist/shared/virtual/window.d.ts +30 -0
- package/dist/task-list/components/GanttGridSplitter.d.ts +6 -0
- package/dist/task-list/components/GanttTaskAddRow.d.ts +7 -0
- package/dist/task-list/components/GanttTaskGrid.d.ts +24 -0
- package/dist/task-list/hooks/useGanttRowDrag.d.ts +17 -0
- package/dist/task-list/hooks/useGanttTaskListPane.d.ts +11 -0
- package/dist/task-list/hooks/useGanttTaskMove.d.ts +16 -0
- package/dist/timeline/components/GanttChartHeader.d.ts +10 -0
- package/dist/timeline/components/GanttHolidayLabels.d.ts +6 -0
- package/dist/timeline/components/GanttNonWorkingLayer.d.ts +6 -0
- package/dist/timeline/components/GanttTodayLine.d.ts +6 -0
- package/dist/{hooks → timeline/hooks}/useGanttScrollApi.d.ts +22 -23
- package/dist/timeline/hooks/useGanttViewport.d.ts +47 -0
- package/dist/timeline/hooks/useGanttVirtualization.d.ts +28 -0
- package/dist/timeline/utils/geometry.d.ts +52 -0
- package/dist/timeline/utils/header.d.ts +8 -0
- package/dist/timeline/utils/transform.d.ts +4 -0
- package/dist/timeline/utils/viewport.d.ts +31 -0
- package/dist/useGanttSelectors.d.ts +11 -0
- package/package.json +12 -12
- package/dist/components/GanttBar.d.ts +0 -23
- package/dist/components/GanttChartHeader.d.ts +0 -17
- package/dist/components/GanttDragGuides.d.ts +0 -9
- package/dist/components/GanttGridSplitter.d.ts +0 -14
- package/dist/components/GanttMarkers.d.ts +0 -18
- package/dist/components/GanttTaskGrid.d.ts +0 -42
- package/dist/components/ScaleSelector.d.ts +0 -11
- package/dist/constants/gantt.d.ts +0 -47
- package/dist/core/criticalPath.d.ts +0 -67
- package/dist/core/scheduling.d.ts +0 -104
- package/dist/hooks/useGanttBarDrag.d.ts +0 -35
- package/dist/hooks/useGanttDrawCreate.d.ts +0 -31
- package/dist/hooks/useGanttExportApi.d.ts +0 -30
- package/dist/hooks/useGanttHistoryApi.d.ts +0 -28
- package/dist/hooks/useGanttRowDrag.d.ts +0 -33
- package/dist/hooks/useGanttSelectors.d.ts +0 -23
- package/dist/hooks/useGanttVirtualization.d.ts +0 -32
- package/dist/hooks/useResolvedTheme.d.ts +0 -15
- package/dist/pages/Gantt.d.ts +0 -306
- package/dist/stores/store.d.ts +0 -118
- package/dist/types/gantt.d.ts +0 -283
- package/dist/types/task.d.ts +0 -111
- package/dist/utils/a11y.d.ts +0 -141
- package/dist/utils/arrowPath.d.ts +0 -66
- package/dist/utils/dependency.d.ts +0 -42
- package/dist/utils/grouping.d.ts +0 -81
- package/dist/utils/headerUtils.d.ts +0 -6
- package/dist/utils/history.d.ts +0 -56
- package/dist/utils/i18n.d.ts +0 -16
- package/dist/utils/mutation.d.ts +0 -47
- package/dist/utils/pngExport.d.ts +0 -67
- package/dist/utils/pointerGesture.d.ts +0 -31
- package/dist/utils/rowDrag.d.ts +0 -69
- package/dist/utils/timeline.d.ts +0 -161
- package/dist/utils/transformData.d.ts +0 -15
- package/dist/utils/viewport.d.ts +0 -95
package/dist/core/types.d.ts
CHANGED
|
@@ -1,23 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The task data model - the part of it the headless core owns.
|
|
3
|
-
*
|
|
4
|
-
* Everything here is plain data and pure functions: no React, no DOM, no pixels.
|
|
5
|
-
* `src/types/task.ts` re-exports these and adds the render-side types (bar geometry,
|
|
6
|
-
* arrow coordinates) on top.
|
|
7
|
-
*/
|
|
8
|
-
export type TaskType = 'task' | 'milestone';
|
|
9
1
|
export type DependencyType = 'FS' | 'SS' | 'FF' | 'SF';
|
|
10
2
|
export interface TaskDependency {
|
|
11
3
|
/** The predecessor's id - a task's `dependencies` list the tasks it waits on */
|
|
12
4
|
targetId: string;
|
|
13
5
|
type: DependencyType;
|
|
14
|
-
/**
|
|
15
|
-
* Signed delay between the two ends of the link, in days
|
|
16
|
-
*
|
|
17
|
-
* Positive is lag (wait this long after the predecessor), negative is lead (overlap).
|
|
18
|
-
* Counted in working days when the working-day calendar is on, calendar days otherwise.
|
|
19
|
-
*/
|
|
20
|
-
lag?: number;
|
|
21
6
|
}
|
|
22
7
|
export interface Task {
|
|
23
8
|
id: string;
|
|
@@ -26,26 +11,13 @@ export interface Task {
|
|
|
26
11
|
endDate: string;
|
|
27
12
|
parentId: string | null;
|
|
28
13
|
sequence: string;
|
|
29
|
-
/** Task kind - 'milestone' renders as a diamond at startDate (default 'task') */
|
|
30
|
-
type?: TaskType;
|
|
31
14
|
/** Progress 0-100 (%) - omitted means no progress display */
|
|
32
15
|
progress?: number;
|
|
33
|
-
/**
|
|
34
|
-
* Bar color - any CSS color value
|
|
35
|
-
*
|
|
36
|
-
* The progress fill and the hover shade are derived from it, so one value colors the
|
|
37
|
-
* whole bar. Omitted, the `--gantt-*` theme tokens decide as before.
|
|
38
|
-
*/
|
|
16
|
+
/** Bar color (any CSS color) - progress fill and hover shade derive from it; omitted, the `--gantt-*` tokens decide */
|
|
39
17
|
color?: string;
|
|
40
18
|
/** Extra class name put on this task's bar and its task-list row */
|
|
41
19
|
className?: string;
|
|
42
|
-
/**
|
|
43
|
-
* Swimlane this task shares a row with
|
|
44
|
-
*
|
|
45
|
-
* Tasks with the same lane (inside the same group) are drawn side by side on one
|
|
46
|
-
* row; overlapping ones stack onto extra rows automatically. Omitted, the task
|
|
47
|
-
* gets a row of its own as before.
|
|
48
|
-
*/
|
|
20
|
+
/** Lane this task shares a row with - lane-mates draw side by side, overlaps stack onto extra rows */
|
|
49
21
|
lane?: string;
|
|
50
22
|
dependencies?: TaskDependency[];
|
|
51
23
|
/** Blocks every gesture on this task - overrides the chart's `readOnly` prop */
|
|
@@ -60,17 +32,12 @@ export interface Task {
|
|
|
60
32
|
allowLinkCreate?: boolean;
|
|
61
33
|
/** Allows/blocks deleting a dependency this task owns - overrides both `readOnly` settings */
|
|
62
34
|
allowLinkDelete?: boolean;
|
|
35
|
+
/** Allows/blocks dragging this row to a new position or parent - opt-in, off unless this or the chart's `allowReorder` turns it on */
|
|
36
|
+
allowReorder?: boolean;
|
|
63
37
|
/** Earliest date this task may be dragged to (ISO string) - overrides the chart's `minDate` */
|
|
64
38
|
minDate?: string;
|
|
65
39
|
/** Latest date this task may be dragged to (ISO string) - overrides the chart's `maxDate` */
|
|
66
40
|
maxDate?: string;
|
|
67
|
-
/** The scheduling engine never moves this task; it still constrains its successors */
|
|
68
|
-
manuallyScheduled?: boolean;
|
|
69
|
-
/** Planned start snapshot - drawn as a thin bar under the live one (UTC ISO string) */
|
|
70
|
-
baselineStart?: string;
|
|
71
|
-
/** Planned end snapshot (UTC ISO string) */
|
|
72
|
-
baselineEnd?: string;
|
|
73
41
|
}
|
|
74
|
-
export declare function isMilestoneTask(task: Pick<Task, 'type'>): boolean;
|
|
75
42
|
/** Normalizes progress into the 0-100 range; null when the value is missing or invalid */
|
|
76
43
|
export declare function normalizeProgress(progress: number | undefined): number | null;
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { GanttDependencyChange } from '../hooks/useGanttLinkDrag';
|
|
2
|
-
import {
|
|
2
|
+
import { GanttVirtualization } from '../../timeline/hooks/useGanttVirtualization';
|
|
3
|
+
import { GanttInteractionConfig, Task, TaskTransformed } from '../../shared/task';
|
|
3
4
|
interface Props {
|
|
4
5
|
transformedTasks: TaskTransformed[];
|
|
5
|
-
/** Row count of the chart - a lane row can carry several tasks, so it is not the task count */
|
|
6
6
|
rowCount: number;
|
|
7
|
-
|
|
8
|
-
criticalLinkIds?: Set<string>;
|
|
7
|
+
virtual: GanttVirtualization;
|
|
9
8
|
interaction?: GanttInteractionConfig;
|
|
10
9
|
onTasksChange?: (updatedTasks: Task[]) => void;
|
|
11
|
-
/** Returning false keeps the dependency */
|
|
12
10
|
onDependencyDelete?: (change: GanttDependencyChange) => boolean | void;
|
|
13
11
|
}
|
|
14
|
-
export default function GanttDependencyArrows({ transformedTasks, rowCount,
|
|
12
|
+
export default function GanttDependencyArrows({ transformedTasks, rowCount, virtual, interaction, onTasksChange, onDependencyDelete, }: Props): import("react").JSX.Element;
|
|
15
13
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DependencyType, GanttInteractionConfig, Task, TaskTransformed } from '
|
|
2
|
-
import { LinkAnchor } from '../utils/
|
|
1
|
+
import { DependencyType, GanttInteractionConfig, Task, TaskTransformed } from '../../shared/task';
|
|
2
|
+
import { LinkAnchor } from '../utils/link';
|
|
3
3
|
/** The link the user drew, handed to `onDependencyCreate` before anything is committed */
|
|
4
4
|
export interface GanttDependencyChange {
|
|
5
5
|
/** Task the drag started on */
|
|
@@ -12,19 +12,8 @@ interface UseGanttLinkDragParams {
|
|
|
12
12
|
task: TaskTransformed;
|
|
13
13
|
interaction?: GanttInteractionConfig;
|
|
14
14
|
onTasksChange?: (updatedTasks: Task[]) => void;
|
|
15
|
-
/** Returning false rejects the link */
|
|
16
15
|
onDependencyCreate?: (change: GanttDependencyChange) => boolean | void;
|
|
17
16
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Dragging a dependency from one of a bar's connector dots to another bar
|
|
20
|
-
*
|
|
21
|
-
* The gesture's direction is the dependency's direction: the bar the drag starts on is
|
|
22
|
-
* the predecessor, the bar it lands on the successor. Which ends the two dots sit on
|
|
23
|
-
* decides the type (see `linkTypeFromAnchors`).
|
|
24
|
-
*
|
|
25
|
-
* The drop target is found with `elementFromPoint` rather than from the bar geometry, so
|
|
26
|
-
* virtualization, scrolling and the sticky task list pane all take care of themselves.
|
|
27
|
-
*/
|
|
28
17
|
export declare function useGanttLinkDrag({ task, interaction, onTasksChange, onDependencyCreate, }: UseGanttLinkDragParams): {
|
|
29
18
|
startLink: (anchor: LinkAnchor) => (e: React.PointerEvent<HTMLElement>) => void;
|
|
30
19
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { RenderedDependency, TaskTransformed } from '../../shared/task';
|
|
2
|
+
import { LinkAnchor } from './link';
|
|
3
|
+
interface DragOffset {
|
|
4
|
+
offsetX: number;
|
|
5
|
+
offsetWidth: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function getSmartGanttPath(dependencyType: string, startX: number, startY: number, endX: number, endY: number): string;
|
|
8
|
+
export declare function anchorPoint(task: TaskTransformed, anchor: LinkAnchor, offset?: DragOffset): {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
};
|
|
12
|
+
export declare function buildTaskIndex(transformedTasks: TaskTransformed[]): Map<string, TaskTransformed>;
|
|
13
|
+
export interface ArrowViewport {
|
|
14
|
+
topPx: number;
|
|
15
|
+
bottomPx: number;
|
|
16
|
+
isBarVisible: (left: number, width: number) => boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function isArrowVisible(dep: Pick<RenderedDependency, "fromX" | "fromY" | "toX" | "toY">, viewport: ArrowViewport): boolean;
|
|
19
|
+
export declare function buildDependencies(taskById: Map<string, TaskTransformed>, liveOffsets: Record<string, DragOffset>): RenderedDependency[];
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DependencyType, Task, TaskDependency, TaskTransformed } from '../../shared/task';
|
|
2
|
+
export type LinkAnchor = "start" | "end";
|
|
3
|
+
export type LinkRejection = "self" | "duplicate" | "cycle";
|
|
4
|
+
type DependencyNode = Pick<Task, "id"> & {
|
|
5
|
+
dependencies?: TaskDependency[];
|
|
6
|
+
};
|
|
7
|
+
export declare function linkTypeFromAnchors(from: LinkAnchor, to: LinkAnchor): DependencyType;
|
|
8
|
+
interface LinkTarget {
|
|
9
|
+
task: TaskTransformed;
|
|
10
|
+
anchor: LinkAnchor;
|
|
11
|
+
}
|
|
12
|
+
export declare function resolveLinkTarget(rowTasks: TaskTransformed[], contentX: number, contentY: number, rowHeight: number, zone: number): LinkTarget | null;
|
|
13
|
+
export declare function validateDependency(tasks: DependencyNode[], predecessorId: string, successorId: string): LinkRejection | null;
|
|
14
|
+
export declare const LINK_REJECTION_LABEL: Record<LinkRejection, string>;
|
|
15
|
+
export declare function addDependency(tasks: Task[], predecessorId: string, successorId: string, type: DependencyType): Task[];
|
|
16
|
+
export declare function removeDependency(tasks: Task[], predecessorId: string, successorId: string): Task[];
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { GanttDetailRenderer, GanttLocaleOptions, GanttScaleKey } from '../../shared/types';
|
|
2
|
+
import { GanttInteractionConfig, Task, TaskTransformed } from '../../shared/task';
|
|
3
|
+
interface GanttDetailPanelProps {
|
|
4
|
+
task: TaskTransformed;
|
|
5
|
+
/** Every task, so a dependency's target id can be printed by name */
|
|
6
|
+
tasks: TaskTransformed[];
|
|
7
|
+
scale: GanttScaleKey;
|
|
8
|
+
localeOptions?: GanttLocaleOptions;
|
|
9
|
+
/** Gates which built-in fields take input - the same flags the drag gestures obey */
|
|
10
|
+
interaction?: GanttInteractionConfig;
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
onTasksChange?: (updatedTasks: Task[]) => void;
|
|
13
|
+
/** Replaces the body; the panel element itself, and its width, stay the chart's */
|
|
14
|
+
render?: GanttDetailRenderer;
|
|
15
|
+
/** False while the panel slides shut - the slide lives in flex-basis, see .gantt-detail */
|
|
16
|
+
open: boolean;
|
|
17
|
+
onTransitionEnd: React.TransitionEventHandler<HTMLElement>;
|
|
18
|
+
}
|
|
19
|
+
/** The docked panel on the right */
|
|
20
|
+
export default function GanttDetailPanel({ task, tasks, scale, localeOptions, interaction, onClose, onTasksChange, render, open, onTransitionEnd, }: GanttDetailPanelProps): import("react").JSX.Element;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { TaskTransformed } from '../../shared/task';
|
|
2
|
+
type TaskMouseHandler = (task: TaskTransformed, event: React.MouseEvent) => void;
|
|
3
|
+
interface ResolvedDetailState<T extends {
|
|
4
|
+
id: string;
|
|
5
|
+
}> {
|
|
6
|
+
openId: string | null;
|
|
7
|
+
task: T | null;
|
|
8
|
+
stale: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function resolveDetailState<T extends {
|
|
11
|
+
id: string;
|
|
12
|
+
}>({ enabled, detailTaskId, uncontrolled, tasks, }: {
|
|
13
|
+
enabled: boolean;
|
|
14
|
+
detailTaskId?: string | null;
|
|
15
|
+
uncontrolled: string | null;
|
|
16
|
+
tasks: T[];
|
|
17
|
+
}): ResolvedDetailState<T>;
|
|
18
|
+
interface UseGanttDetailParams {
|
|
19
|
+
enabled: boolean;
|
|
20
|
+
tasks: TaskTransformed[];
|
|
21
|
+
detailTaskId?: string | null;
|
|
22
|
+
onDetailChange?: (task: TaskTransformed | null) => void;
|
|
23
|
+
onTaskClick?: TaskMouseHandler;
|
|
24
|
+
}
|
|
25
|
+
interface GanttDetail {
|
|
26
|
+
task: TaskTransformed | null;
|
|
27
|
+
open: (taskId: string) => void;
|
|
28
|
+
close: () => void;
|
|
29
|
+
onTaskClick: TaskMouseHandler;
|
|
30
|
+
}
|
|
31
|
+
/** Controlled by `detailTaskId`, uncontrolled without it; `onDetailChange` fires in both modes */
|
|
32
|
+
export declare function useGanttDetail({ enabled, tasks, detailTaskId, onDetailChange, onTaskClick, }: UseGanttDetailParams): GanttDetail;
|
|
33
|
+
interface GanttDetailSlide {
|
|
34
|
+
/** The task to keep rendered - the open one, or the last one while the panel slides shut */
|
|
35
|
+
task: TaskTransformed | null;
|
|
36
|
+
/** Drives .gantt-detail-open - false on the mount frame so opening transitions up from zero */
|
|
37
|
+
open: boolean;
|
|
38
|
+
onTransitionEnd: React.TransitionEventHandler<HTMLElement>;
|
|
39
|
+
}
|
|
40
|
+
/** Holds the panel mounted through the slide-closed transition, then releases it */
|
|
41
|
+
export declare function useGanttDetailSlide(task: TaskTransformed | null): GanttDetailSlide;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { GanttInteractionConfig, Task } from '../../shared/task';
|
|
2
|
+
export type DetailEditableField = "name" | "startDate" | "endDate" | "progress";
|
|
3
|
+
interface DetailEditability {
|
|
4
|
+
name: boolean;
|
|
5
|
+
/** One flag for both dates - changing either one is a resize */
|
|
6
|
+
dates: boolean;
|
|
7
|
+
progress: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveDetailEditability(task: Task & {
|
|
10
|
+
isSummary?: boolean;
|
|
11
|
+
}, config?: GanttInteractionConfig): DetailEditability;
|
|
12
|
+
/** Turns one field's raw input into a patch; null means the value cannot commit and the field reverts */
|
|
13
|
+
export declare function resolveFieldPatch(task: Task, field: DetailEditableField, value: string, config?: GanttInteractionConfig): Partial<Omit<Task, "id">> | null;
|
|
14
|
+
export declare function applyTaskPatch(rawTasks: Task[], taskId: string, patch: Partial<Omit<Task, "id">>): Task[];
|
|
15
|
+
export declare function commitDetailPatch(storeApi: {
|
|
16
|
+
getState: () => {
|
|
17
|
+
rawTasks: Task[];
|
|
18
|
+
setRawTasks: (tasks: Task[]) => void;
|
|
19
|
+
};
|
|
20
|
+
}, taskId: string, patch: Partial<Omit<Task, "id">>, onTasksChange?: (tasks: Task[]) => void): void;
|
|
21
|
+
export {};
|
package/dist/gantt-chart.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.gantt-container{--gantt-font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Geist", system-ui, sans-serif;--gantt-background: #fafafa;--gantt-foreground: #18181b;--gantt-muted: #f4f4f5;--gantt-muted-foreground: #71717a;--gantt-border: #e4e4e7;--gantt-border-subtle: rgba(0, 0, 0, .04);--gantt-bar-bg: #e4e4e7;--gantt-bar-bg-hover: #d4d4d8;--gantt-bar-text: #18181b;--gantt-bar-shadow: 0 1px 2px rgba(0, 0, 0, .05);--gantt-bar-shadow-hover: 0 4px 12px rgba(0, 0, 0, .1);--gantt-bar-shadow-drag: 0 8px 24px rgba(0, 0, 0, .15);--gantt-arrow: #a1a1aa;--gantt-accent: #3b82f6;--gantt-today-marker: #f43f5e;--gantt-marker: #6366f1;--gantt-marker-warning: #f59e0b;--gantt-marker-label: #ffffff;--gantt-band-bg: rgba(99, 102, 241, .1);--gantt-milestone-bg: #52525b;--gantt-milestone-bg-hover: #3f3f46;--gantt-critical: #dc2626;--gantt-critical-bg: #fecaca;--gantt-critical-bg-hover: #fca5a5;--gantt-critical-text: #7f1d1d;--gantt-baseline-bg: #a1a1aa;--gantt-progress-bg: #a1a1aa;--gantt-progress-handle: #52525b;--gantt-non-working-bg: rgba(0, 0, 0, .035);--gantt-duration-fast: .15s;--gantt-transition-fast: .15s ease;--gantt-transition-normal: .2s ease}.gantt-container.dark,.gantt-container[data-theme=dark]{--gantt-background: #09090b;--gantt-foreground: #fafafa;--gantt-muted: #18181b;--gantt-muted-foreground: #a1a1aa;--gantt-border: #27272a;--gantt-border-subtle: rgba(255, 255, 255, .04);--gantt-bar-bg: #27272a;--gantt-bar-bg-hover: #3f3f46;--gantt-bar-text: #fafafa;--gantt-bar-shadow: 0 1px 2px rgba(0, 0, 0, .2);--gantt-bar-shadow-hover: 0 4px 12px rgba(0, 0, 0, .3);--gantt-bar-shadow-drag: 0 8px 24px rgba(0, 0, 0, .4);--gantt-arrow: #71717a;--gantt-today-marker: #fb7185;--gantt-marker: #818cf8;--gantt-marker-warning: #fbbf24;--gantt-marker-label: #18181b;--gantt-band-bg: rgba(129, 140, 248, .16);--gantt-milestone-bg: #d4d4d8;--gantt-milestone-bg-hover: #e4e4e7;--gantt-critical: #f87171;--gantt-critical-bg: #7f1d1d;--gantt-critical-bg-hover: #991b1b;--gantt-critical-text: #fee2e2;--gantt-baseline-bg: #71717a;--gantt-progress-bg: #52525b;--gantt-progress-handle: #a1a1aa;--gantt-non-working-bg: rgba(255, 255, 255, .03)}@media(prefers-color-scheme:dark){.gantt-container:not(.light):not([data-theme=light]){--gantt-background: #09090b;--gantt-foreground: #fafafa;--gantt-muted: #18181b;--gantt-muted-foreground: #a1a1aa;--gantt-border: #27272a;--gantt-border-subtle: rgba(255, 255, 255, .04);--gantt-bar-bg: #27272a;--gantt-bar-bg-hover: #3f3f46;--gantt-bar-text: #fafafa;--gantt-bar-shadow: 0 1px 2px rgba(0, 0, 0, .2);--gantt-bar-shadow-hover: 0 4px 12px rgba(0, 0, 0, .3);--gantt-bar-shadow-drag: 0 8px 24px rgba(0, 0, 0, .4);--gantt-arrow: #71717a;--gantt-today-marker: #fb7185;--gantt-marker: #818cf8;--gantt-marker-warning: #fbbf24;--gantt-marker-label: #18181b;--gantt-band-bg: rgba(129, 140, 248, .16);--gantt-milestone-bg: #d4d4d8;--gantt-milestone-bg-hover: #e4e4e7;--gantt-critical: #f87171;--gantt-critical-bg: #7f1d1d;--gantt-critical-bg-hover: #991b1b;--gantt-critical-text: #fee2e2;--gantt-baseline-bg: #71717a;--gantt-progress-bg: #52525b;--gantt-progress-handle: #a1a1aa;--gantt-non-working-bg: rgba(255, 255, 255, .03)}}.gantt-container,.gantt-container *,.gantt-container *:before,.gantt-container *:after{box-sizing:border-box}.gantt-container{display:flex;flex-direction:column;overflow:hidden;background:var(--gantt-background);font-family:var(--gantt-font-sans);font-size:13px;line-height:1.5;color:var(--gantt-foreground);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.gantt-container:focus{outline:none}.gantt-toolbar{flex-shrink:0;display:flex;align-items:center;justify-content:flex-end;padding:12px 16px;background:var(--gantt-background);border-bottom:1px solid var(--gantt-border)}.gantt-grid-toggle{margin-right:auto;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;color:var(--gantt-muted-foreground);background:transparent;border:1px solid var(--gantt-border);border-radius:6px;cursor:pointer;transition:color var(--gantt-transition-fast),background var(--gantt-transition-fast)}.gantt-grid-toggle:hover{color:var(--gantt-foreground);background:var(--gantt-muted)}.gantt-grid-toggle:focus-visible{outline:2px solid var(--gantt-accent);outline-offset:-2px}.gantt-grid-toggle svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.3}.gantt-grid-toggle[aria-expanded=true] svg rect{fill:var(--gantt-muted)}.gantt-scale-selector{display:inline-flex}.gantt-scale-control{display:flex;gap:2px;padding:3px;background:var(--gantt-muted);border-radius:8px;border:1px solid var(--gantt-border)}.gantt-scale-button{position:relative;padding:6px 14px;font-family:inherit;font-size:12px;font-weight:500;color:var(--gantt-muted-foreground);background:transparent;border:none;border-radius:6px;cursor:pointer;transition:all var(--gantt-transition-fast);text-transform:capitalize}.gantt-scale-button:hover{color:var(--gantt-foreground)}.gantt-scale-button:focus-visible{outline:2px solid var(--gantt-accent);outline-offset:-2px}.gantt-scale-button[data-active=true]{color:var(--gantt-foreground);background:var(--gantt-background);box-shadow:0 1px 3px #00000014}.gantt-main{position:relative;flex:1;min-height:0;overflow:hidden}.gantt-scroll-container{position:relative;width:100%;height:100%;overflow:auto}.gantt-body{display:flex;align-items:stretch;width:max-content;min-width:100%}.gantt-timeline{position:relative;flex:none}.gantt-grid{position:sticky;left:0;z-index:50;flex:none;background:var(--gantt-background);border-right:1px solid var(--gantt-border)}.gantt-grid-header{position:sticky;top:0;z-index:1;display:flex;align-items:flex-end;padding-bottom:6px;overflow:hidden;background:var(--gantt-background);border-bottom:1px solid var(--gantt-border)}.gantt-grid-header-cell{padding:0 10px;font-size:11px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--gantt-muted-foreground);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gantt-grid-body{position:relative}.gantt-grid-row{position:absolute;top:0;left:0;display:flex;width:100%;align-items:center;overflow:hidden;border-bottom:1px solid var(--gantt-border-subtle)}.gantt-grid-row:hover{background:var(--gantt-muted)}.gantt-grid-row.summary{font-weight:600}.gantt-grid-row.selected{background:var(--gantt-muted);box-shadow:inset 2px 0 0 var(--gantt-accent)}.gantt-grid-row.draggable{cursor:grab}.gantt-grid.row-dragging,.gantt-grid.row-dragging .gantt-grid-row{cursor:grabbing}.gantt-grid-row.dragging{opacity:.45}.gantt-grid-row.drop-into{background:color-mix(in srgb,var(--gantt-accent) 14%,transparent);box-shadow:inset 0 0 0 1px var(--gantt-accent)}.gantt-grid-row.drop-into.invalid,.gantt-grid.row-dragging .gantt-grid-row.drop-into.invalid{background:color-mix(in srgb,var(--gantt-today-marker) 14%,transparent);box-shadow:inset 0 0 0 1px var(--gantt-today-marker);cursor:no-drop}.gantt-grid-drop-line{position:absolute;left:0;right:0;height:2px;margin-top:-1px;background:var(--gantt-accent);pointer-events:none}.gantt-grid-drop-line:before{content:"";position:absolute;top:-3px;left:0;width:8px;height:8px;border-radius:50%;background:inherit}.gantt-grid-drop-line.invalid{background:var(--gantt-today-marker)}.gantt-grid-cell{display:flex;align-items:center;min-width:0;padding:0 10px;font-size:12px;color:var(--gantt-foreground)}.gantt-grid-cell+.gantt-grid-cell{color:var(--gantt-muted-foreground)}.gantt-grid-cell-text{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gantt-grid-indent{flex:none}.gantt-grid-expander{flex:none;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:4px;padding:0;color:var(--gantt-muted-foreground);background:transparent;border:none;border-radius:3px;cursor:pointer}.gantt-grid-expander:hover{color:var(--gantt-foreground);background:var(--gantt-border)}.gantt-grid-expander:focus-visible{outline:2px solid var(--gantt-accent);outline-offset:-2px}.gantt-grid-expander svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;transition:transform var(--gantt-transition-fast)}.gantt-grid-expander.open svg{transform:rotate(90deg)}.gantt-grid-expander-spacer{flex:none;width:20px}.gantt-grid-splitter{position:absolute;top:0;bottom:0;z-index:60;width:5px;cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none}.gantt-grid-splitter:hover,.gantt-grid-splitter:focus-visible{background:var(--gantt-accent);opacity:.5;outline:none}.gantt-drag-guides{position:absolute;top:0;bottom:0;left:0;z-index:40;pointer-events:none}.gantt-drag-guide{position:absolute;top:0;bottom:0;width:1px;background:var(--gantt-accent);opacity:.9}.gantt-drag-guide-label{position:absolute;top:6px;left:0;transform:translate(-50%);padding:3px 7px;background:var(--gantt-accent);color:#fff;border-radius:4px;font-family:inherit;font-size:11px;font-weight:500;white-space:nowrap}.gantt-scroll-container{scrollbar-width:thin;scrollbar-color:var(--gantt-border) transparent}.gantt-scroll-container::-webkit-scrollbar{width:10px;height:10px}.gantt-scroll-container::-webkit-scrollbar-track{background:transparent}.gantt-scroll-container::-webkit-scrollbar-thumb{background:var(--gantt-border);border-radius:5px;border:2px solid var(--gantt-background)}.gantt-scroll-container::-webkit-scrollbar-thumb:hover{background:var(--gantt-muted-foreground)}.gantt-scroll-container::-webkit-scrollbar-corner{background:transparent}.gantt-header-wrapper{position:sticky;top:0;z-index:30}.gantt-header{position:relative;background:var(--gantt-background);border-bottom:1px solid var(--gantt-border)}.gantt-header-content{display:flex;flex-direction:column}.gantt-top-header{position:relative;display:flex;height:44px;border-bottom:1px solid var(--gantt-border-subtle)}.gantt-top-groups{display:flex}.gantt-top-group{--top-group-inset: 16px;display:flex;align-items:center;padding:0 var(--top-group-inset);font-size:13px;font-weight:600;letter-spacing:-.01em;background:var(--gantt-background);color:var(--gantt-foreground)}.gantt-top-group-label{position:sticky;left:var(--top-group-inset);margin:0;padding:0;white-space:nowrap}.gantt-bottom-row{display:flex;height:28px;background:var(--gantt-muted)}.gantt-bottom-cell{display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:500;color:var(--gantt-muted-foreground);letter-spacing:.01em}.gantt-content{position:relative;background:var(--gantt-background)}.gantt-non-working-layer{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:0}.gantt-non-working-range{position:absolute;top:0;bottom:0;background:var(--gantt-non-working-bg)}.gantt-rows{position:absolute;top:0;left:0;width:100%;height:100%;z-index:0;pointer-events:none}.gantt-task-row{position:absolute;top:0;left:0;display:flex;width:100%;align-items:center;border-bottom:1px solid var(--gantt-border-subtle);pointer-events:none}.gantt-range-band-layer{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:0}.gantt-range-band{position:absolute;top:0;bottom:0;background:var(--gantt-band-color, var(--gantt-band-bg))}.gantt-range-band-label{position:absolute;top:2px;left:4px;font-size:10px;font-weight:600;color:var(--gantt-muted-foreground);white-space:nowrap}.gantt-marker{position:absolute;top:0;bottom:0;width:2px;margin-left:-1px;background:var(--gantt-marker-color, var(--gantt-marker));pointer-events:none;z-index:2}.gantt-marker[data-warning=true]{--gantt-marker-color: var(--gantt-marker-warning)}.gantt-marker-label{position:absolute;top:2px;left:3px;padding:1px 5px;font-size:10px;font-weight:600;line-height:1.4;color:var(--gantt-marker-label);background:var(--gantt-marker-color, var(--gantt-marker));border-radius:3px;white-space:nowrap}.gantt-today-marker{position:absolute;top:0;bottom:0;width:2px;margin-left:-1px;background:var(--gantt-today-marker);opacity:.7;pointer-events:none;z-index:2}.gantt-dependency-arrows{position:absolute;top:0;left:0;width:100%;pointer-events:none;z-index:0}.gantt-dependency-arrows.linking{z-index:150}.gantt-dependency-arrow{stroke:var(--gantt-arrow);stroke-width:1.5;fill:none}.gantt-dependency-arrow.selected{stroke:var(--gantt-accent);stroke-width:2.5}.gantt-dependency-arrow-head{fill:var(--gantt-arrow);stroke:none}.gantt-dependency-hit{stroke:transparent;stroke-width:12;fill:none;cursor:pointer;pointer-events:stroke}.gantt-dependency-hit:hover+.gantt-dependency-arrow{stroke:var(--gantt-accent)}.gantt-dependency-delete{cursor:pointer;pointer-events:auto}.gantt-dependency-delete circle{fill:var(--gantt-accent)}.gantt-dependency-delete path{stroke:#fff;stroke-width:1.6;stroke-linecap:round}.gantt-link-handle{position:absolute;top:50%;width:10px;height:10px;background:var(--gantt-background);border:2px solid var(--gantt-accent);border-radius:50%;transform:translateY(-50%);opacity:0;cursor:crosshair;touch-action:none;pointer-events:none;transition:opacity var(--gantt-transition-fast)}.gantt-link-handle.start{left:-14px}.gantt-link-handle.end{right:-14px}.gantt-milestone .gantt-link-handle.start{left:-9px}.gantt-milestone .gantt-link-handle.end{left:15px;right:auto}.gantt-task-bar:hover .gantt-link-handle,.gantt-milestone:hover .gantt-link-handle,.gantt-task-bar.selected .gantt-link-handle,.gantt-milestone.selected .gantt-link-handle{opacity:1;pointer-events:auto}.gantt-task-bar.link-target,.gantt-milestone.link-target .gantt-milestone-diamond{outline:2px solid var(--gantt-accent);outline-offset:2px}.gantt-task-bar.link-target.invalid,.gantt-milestone.link-target.invalid .gantt-milestone-diamond{outline-color:var(--gantt-today-marker)}.gantt-link-preview-line{stroke:var(--gantt-accent);stroke-width:2;stroke-dasharray:4 3;fill:none}.gantt-link-preview-line.invalid{stroke:var(--gantt-today-marker)}.gantt-link-preview-origin{fill:var(--gantt-accent)}.gantt-link-preview-reason{fill:var(--gantt-today-marker);font-family:inherit;font-size:11px;font-weight:500;paint-order:stroke;stroke:var(--gantt-background);stroke-width:3px;stroke-linejoin:round}.gantt-content.drawable{cursor:crosshair}.gantt-draw-ghost{position:absolute;top:0;left:0;height:19px;margin-top:9px;background:var(--gantt-accent);opacity:.35;border:1px dashed var(--gantt-accent);border-radius:6px;pointer-events:none;z-index:5}.gantt-task-bar{position:relative;touch-action:pan-x pan-y;z-index:10;display:flex;align-items:center;background:var(--gantt-bar-color, var(--gantt-bar-bg));border-radius:6px;-webkit-user-select:none;user-select:none;cursor:grab;box-shadow:var(--gantt-bar-shadow);transition:background var(--gantt-transition-fast),box-shadow var(--gantt-transition-normal)}.gantt-task-bar:before,.gantt-task-bar:after{content:"";position:absolute;top:50%;width:3px;height:12px;background:var(--gantt-muted-foreground);border-radius:2px;opacity:0;transform:translateY(-50%);transition:opacity var(--gantt-transition-fast)}.gantt-task-bar:before{left:4px}.gantt-task-bar:after{right:4px}.gantt-task-bar:hover{background:var(--gantt-bar-color-hover, var(--gantt-bar-bg-hover));box-shadow:var(--gantt-bar-shadow-hover)}.gantt-task-bar:hover:before,.gantt-task-bar:hover:after{opacity:.5}.gantt-task-bar:active,.gantt-task-bar.dragging{cursor:grabbing;box-shadow:var(--gantt-bar-shadow-drag);z-index:100}.gantt-task-bar.dragging:before,.gantt-task-bar.dragging:after{opacity:.7}.gantt-task-bar.summary{background:var(--gantt-bar-color, var(--gantt-milestone-bg));border-radius:3px}.gantt-task-bar.summary:hover{background:var(--gantt-bar-color-hover, var(--gantt-milestone-bg-hover))}.gantt-task-bar.summary .gantt-task-name{color:var(--gantt-background)}.gantt-task-bar.summary .gantt-task-name.outside{color:var(--gantt-foreground)}.gantt-task-bar.summary .gantt-progress-fill{background:var(--gantt-progress-color, var(--gantt-foreground));opacity:.35;border-radius:3px 0 0 3px}.gantt-task-bar.summary:before,.gantt-task-bar.summary:after,.gantt-task-bar.summary:hover:before,.gantt-task-bar.summary:hover:after{opacity:0}.gantt-baseline{position:absolute;bottom:3px;height:4px;background:var(--gantt-baseline-bg);border-radius:2px;opacity:.65;pointer-events:none}.gantt-baseline.milestone{width:8px;height:8px;bottom:1px;margin-left:-4px;border-radius:1px;transform:rotate(45deg)}.gantt-task-bar.critical{background:var(--gantt-critical-bg)}.gantt-task-bar.critical:hover{background:var(--gantt-critical-bg-hover)}.gantt-task-bar.critical .gantt-task-name{color:var(--gantt-critical-text)}.gantt-task-bar.critical .gantt-task-name.outside{color:var(--gantt-foreground)}.gantt-task-bar.critical .gantt-progress-fill{background:var(--gantt-critical);opacity:.45}.gantt-milestone.critical .gantt-milestone-diamond{background:var(--gantt-critical)}.gantt-dependency-arrow.critical{stroke:var(--gantt-critical);stroke-width:2}.gantt-dependency-arrow-head.critical{fill:var(--gantt-critical)}.gantt-task-bar.selected,.gantt-milestone.selected .gantt-milestone-diamond{outline:2px solid var(--gantt-accent);outline-offset:2px}.gantt-task-bar.reverting,.gantt-milestone.reverting{transition:transform var(--gantt-transition-normal),width var(--gantt-transition-normal),background var(--gantt-transition-fast),box-shadow var(--gantt-transition-normal)}.gantt-task-bar.reverting .gantt-progress-fill,.gantt-task-bar.reverting .gantt-progress-handle{transition:width var(--gantt-transition-normal),left var(--gantt-transition-normal)}.gantt-task-bar.compact:before,.gantt-task-bar.compact:after,.gantt-task-bar.compact:hover:before,.gantt-task-bar.compact:hover:after,.gantt-task-bar.compact.dragging:before,.gantt-task-bar.compact.dragging:after,.gantt-task-bar.no-resize:before,.gantt-task-bar.no-resize:after,.gantt-task-bar.no-resize:hover:before,.gantt-task-bar.no-resize:hover:after,.gantt-task-bar.no-resize.dragging:before,.gantt-task-bar.no-resize.dragging:after{opacity:0}.gantt-progress-fill{position:absolute;top:0;left:0;bottom:0;background:var(--gantt-progress-color, var(--gantt-progress-bg));border-radius:6px 0 0 6px;pointer-events:none}.gantt-progress-handle{position:absolute;top:50%;width:10px;height:10px;margin-left:-5px;background:var(--gantt-background);border:2px solid var(--gantt-progress-handle);border-radius:50%;transform:translateY(-50%);opacity:0;cursor:ew-resize;transition:opacity var(--gantt-transition-fast)}.gantt-task-bar:hover .gantt-progress-handle,.gantt-progress-handle.dragging{opacity:1}@media(hover:none){.gantt-progress-handle{opacity:1}.gantt-progress-handle:before{content:"";position:absolute;top:-17px;right:-17px;bottom:-17px;left:-17px}}.gantt-task-name{position:relative;flex:1;padding:0 14px;font-family:inherit;font-size:12px;font-weight:500;color:var(--gantt-bar-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none}.gantt-task-name.outside{position:absolute;left:100%;flex:none;padding:0 0 0 8px;color:var(--gantt-foreground);overflow:visible}.gantt-milestone{position:relative;touch-action:pan-x pan-y;z-index:10;display:flex;align-items:center;gap:10px;-webkit-user-select:none;user-select:none;cursor:grab}.gantt-milestone-diamond{flex-shrink:0;width:16px;height:16px;background:var(--gantt-bar-color, var(--gantt-milestone-bg));border-radius:3px;transform:rotate(45deg);box-shadow:var(--gantt-bar-shadow);transition:background var(--gantt-transition-fast),box-shadow var(--gantt-transition-normal)}.gantt-milestone:hover .gantt-milestone-diamond{background:var(--gantt-bar-color-hover, var(--gantt-milestone-bg-hover));box-shadow:var(--gantt-bar-shadow-hover)}.gantt-milestone:active,.gantt-milestone.dragging{cursor:grabbing;z-index:100}.gantt-milestone.dragging .gantt-milestone-diamond{box-shadow:var(--gantt-bar-shadow-drag)}.gantt-milestone-name{font-family:inherit;font-size:12px;font-weight:500;color:var(--gantt-foreground);white-space:nowrap;pointer-events:none}.gantt-bar-tooltip{position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%);z-index:200;padding:8px 12px;background:var(--gantt-foreground);color:var(--gantt-background);border-radius:6px;font-family:inherit;font-size:11px;font-weight:500;white-space:nowrap;box-shadow:0 4px 16px #00000026;pointer-events:none;animation:tooltipFadeIn var(--gantt-duration-fast) ease-out}@keyframes tooltipFadeIn{0%{opacity:0;transform:translate(-50%) translateY(-4px)}to{opacity:1;transform:translate(-50%) translateY(0)}}.gantt-bar-tooltip-detail{display:flex;flex-direction:column;gap:2px;text-align:left}.gantt-tooltip-name{font-weight:600}.gantt-tooltip-meta{opacity:.75}.gantt-bar-tooltip:after{content:"";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border:5px solid transparent;border-bottom-color:var(--gantt-foreground)}@media(max-width:768px){.gantt-toolbar{padding:8px 12px}.gantt-scale-button{padding:5px 10px;font-size:11px}.gantt-top-group{--top-group-inset: 12px;font-size:12px}.gantt-bottom-cell{font-size:10px}.gantt-task-name{font-size:11px;padding:0 10px}}.gantt-grid-row.group,.gantt-task-row.group{background:var(--gantt-muted);font-weight:600}.gantt-grid-row.group .gantt-grid-cell{gap:6px}.gantt-group-label{position:sticky;left:0;display:flex;align-items:center;gap:6px;height:100%;padding:0 10px;pointer-events:auto;font-weight:600;white-space:nowrap}.gantt-grid-group-count{flex:none;padding:0 6px;border-radius:999px;background:var(--gantt-border);color:var(--gantt-muted-foreground);font-size:10px;font-weight:600;line-height:16px}.gantt-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;border:0;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}.gantt-container [data-gantt-cell]:focus-visible{outline:2px solid var(--gantt-accent);outline-offset:1px}@media(prefers-reduced-motion:reduce){.gantt-container *,.gantt-container *:before,.gantt-container *:after{transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important}}
|
|
1
|
+
.gantt-container{color-scheme:light;--gantt-detail-width: 320px;--gantt-font-sans: "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont, "Segoe UI", "Geist", system-ui, sans-serif;--gantt-background: #fafafa;--gantt-foreground: #18181b;--gantt-muted: #f4f4f5;--gantt-muted-foreground: #71717a;--gantt-border: #e4e4e7;--gantt-border-subtle: rgba(0, 0, 0, .04);--gantt-bar-bg: #c7c7cd;--gantt-bar-bg-hover: #b4b4bc;--gantt-bar-text: #18181b;--gantt-bar-shadow: none;--gantt-bar-shadow-hover: 0 1px 2px rgba(0, 0, 0, .08);--gantt-bar-shadow-drag: 0 4px 12px rgba(0, 0, 0, .16);--gantt-shadow-overlay: 0 4px 16px rgba(0, 0, 0, .15);--gantt-arrow: #a1a1aa;--gantt-accent: #3b82f6;--gantt-today-marker: #f43f5e;--gantt-summary-bg: #dcdce0;--gantt-summary-bg-hover: #cfcfd4;--gantt-progress-bg: #8e8e97;--gantt-progress-handle: #52525b;--gantt-non-working-bg: rgba(0, 0, 0, .035);--gantt-duration-fast: .15s;--gantt-transition-fast: .15s ease;--gantt-transition-normal: .2s ease}.gantt-container[data-theme=dark]{color-scheme:dark;--gantt-background: #09090b;--gantt-foreground: #fafafa;--gantt-muted: #18181b;--gantt-muted-foreground: #a1a1aa;--gantt-border: #27272a;--gantt-border-subtle: rgba(255, 255, 255, .04);--gantt-bar-bg: #3a3a41;--gantt-bar-bg-hover: #47474f;--gantt-bar-text: #fafafa;--gantt-bar-shadow: none;--gantt-bar-shadow-hover: 0 1px 2px rgba(0, 0, 0, .4);--gantt-bar-shadow-drag: 0 4px 12px rgba(0, 0, 0, .5);--gantt-shadow-overlay: 0 8px 24px rgba(0, 0, 0, .55), 0 0 0 1px rgba(255, 255, 255, .08);--gantt-arrow: #71717a;--gantt-today-marker: #fb7185;--gantt-summary-bg: #2a2a2f;--gantt-summary-bg-hover: #35353c;--gantt-progress-bg: #6c6c76;--gantt-progress-handle: #a1a1aa;--gantt-non-working-bg: rgba(255, 255, 255, .03)}.gantt-container,.gantt-container *,.gantt-container *:before,.gantt-container *:after{box-sizing:border-box}.gantt-container{display:flex;flex-direction:column;overflow:hidden;isolation:isolate;background:var(--gantt-background);font-family:var(--gantt-font-sans);font-size:13px;line-height:1.5;color:var(--gantt-foreground);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.gantt-container:focus{outline:none}.gantt-main{position:relative;flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}.gantt-scroll-container{position:relative;width:100%;flex:1;min-height:0;overflow:auto}.gantt-body{display:flex;align-items:stretch;width:max-content;min-width:100%;min-height:100%}.gantt-timeline{position:relative;flex:1 0 auto;display:flex;flex-direction:column;isolation:isolate}.gantt-grid{position:sticky;left:0;z-index:50;flex:none;display:flex;flex-direction:column;background:var(--gantt-background);border-right:1px solid var(--gantt-border)}.gantt-grid-header{position:sticky;top:0;flex:none;z-index:1;display:flex;align-items:flex-end;padding-bottom:6px;overflow:hidden;background:var(--gantt-background);border-bottom:1px solid var(--gantt-border)}.gantt-grid-header-cell{flex:1;min-width:0;padding:0 10px;font-size:11px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--gantt-muted-foreground);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gantt-grid-body{position:relative}.gantt-grid-row{position:absolute;top:0;left:0;display:flex;width:100%;align-items:center;overflow:hidden;border-bottom:1px solid var(--gantt-border-subtle)}.gantt-grid-row:hover{background:var(--gantt-muted)}.gantt-grid-row.summary{font-weight:600}.gantt-grid-row.selected{background:var(--gantt-muted);box-shadow:inset 2px 0 0 var(--gantt-accent)}.gantt-grid-row.dragging{opacity:.45}.gantt-grid-cell{flex:1;display:flex;align-items:center;min-width:0;padding:0 10px;font-size:12px;color:var(--gantt-foreground)}.gantt-grid-cell-text{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gantt-grid-indent{flex:none}.gantt-grid-no{flex:none;min-width:2.25rem;margin-right:4px;font-size:11px;font-weight:400;font-variant-numeric:tabular-nums;color:var(--gantt-muted-foreground);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gantt-grid-expander{flex:none;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:4px;padding:0;color:var(--gantt-muted-foreground);background:transparent;border:none;border-radius:3px;cursor:pointer}.gantt-grid-expander:hover{color:var(--gantt-foreground);background:var(--gantt-border)}.gantt-grid-expander:focus-visible{outline:2px solid var(--gantt-accent);outline-offset:-2px}.gantt-grid-expander svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;transition:transform var(--gantt-transition-fast)}.gantt-grid-expander.open svg{transform:rotate(90deg)}.gantt-grid-expander-spacer{flex:none;width:20px}.gantt-grid-grip{flex:none;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:4px;padding:0;color:var(--gantt-muted-foreground);background:transparent;border:none;border-radius:3px;opacity:0;cursor:grab;transition:opacity var(--gantt-transition-fast)}.gantt-grid-row:hover .gantt-grid-grip,.gantt-grid-row:focus-within .gantt-grid-grip{opacity:1}.gantt-grid-grip:active{cursor:grabbing}.gantt-grid-grip svg{width:12px;height:12px;fill:currentColor}.gantt-grid-grip-spacer{flex:none;width:20px}.gantt-grid-drop{position:absolute;left:0;right:0;height:2px;margin-top:-1px;color:var(--gantt-accent);background:currentColor;pointer-events:none}.gantt-grid-drop.child{height:auto;margin-top:0;background:none;border-radius:3px;box-shadow:inset 0 0 0 2px currentColor}.gantt-grid-drop.blocked{color:var(--gantt-today-marker)}.gantt-grid-splitter{position:absolute;top:0;bottom:0;z-index:60;width:5px;cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none}.gantt-grid-splitter:hover,.gantt-grid-splitter:focus-visible{background:var(--gantt-accent);opacity:.5;outline:none}.gantt-grid-footer{flex:none;display:flex;align-items:center;height:34px;padding:0 6px;background:var(--gantt-background);border-top:1px solid var(--gantt-border);border-right:1px solid var(--gantt-border)}.gantt-grid-add{display:inline-flex;align-items:center;gap:6px;width:100%;min-width:0;padding:5px 8px;font:inherit;font-size:12px;color:var(--gantt-muted-foreground);text-align:left;white-space:nowrap;overflow:hidden;background:transparent;border:none;border-radius:4px;cursor:pointer}.gantt-grid-add:hover{color:var(--gantt-foreground);background:var(--gantt-muted)}.gantt-grid-add:focus-visible{outline:2px solid var(--gantt-accent);outline-offset:-2px}.gantt-grid-add svg{flex:none;width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round}.gantt-drag-guides{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.gantt-drag-cell{position:absolute;top:44px;height:28px;display:flex;align-items:center;justify-content:center;background:var(--gantt-muted)}.gantt-drag-cell>span{flex:none;padding:0 6px;background:var(--gantt-muted);color:var(--gantt-foreground);font-family:inherit;font-size:11px;font-weight:500;line-height:28px;letter-spacing:.01em;white-space:nowrap}.gantt-drag-footprint{position:absolute;top:49px;height:18px;border-radius:6px;background:color-mix(in srgb,var(--gantt-foreground) 6%,transparent)}.gantt-holiday-labels{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.gantt-holiday-band{position:absolute;top:0;bottom:0;pointer-events:auto}.gantt-holiday-cell{position:absolute;top:44px;height:28px;display:flex;align-items:center;justify-content:center;overflow:hidden;background:var(--gantt-muted);opacity:0;transition:opacity 90ms ease-out}.gantt-holiday-cell.shown,.gantt-holiday-band:hover .gantt-holiday-cell{opacity:1}@media(prefers-reduced-motion:reduce){.gantt-holiday-cell{transition:none}}.gantt-holiday-cell>span{padding:0 6px;color:var(--gantt-foreground);font-family:inherit;font-size:11px;font-weight:500;line-height:28px;letter-spacing:.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.gantt-scroll-container{scrollbar-width:thin;scrollbar-color:var(--gantt-border) transparent}.gantt-scroll-container::-webkit-scrollbar{width:10px;height:10px}.gantt-scroll-container::-webkit-scrollbar-track{background:transparent}.gantt-scroll-container::-webkit-scrollbar-thumb{background:var(--gantt-border);border-radius:5px;border:2px solid var(--gantt-background)}.gantt-scroll-container::-webkit-scrollbar-thumb:hover{background:var(--gantt-muted-foreground)}.gantt-scroll-container::-webkit-scrollbar-corner{background:transparent}.gantt-header-wrapper{position:sticky;top:0;flex:none;z-index:30;min-width:100%}.gantt-header{position:relative;min-width:100%;background:var(--gantt-background);border-bottom:1px solid var(--gantt-border)}.gantt-header-content{display:flex;flex-direction:column}.gantt-top-header{position:relative;display:flex;height:44px;border-bottom:1px solid var(--gantt-border-subtle)}.gantt-top-groups{display:flex}.gantt-top-group{--top-group-inset: 16px;display:flex;align-items:center;padding:0 var(--top-group-inset);font-size:13px;font-weight:600;letter-spacing:-.01em;background:var(--gantt-background);color:var(--gantt-foreground)}.gantt-top-group-label{position:sticky;left:calc(var(--gantt-pane-inset, 0px) + var(--top-group-inset));margin:0;padding:0;white-space:nowrap;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis}.gantt-bottom-row{display:flex;height:28px;background:var(--gantt-muted)}.gantt-bottom-cell{display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:500;color:var(--gantt-muted-foreground);letter-spacing:.01em}.gantt-content{position:relative;min-width:100%;background:var(--gantt-background)}.gantt-non-working-layer{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.gantt-non-working-range{position:absolute;top:0;bottom:0;background:var(--gantt-non-working-bg)}.gantt-rows{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.gantt-task-row{position:absolute;top:0;left:0;display:flex;width:100%;align-items:center;border-bottom:1px solid var(--gantt-border-subtle);pointer-events:none}.gantt-content,.gantt-grid-body{flex:1 0 auto;background-image:repeating-linear-gradient(to bottom,transparent 0,transparent calc(var(--gantt-row-height) - 1px),var(--gantt-border-subtle) calc(var(--gantt-row-height) - 1px),var(--gantt-border-subtle) var(--gantt-row-height))}.gantt-today-marker{position:absolute;top:0;bottom:0;width:1px;background:var(--gantt-today-marker);opacity:.6;pointer-events:none}.gantt-today-dot{position:absolute;bottom:0;width:6px;height:6px;border-radius:50%;background:var(--gantt-today-marker);transform:translate(-50%,50%);pointer-events:none}.gantt-dependency-arrows{position:absolute;top:0;left:0;width:100%;pointer-events:none;z-index:0}.gantt-dependency-arrows.linking{z-index:45}.gantt-dependency-arrows.linking .gantt-dependency-hit,.gantt-dependency-arrows.linking .gantt-dependency-delete{pointer-events:none}.gantt-dependency-arrow{stroke:var(--gantt-arrow);stroke-width:1.5;fill:none;opacity:.45}.gantt-dependency-arrow.selected,.gantt-dependency-arrow.related,.gantt-dependency-hit:hover+.gantt-dependency-arrow{opacity:1}.gantt-dependency-arrow.selected{stroke:var(--gantt-accent);stroke-width:2.5}.gantt-dependency-arrow-head{fill:var(--gantt-arrow);stroke:none}.gantt-dependency-hit{stroke:transparent;stroke-width:12;fill:none;cursor:pointer;pointer-events:stroke}.gantt-dependency-hit:hover+.gantt-dependency-arrow{stroke:var(--gantt-accent)}.gantt-dependency-delete{cursor:pointer;pointer-events:auto}.gantt-dependency-delete circle{fill:var(--gantt-accent)}.gantt-dependency-delete path{stroke:#fff;stroke-width:1.6;stroke-linecap:round}.gantt-link-handle{position:absolute;top:50%;width:12px;height:12px;background:var(--gantt-background);border:2px solid var(--gantt-accent);border-radius:50%;transform:translateY(-50%);opacity:0;cursor:crosshair;touch-action:none;pointer-events:none;transition:opacity var(--gantt-transition-fast)}.gantt-link-handle.start{left:-18px}.gantt-link-handle.end{right:-18px}.gantt-link-handle:before{content:"";position:absolute}.gantt-link-handle.start:before{top:-8px;right:-6px;bottom:-8px;left:-8px}.gantt-link-handle.end:before{top:-8px;right:-8px;bottom:-8px;left:-6px}.gantt-task-bar:hover .gantt-link-handle,.gantt-task-bar.selected .gantt-link-handle{opacity:1;pointer-events:auto}.gantt-task-bar.link-source.link-at-start .gantt-link-handle.start,.gantt-task-bar.link-source.link-at-end .gantt-link-handle.end{opacity:1}@media(hover:none){.gantt-link-handle{opacity:.55;pointer-events:auto}}.gantt-task-bar.link-valid,.gantt-task-bar.link-invalid{outline:2px solid var(--gantt-accent);outline-offset:2px}.gantt-task-bar.link-valid{background:var(--gantt-bar-color-hover, var(--gantt-bar-bg-hover));box-shadow:0 0 0 4px color-mix(in srgb,var(--gantt-accent) 25%,transparent)}.gantt-task-bar.link-invalid{outline-color:var(--gantt-today-marker);box-shadow:none}.gantt-task-bar.link-valid .gantt-link-handle.start,.gantt-task-bar.link-valid .gantt-link-handle.end{opacity:0}.gantt-task-bar.link-valid.link-at-start .gantt-link-handle.start,.gantt-task-bar.link-valid.link-at-end .gantt-link-handle.end{opacity:1;background:var(--gantt-accent)}.gantt-link-preview-line{stroke:var(--gantt-accent);stroke-width:2;stroke-dasharray:4 3;fill:none}.gantt-link-preview-line.armed{stroke-dasharray:none;stroke-width:2.5}.gantt-link-preview-line.invalid{stroke:var(--gantt-today-marker)}.gantt-link-preview-origin{fill:var(--gantt-accent)}.gantt-link-preview-type{fill:var(--gantt-accent);font-family:inherit;font-size:11px;font-weight:600;letter-spacing:.04em;paint-order:stroke;stroke:var(--gantt-background);stroke-width:3px;stroke-linejoin:round}.gantt-link-preview-reason{fill:var(--gantt-today-marker);font-family:inherit;font-size:11px;font-weight:500;paint-order:stroke;stroke:var(--gantt-background);stroke-width:3px;stroke-linejoin:round}.gantt-content.drawable{cursor:crosshair}.gantt-draw-ghost{position:absolute;top:0;left:0;background:var(--gantt-accent);opacity:.35;border:1px dashed var(--gantt-accent);border-radius:6px;pointer-events:none;z-index:5}.gantt-bar-wrap:has(>.gantt-task-bar.has-tooltip){z-index:1}.gantt-bar-wrap:has(>.gantt-task-bar.dragging){z-index:2}.gantt-task-bar{position:relative;touch-action:pan-x pan-y;display:flex;align-items:center;background:var(--gantt-bar-color, var(--gantt-bar-bg));border-radius:6px;-webkit-user-select:none;user-select:none;cursor:grab;box-shadow:var(--gantt-bar-shadow);transition:background var(--gantt-transition-fast),box-shadow var(--gantt-transition-normal)}.gantt-task-bar:before,.gantt-task-bar:after{content:"";position:absolute;top:50%;width:3px;height:12px;background:var(--gantt-muted-foreground);border-radius:2px;opacity:0;transform:translateY(-50%);transition:opacity var(--gantt-transition-fast)}.gantt-task-bar:before{left:4px}.gantt-task-bar:after{right:4px}.gantt-task-bar:hover{background:var(--gantt-bar-color-hover, var(--gantt-bar-bg-hover));box-shadow:var(--gantt-bar-shadow-hover)}.gantt-task-bar:hover:before,.gantt-task-bar:hover:after{opacity:.5}.gantt-task-bar:active,.gantt-task-bar.dragging{cursor:grabbing;box-shadow:var(--gantt-bar-shadow-drag)}.gantt-task-bar.summary{background:var(--gantt-bar-color, var(--gantt-summary-bg));border-radius:3px}.gantt-task-bar.summary:hover{background:var(--gantt-bar-color-hover, var(--gantt-summary-bg-hover))}.gantt-task-bar.summary .gantt-progress-fill{background:var(--gantt-progress-color, var(--gantt-foreground));opacity:.25}.gantt-task-bar.selected{outline:2px solid var(--gantt-accent);outline-offset:2px}.gantt-task-bar.compact:before,.gantt-task-bar.compact:after,.gantt-task-bar.compact:hover:before,.gantt-task-bar.compact:hover:after,.gantt-task-bar.compact.dragging:before,.gantt-task-bar.compact.dragging:after,.gantt-task-bar.no-resize:before,.gantt-task-bar.no-resize:after,.gantt-task-bar.no-resize:hover:before,.gantt-task-bar.no-resize:hover:after,.gantt-task-bar.no-resize.dragging:before,.gantt-task-bar.no-resize.dragging:after{opacity:0}.gantt-progress-fill{position:absolute;top:0;left:0;bottom:0;background:var(--gantt-progress-color, var(--gantt-progress-bg));border-radius:inherit;pointer-events:none}.gantt-progress-handle{position:absolute;top:50%;width:10px;height:10px;margin-left:-5px;background:var(--gantt-background);border:2px solid var(--gantt-progress-handle);border-radius:50%;transform:translateY(-50%);opacity:0;cursor:ew-resize;transition:opacity var(--gantt-transition-fast)}.gantt-task-bar:hover .gantt-progress-handle,.gantt-progress-handle.dragging{opacity:1}@media(hover:none){.gantt-progress-handle{opacity:1}.gantt-progress-handle:before{content:"";position:absolute;top:-17px;right:-17px;bottom:-17px;left:-17px}}.gantt-task-name{position:relative;flex:1;padding:0 14px;font-family:inherit;font-size:12px;font-weight:500;color:var(--gantt-bar-text-color, var(--gantt-bar-text));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;pointer-events:none}.gantt-task-name.outside{position:absolute;left:100%;flex:none;padding:0 0 0 8px;color:var(--gantt-muted-foreground);max-width:160px;overflow:hidden;text-overflow:ellipsis}.gantt-task-bar:hover .gantt-task-name.outside,.gantt-task-bar.selected .gantt-task-name.outside,.gantt-task-bar.dragging .gantt-task-name.outside{color:var(--gantt-foreground)}.gantt-bar-tooltip{position:absolute;top:calc(100% + 8px);left:50%;transform:translate(-50%);padding:8px 12px;background:var(--gantt-foreground);color:var(--gantt-background);border-radius:6px;font-family:inherit;font-size:11px;font-weight:500;white-space:nowrap;box-shadow:var(--gantt-shadow-overlay);pointer-events:none;animation:tooltipFadeIn var(--gantt-duration-fast) ease-out}@keyframes tooltipFadeIn{0%{opacity:0;transform:translate(-50%) translateY(-4px)}to{opacity:1;transform:translate(-50%) translateY(0)}}.gantt-bar-tooltip-detail{display:flex;flex-direction:column;gap:2px;text-align:left}.gantt-tooltip-name{font-weight:600}.gantt-tooltip-meta{opacity:.75}.gantt-bar-tooltip:after{content:"";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border:5px solid transparent;border-bottom-color:var(--gantt-foreground)}@media(max-width:768px){.gantt-top-group{--top-group-inset: 12px;font-size:12px}.gantt-bottom-cell{font-size:10px}.gantt-task-name{font-size:11px;padding:0 10px}}.gantt-grid-lane-count{flex:none;padding:0 6px;border-radius:999px;background:var(--gantt-border);color:var(--gantt-muted-foreground);font-size:10px;font-weight:600;line-height:16px}.gantt-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;border:0;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}.gantt-container [data-gantt-cell]:focus-visible{outline:2px solid var(--gantt-accent);outline-offset:1px}@media(prefers-reduced-motion:reduce){.gantt-container *,.gantt-container *:before,.gantt-container *:after{transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important}}.gantt-layout{display:flex;flex:1;min-height:0}.gantt-detail{position:relative;flex:0 0 0px;display:flex;flex-direction:column;gap:12px;padding:16px 0;overflow:hidden auto;border-left:0 solid var(--gantt-border);background:var(--gantt-background);color:var(--gantt-foreground);transition:flex-basis .2s ease,padding .2s ease,border-left-width .2s ease}.gantt-detail-open{flex-basis:var(--gantt-detail-width);padding:16px;border-left-width:1px}.gantt-detail>*{min-width:calc(var(--gantt-detail-width) - 32px)}.gantt-detail-header{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}.gantt-detail-title{margin:0;font-size:14px;font-weight:600;line-height:1.4}.gantt-detail-close{flex:0 0 auto;padding:2px 6px;border:none;border-radius:4px;background:none;color:var(--gantt-muted-foreground);font-size:13px;line-height:1;cursor:pointer}.gantt-detail-close:hover{background:var(--gantt-muted);color:var(--gantt-foreground)}.gantt-detail-close:focus-visible{outline:2px solid var(--gantt-accent);outline-offset:1px}.gantt-detail-fields{display:grid;grid-template-columns:max-content minmax(0,1fr);gap:8px 16px;margin:0;font-size:12px}.gantt-detail-fields dt{color:var(--gantt-muted-foreground)}.gantt-detail-fields dd{margin:0;overflow-wrap:anywhere}.gantt-detail-input{padding:2px 6px;border:1px solid var(--gantt-border);border-radius:4px;background:var(--gantt-background);color:var(--gantt-foreground);font:inherit;font-size:12px}.gantt-detail-input:focus-visible{outline:2px solid var(--gantt-accent);outline-offset:1px}.gantt-detail-header .gantt-detail-input{flex:1;min-width:0;font-size:14px;font-weight:600}.gantt-detail-fields .gantt-detail-input{width:100%}
|