diff --git a/frontend/src/components/StrategyEditorPage.tsx b/frontend/src/components/StrategyEditorPage.tsx index aac1958..b763c88 100644 --- a/frontend/src/components/StrategyEditorPage.tsx +++ b/frontend/src/components/StrategyEditorPage.tsx @@ -91,6 +91,10 @@ import { type StableStrategyFilterLevel, type StableStrategyId, } from '../utils/stableStrategyPairs'; +import { + buildIchimokuSituationTree, + isIchimokuSituationPaletteValue, +} from '../utils/ichimokuSituationStrategy'; import { buildStochOverboughtPairTree, findStochPairRootInForest, @@ -1367,7 +1371,8 @@ export default function StrategyEditorPage({ const inflection33 = isInflection33PaletteValue(item.value); const ichimokuBb = isIchimokuBbPaletteValue(item.value); const stableStrategy = isStableStrategyPaletteValue(item.value); - const composite = item.kind === 'composite' && !stochPair && !priceExtremeBreakout && !inflection33 && !ichimokuBb && !stableStrategy; + const ichimokuSituation = isIchimokuSituationPaletteValue(item.value); + const composite = item.kind === 'composite' && !stochPair && !priceExtremeBreakout && !inflection33 && !ichimokuBb && !stableStrategy && !ichimokuSituation; const newNode = stochPair ? buildStochOverboughtPairTree(item.secondaryIndicator ?? 'CCI', DEF) : priceExtremeBreakout @@ -1378,6 +1383,8 @@ export default function StrategyEditorPage({ ? buildIchimokuBbTree(item.value, DEF) : stableStrategy ? buildStableStrategyTree(item.value, DEF) + : ichimokuSituation + ? buildIchimokuSituationTree(item.value, DEF) : makeNode('indicator', item.value, signalTab, DEF, composite ? { composite: true } : undefined); if (!newNode) return; handleEditorStateChange(prev => { diff --git a/frontend/src/components/strategyEditor/FlowNodes.tsx b/frontend/src/components/strategyEditor/FlowNodes.tsx index 767d3ac..2126c45 100644 --- a/frontend/src/components/strategyEditor/FlowNodes.tsx +++ b/frontend/src/components/strategyEditor/FlowNodes.tsx @@ -31,6 +31,11 @@ import { inferStableStrategyFilterLevel, type StableStrategyId, } from '../../utils/stableStrategyPairs'; +import { + isIchimokuSituationPairRoot, + ichimokuSituationDisplayName, + type IchimokuSituationId, +} from '../../utils/ichimokuSituationStrategy'; import StableStrategyPairNodeSettings from './StableStrategyPairNodeSettings'; import { isStochOverboughtPairRoot, @@ -241,12 +246,13 @@ export const LogicGateNode = memo(function LogicGateNode({ id, data, selected }: const isInflection33Pair = isInflection33PairRoot(node); const isIchimokuBbPair = isIchimokuBbPairRoot(node); const isStableStrategyPair = isStableStrategyPairRoot(node); + const isIchimokuSituationPair = isIchimokuSituationPairRoot(node); const { onDragEnter, onDragOver, onDragLeave, onDrop } = usePaletteDropHandlers(id, d); const [settingsOpen, setSettingsOpen] = useState(false); return (
)} + {isIchimokuSituationPair && node.ichimokuSituationPair && ( +
+ + {ichimokuSituationDisplayName( + node.ichimokuSituationPair.situationId as IchimokuSituationId, + node.ichimokuSituationPair.mode, + )} + +
+ )} {isInflection33Pair && node.inflection33Pair && (
diff --git a/frontend/src/components/strategyEditor/IndicatorPaletteTab.tsx b/frontend/src/components/strategyEditor/IndicatorPaletteTab.tsx index af691b7..51f6882 100644 --- a/frontend/src/components/strategyEditor/IndicatorPaletteTab.tsx +++ b/frontend/src/components/strategyEditor/IndicatorPaletteTab.tsx @@ -8,6 +8,7 @@ import { isPriceExtremeBreakoutPairPaletteValue } from '../../utils/priceExtreme import { isInflection33PaletteValue } from '../../utils/inflection33Strategy'; import { isIchimokuBbPaletteValue } from '../../utils/ichimokuBbStrategy'; import { isStableStrategyPaletteValue, STABLE_STRATEGY_PALETTE_ITEMS } from '../../utils/stableStrategyPairs'; +import { isIchimokuSituationPaletteValue } from '../../utils/ichimokuSituationStrategy'; import { getDefaultIndicatorPeriod } from '../../utils/conditionPeriods'; import { getStrategyIndicatorDisplayName } from '../../utils/strategyPaletteStorage'; import { getIndicatorPeriodLabel } from '../../utils/strategyFlowLayout'; @@ -39,6 +40,9 @@ function periodLabel(item: PaletteItem, def: DefType): string { const meta = STABLE_STRATEGY_PALETTE_ITEMS.find(i => i.value === item.value); return meta?.periodHint ?? ''; } + if (item.kind === 'composite' && isIchimokuSituationPaletteValue(item.value)) { + return '9 / 26 / 52'; + } if (item.kind === 'composite') { const d = getCompositeDefaultPeriods(item.value, def); return `${d.short} / ${d.long}`; @@ -194,12 +198,14 @@ export default function IndicatorPaletteTab({ && !isPriceExtremeBreakoutPairPaletteValue(item.value) && !isInflection33PaletteValue(item.value) && !isIchimokuBbPaletteValue(item.value) - && !isStableStrategyPaletteValue(item.value)} + && !isStableStrategyPaletteValue(item.value) + && !isIchimokuSituationPaletteValue(item.value)} stochPair={isStochOverboughtPairPaletteValue(item.value)} priceExtremeBreakout={isPriceExtremeBreakoutPairPaletteValue(item.value)} inflection33={isInflection33PaletteValue(item.value)} ichimokuBb={isIchimokuBbPaletteValue(item.value)} stableStrategy={isStableStrategyPaletteValue(item.value)} + ichimokuSituation={isIchimokuSituationPaletteValue(item.value)} secondaryIndicator={item.secondaryIndicator} period={periodLabel(item, def)} periodValue={item.period} diff --git a/frontend/src/components/strategyEditor/PaletteChip.tsx b/frontend/src/components/strategyEditor/PaletteChip.tsx index a9f97a5..f42076a 100644 --- a/frontend/src/components/strategyEditor/PaletteChip.tsx +++ b/frontend/src/components/strategyEditor/PaletteChip.tsx @@ -29,6 +29,7 @@ interface Props { inflection33?: boolean; ichimokuBb?: boolean; stableStrategy?: boolean; + ichimokuSituation?: boolean; secondaryIndicator?: string; selected?: boolean; onSelect?: () => void; @@ -37,7 +38,7 @@ interface Props { export default function PaletteChip({ type, value, label, desc, color, period, periodValue, shortPeriod, longPeriod, - composite = false, stochPair = false, priceExtremeBreakout = false, inflection33 = false, ichimokuBb = false, stableStrategy = false, secondaryIndicator, selected = false, onSelect, onAdd, + composite = false, stochPair = false, priceExtremeBreakout = false, inflection33 = false, ichimokuBb = false, stableStrategy = false, ichimokuSituation = false, secondaryIndicator, selected = false, onSelect, onAdd, }: Props) { const buildPayload = (): PaletteDragPayload => ({ type, value, label, @@ -47,6 +48,7 @@ export default function PaletteChip({ inflection33: inflection33 || undefined, ichimokuBb: ichimokuBb || undefined, stableStrategy: stableStrategy || undefined, + ichimokuSituation: ichimokuSituation || undefined, secondaryIndicator, period: periodValue, shortPeriod, diff --git a/frontend/src/components/strategyEditor/StrategyEditorCanvas.tsx b/frontend/src/components/strategyEditor/StrategyEditorCanvas.tsx index 07b2b1f..5245aa3 100644 --- a/frontend/src/components/strategyEditor/StrategyEditorCanvas.tsx +++ b/frontend/src/components/strategyEditor/StrategyEditorCanvas.tsx @@ -794,6 +794,9 @@ function StrategyEditorCanvasInner({ : n.stableStrategyPair?.mode === 'sell' ? (gateType === 'OR' ? n.stableStrategyPair : undefined) : undefined, + ichimokuSituationPair: n.ichimokuSituationPair + ? n.ichimokuSituationPair + : undefined, } : n ); diff --git a/frontend/src/hooks/useStrategyEvaluationEditor.ts b/frontend/src/hooks/useStrategyEvaluationEditor.ts index ec6b080..9a6c4b0 100644 --- a/frontend/src/hooks/useStrategyEvaluationEditor.ts +++ b/frontend/src/hooks/useStrategyEvaluationEditor.ts @@ -51,6 +51,10 @@ import { buildStableStrategyTree, isStableStrategyPaletteValue, } from '../utils/stableStrategyPairs'; +import { + buildIchimokuSituationTree, + isIchimokuSituationPaletteValue, +} from '../utils/ichimokuSituationStrategy'; import { buildSidewaysFilterNode, loadSidewaysPaletteItems, @@ -453,7 +457,8 @@ export function useStrategyEvaluationEditor({ const inflection33 = isInflection33PaletteValue(item.value); const ichimokuBb = isIchimokuBbPaletteValue(item.value); const stableStrategy = isStableStrategyPaletteValue(item.value); - const composite = item.kind === 'composite' && !stochPair && !priceExtremeBreakout && !inflection33 && !ichimokuBb && !stableStrategy; + const ichimokuSituation = isIchimokuSituationPaletteValue(item.value); + const composite = item.kind === 'composite' && !stochPair && !priceExtremeBreakout && !inflection33 && !ichimokuBb && !stableStrategy && !ichimokuSituation; const newNode = stochPair ? buildStochOverboughtPairTree(item.secondaryIndicator ?? 'CCI', def) : priceExtremeBreakout @@ -464,6 +469,8 @@ export function useStrategyEvaluationEditor({ ? buildIchimokuBbTree(item.value, def) : stableStrategy ? buildStableStrategyTree(item.value, def) + : ichimokuSituation + ? buildIchimokuSituationTree(item.value, def) : makeNode('indicator', item.value, signalTab, def, composite ? { composite: true } : undefined); if (!newNode) return; handleEditorStateChange(prev => { diff --git a/frontend/src/utils/ichimokuSituationStrategy.ts b/frontend/src/utils/ichimokuSituationStrategy.ts new file mode 100644 index 0000000..b3d7cfc --- /dev/null +++ b/frontend/src/utils/ichimokuSituationStrategy.ts @@ -0,0 +1,358 @@ +/** + * 일목균형표 상황별·엘리어트 파동 복합 전략 + * @see 일목균형표 전략.md + */ +import type { ConditionDSL, LogicNode } from './strategyTypes'; +import { initConditionPeriodsInherit, type IndicatorPeriodDef } from './conditionPeriods'; +import { genId } from './strategyNodeIds'; + +export type IchimokuSituationCategory = 'basic' | 'alignment' | 'elliott'; + +export type IchimokuSituationId = + | 'GOLDEN_CROSS' + | 'BASE_BREAKUP' + | 'CLOUD_BREAKUP' + | 'LAGGING_BULL' + | 'CLOUD_SUPPORT' + | 'DEAD_CROSS' + | 'BASE_BREAKDOWN' + | 'CLOUD_BREAKDOWN' + | 'LAGGING_BEAR' + | 'CLOUD_RESISTANCE' + | 'SANYAKU_REVERSE' + | 'HOJEON' + | 'GYEOKJEON' + | 'EW1' + | 'EW2' + | 'EW3' + | 'EW4' + | 'EW5' + | 'EW_A' + | 'EW_B' + | 'EW_C'; + +const SITUATION_PREFIX = 'ICHIMOKU_SIT_'; + +export function ichimokuSituationPaletteValue(id: IchimokuSituationId, mode: 'buy' | 'sell'): string { + return `${SITUATION_PREFIX}${id}_${mode.toUpperCase()}`; +} + +export interface IchimokuSituationPaletteMeta { + value: string; + label: string; + desc: string; + situationId: IchimokuSituationId; + mode: 'buy' | 'sell'; + category: IchimokuSituationCategory; +} + +export const ICHIMOKU_SITUATION_PALETTE_ITEMS: IchimokuSituationPaletteMeta[] = [ + // §2.1 기본 매수 + { value: ichimokuSituationPaletteValue('GOLDEN_CROSS', 'buy'), label: '일목 골든크로스 매수', situationId: 'GOLDEN_CROSS', mode: 'buy', category: 'basic', + desc: 'L1 — 전환선이 기준선 상향 돌파 (호전 1차)' }, + { value: ichimokuSituationPaletteValue('BASE_BREAKUP', 'buy'), label: '일목 기준선 돌파 매수', situationId: 'BASE_BREAKUP', mode: 'buy', category: 'basic', + desc: 'L2 — 종가가 기준선 상향 돌파 (중기 추세 전환)' }, + { value: ichimokuSituationPaletteValue('CLOUD_BREAKUP', 'buy'), label: '일목 구름 돌파 매수', situationId: 'CLOUD_BREAKUP', mode: 'buy', category: 'basic', + desc: 'L3 — 구름대 상향 돌파 (매물·심리 저항 돌파)' }, + { value: ichimokuSituationPaletteValue('LAGGING_BULL', 'buy'), label: '일목 후행 호전 매수', situationId: 'LAGGING_BULL', mode: 'buy', category: 'basic', + desc: 'L4 — 후행스팬 > 26봉 전 종가 (추세 확정)' }, + { value: ichimokuSituationPaletteValue('CLOUD_SUPPORT', 'buy'), label: '일목 구름 지지 매수', situationId: 'CLOUD_SUPPORT', mode: 'buy', category: 'basic', + desc: 'L5 — 종가 > 선행1·기준선 (양운·기준선 지지 반등)' }, + // §1.3 호전 + { value: ichimokuSituationPaletteValue('HOJEON', 'buy'), label: '일목 호전(정배열) 매수', situationId: 'HOJEON', mode: 'buy', category: 'alignment', + desc: '괘·구름 위·양운·후행 — 완벽한 상승 추세 4조건' }, + // §2.2 기본 매도 + { value: ichimokuSituationPaletteValue('DEAD_CROSS', 'sell'), label: '일목 데드크로스 매도', situationId: 'DEAD_CROSS', mode: 'sell', category: 'basic', + desc: 'S1 — 전환선이 기준선 하향 이탈' }, + { value: ichimokuSituationPaletteValue('BASE_BREAKDOWN', 'sell'), label: '일목 기준선 이탈 매도', situationId: 'BASE_BREAKDOWN', mode: 'sell', category: 'basic', + desc: 'S2 — 종가가 기준선 하향 이탈' }, + { value: ichimokuSituationPaletteValue('CLOUD_BREAKDOWN', 'sell'), label: '일목 구름 이탈 매도', situationId: 'CLOUD_BREAKDOWN', mode: 'sell', category: 'basic', + desc: 'S3 — 구름대 하향 이탈 (지지 붕괴)' }, + { value: ichimokuSituationPaletteValue('LAGGING_BEAR', 'sell'), label: '일목 후행 역전 매도', situationId: 'LAGGING_BEAR', mode: 'sell', category: 'basic', + desc: 'S4 — 후행스팬 < 26봉 전 종가' }, + { value: ichimokuSituationPaletteValue('CLOUD_RESISTANCE', 'sell'), label: '일목 구름 저항 매도', situationId: 'CLOUD_RESISTANCE', mode: 'sell', category: 'basic', + desc: 'S5 — 종가 < 선행1·기준선 (음운·기준선 저항)' }, + { value: ichimokuSituationPaletteValue('SANYAKU_REVERSE', 'sell'), label: '일목 삼역역전 매도', situationId: 'SANYAKU_REVERSE', mode: 'sell', category: 'alignment', + desc: 'S6 — 데드 + 구름 아래 + 후행 역전 (강력 청산)' }, + { value: ichimokuSituationPaletteValue('GYEOKJEON', 'sell'), label: '일목 역전(역배열) 매도', situationId: 'GYEOKJEON', mode: 'sell', category: 'alignment', + desc: '괘·구름 아래·음운·후행 — 완벽한 하락 추세 4조건' }, + // §4 엘리어트 파동 + { value: ichimokuSituationPaletteValue('EW1', 'buy'), label: '일목 1파 매수', situationId: 'EW1', mode: 'buy', category: 'elliott', + desc: '추세 전환 시동 — 기준선 돌파 + 전환>기준 (소액·분할)' }, + { value: ichimokuSituationPaletteValue('EW2', 'buy'), label: '일목 2파 매수', situationId: 'EW2', mode: 'buy', category: 'elliott', + desc: '눌림목 — 기준선·구름하단(선행2) 지지 + 전환>기준' }, + { value: ichimokuSituationPaletteValue('EW2', 'sell'), label: '일목 2파 손절', situationId: 'EW2', mode: 'sell', category: 'elliott', + desc: '2파 지지 이탈 — 기준선 이탈 OR 구름 하향 돌파' }, + { value: ichimokuSituationPaletteValue('EW3', 'buy'), label: '일목 3파 매수', situationId: 'EW3', mode: 'buy', category: 'elliott', + desc: '본격 상승 — 삼역호전(괘·구름·후행·양운) 불타기' }, + { value: ichimokuSituationPaletteValue('EW4', 'buy'), label: '일목 4파 재매수', situationId: 'EW4', mode: 'buy', category: 'elliott', + desc: '횡보 조정 — 구름 상단(선행1)·기준선 지지 반등' }, + { value: ichimokuSituationPaletteValue('EW4', 'sell'), label: '일목 4파 익절', situationId: 'EW4', mode: 'sell', category: 'elliott', + desc: '4파 조정 — 기준선 이탈 OR 구름 하향 이탈' }, + { value: ichimokuSituationPaletteValue('EW5', 'sell'), label: '일목 5파 분할매도', situationId: 'EW5', mode: 'sell', category: 'elliott', + desc: '과열 — 전환선·데드·구름 이탈 (분할 청산)' }, + { value: ichimokuSituationPaletteValue('EW_A', 'sell'), label: '일목 A파 매도', situationId: 'EW_A', mode: 'sell', category: 'elliott', + desc: '하락 개시 — 기준선·데드크로스' }, + { value: ichimokuSituationPaletteValue('EW_B', 'sell'), label: '일목 B파 매도', situationId: 'EW_B', mode: 'sell', category: 'elliott', + desc: '기술적 반등 실패 — 기준선·음운 저항 (전량 대피)' }, + { value: ichimokuSituationPaletteValue('EW_C', 'sell'), label: '일목 C파 매도', situationId: 'EW_C', mode: 'sell', category: 'elliott', + desc: '본 하락 — 삼역역전 + 구름 이탈 (물타기 금지)' }, +]; + +const VALUE_TO_META: Record = + Object.fromEntries(ICHIMOKU_SITUATION_PALETTE_ITEMS.map(i => [i.value, { situationId: i.situationId, mode: i.mode }])); + +export function isIchimokuSituationPaletteValue(value: string): boolean { + return value.startsWith(SITUATION_PREFIX) && value in VALUE_TO_META; +} + +export function isIchimokuSituationPairRoot(node: LogicNode): boolean { + return !!node.ichimokuSituationPair?.situationId + && (node.type === 'AND' || node.type === 'OR'); +} + +function makeIch( + def: IndicatorPeriodDef, + conditionType: string, + leftField: string, + rightField: string, + extra?: Partial, +): LogicNode { + const base: ConditionDSL = { + indicatorType: 'ICHIMOKU', + conditionType, + leftField, + rightField, + candleRange: 1, + valuePeriodOverride: false, + thresholdOverride: false, + rightPeriodOverride: false, + ...extra, + }; + return { + id: genId(), + type: 'CONDITION', + condition: initConditionPeriodsInherit('ICHIMOKU', base, def), + }; +} + +function pairMeta( + situationId: IchimokuSituationId, + mode: 'buy' | 'sell', +): LogicNode['ichimokuSituationPair'] { + return { situationId, mode }; +} + +function wrapAnd(children: LogicNode[], meta: LogicNode['ichimokuSituationPair']): LogicNode { + return { id: genId(), type: 'AND', ichimokuSituationPair: meta, children }; +} + +function wrapOr(children: LogicNode[], meta: LogicNode['ichimokuSituationPair']): LogicNode { + return { id: genId(), type: 'OR', ichimokuSituationPair: meta, children }; +} + +type Builder = (def: IndicatorPeriodDef) => LogicNode; + +const BUILDERS: Record>> = { + GOLDEN_CROSS: { + buy: def => wrapAnd([ + makeIch(def, 'CROSS_UP', 'CONVERSION_LINE', 'BASE_LINE'), + ], pairMeta('GOLDEN_CROSS', 'buy')), + }, + BASE_BREAKUP: { + buy: def => wrapAnd([ + makeIch(def, 'CROSS_UP', 'CLOSE_PRICE', 'BASE_LINE'), + ], pairMeta('BASE_BREAKUP', 'buy')), + }, + CLOUD_BREAKUP: { + buy: def => wrapAnd([ + makeIch(def, 'CLOUD_BREAK_UP', 'CLOSE_PRICE', 'NONE'), + ], pairMeta('CLOUD_BREAKUP', 'buy')), + }, + LAGGING_BULL: { + buy: def => wrapAnd([ + makeIch(def, 'LAGGING_GT_PRICE', 'LAGGING_SPAN', 'CLOSE_PRICE'), + ], pairMeta('LAGGING_BULL', 'buy')), + }, + CLOUD_SUPPORT: { + buy: def => wrapAnd([ + makeIch(def, 'GT', 'CLOSE_PRICE', 'LEADING_SPAN1'), + makeIch(def, 'GT', 'CLOSE_PRICE', 'BASE_LINE'), + ], pairMeta('CLOUD_SUPPORT', 'buy')), + }, + HOJEON: { + buy: def => wrapAnd([ + makeIch(def, 'GT', 'CONVERSION_LINE', 'BASE_LINE'), + makeIch(def, 'ABOVE_CLOUD', 'CLOSE_PRICE', 'NONE'), + makeIch(def, 'SPAN1_GT_SPAN2', 'LEADING_SPAN1', 'LEADING_SPAN2'), + makeIch(def, 'LAGGING_GT_PRICE', 'LAGGING_SPAN', 'CLOSE_PRICE'), + ], pairMeta('HOJEON', 'buy')), + }, + DEAD_CROSS: { + sell: def => wrapOr([ + makeIch(def, 'CROSS_DOWN', 'CONVERSION_LINE', 'BASE_LINE'), + ], pairMeta('DEAD_CROSS', 'sell')), + }, + BASE_BREAKDOWN: { + sell: def => wrapOr([ + makeIch(def, 'CROSS_DOWN', 'CLOSE_PRICE', 'BASE_LINE'), + ], pairMeta('BASE_BREAKDOWN', 'sell')), + }, + CLOUD_BREAKDOWN: { + sell: def => wrapOr([ + makeIch(def, 'CLOUD_BREAK_DOWN', 'CLOSE_PRICE', 'NONE'), + ], pairMeta('CLOUD_BREAKDOWN', 'sell')), + }, + LAGGING_BEAR: { + sell: def => wrapOr([ + makeIch(def, 'LAGGING_LT_PRICE', 'LAGGING_SPAN', 'CLOSE_PRICE'), + ], pairMeta('LAGGING_BEAR', 'sell')), + }, + CLOUD_RESISTANCE: { + sell: def => wrapAnd([ + makeIch(def, 'LT', 'CLOSE_PRICE', 'LEADING_SPAN1'), + makeIch(def, 'LT', 'CLOSE_PRICE', 'BASE_LINE'), + ], pairMeta('CLOUD_RESISTANCE', 'sell')), + }, + SANYAKU_REVERSE: { + sell: def => wrapAnd([ + makeIch(def, 'LT', 'CONVERSION_LINE', 'BASE_LINE'), + makeIch(def, 'BELOW_CLOUD', 'CLOSE_PRICE', 'NONE'), + makeIch(def, 'LAGGING_LT_PRICE', 'LAGGING_SPAN', 'CLOSE_PRICE'), + ], pairMeta('SANYAKU_REVERSE', 'sell')), + }, + GYEOKJEON: { + sell: def => wrapAnd([ + makeIch(def, 'LT', 'CONVERSION_LINE', 'BASE_LINE'), + makeIch(def, 'BELOW_CLOUD', 'CLOSE_PRICE', 'NONE'), + makeIch(def, 'SPAN1_LT_SPAN2', 'LEADING_SPAN1', 'LEADING_SPAN2'), + makeIch(def, 'LAGGING_LT_PRICE', 'LAGGING_SPAN', 'CLOSE_PRICE'), + ], pairMeta('GYEOKJEON', 'sell')), + }, + EW1: { + buy: def => wrapAnd([ + makeIch(def, 'CROSS_UP', 'CLOSE_PRICE', 'BASE_LINE'), + makeIch(def, 'GT', 'CONVERSION_LINE', 'BASE_LINE'), + ], pairMeta('EW1', 'buy')), + }, + EW2: { + buy: def => wrapAnd([ + makeIch(def, 'GT', 'CLOSE_PRICE', 'BASE_LINE'), + makeIch(def, 'GT', 'CLOSE_PRICE', 'LEADING_SPAN2'), + makeIch(def, 'GT', 'CONVERSION_LINE', 'BASE_LINE'), + ], pairMeta('EW2', 'buy')), + sell: def => wrapOr([ + makeIch(def, 'CROSS_DOWN', 'CLOSE_PRICE', 'BASE_LINE'), + makeIch(def, 'CLOUD_BREAK_DOWN', 'CLOSE_PRICE', 'NONE'), + ], pairMeta('EW2', 'sell')), + }, + EW3: { + buy: def => wrapAnd([ + makeIch(def, 'GT', 'CONVERSION_LINE', 'BASE_LINE'), + makeIch(def, 'ABOVE_CLOUD', 'CLOSE_PRICE', 'NONE'), + makeIch(def, 'LAGGING_GT_PRICE', 'LAGGING_SPAN', 'CLOSE_PRICE'), + makeIch(def, 'SPAN1_GT_SPAN2', 'LEADING_SPAN1', 'LEADING_SPAN2'), + ], pairMeta('EW3', 'buy')), + }, + EW4: { + buy: def => wrapAnd([ + makeIch(def, 'GT', 'CLOSE_PRICE', 'LEADING_SPAN1'), + makeIch(def, 'GT', 'CONVERSION_LINE', 'BASE_LINE'), + ], pairMeta('EW4', 'buy')), + sell: def => wrapOr([ + makeIch(def, 'CROSS_DOWN', 'CLOSE_PRICE', 'BASE_LINE'), + makeIch(def, 'CLOUD_BREAK_DOWN', 'CLOSE_PRICE', 'NONE'), + ], pairMeta('EW4', 'sell')), + }, + EW5: { + sell: def => wrapOr([ + makeIch(def, 'CROSS_DOWN', 'CLOSE_PRICE', 'CONVERSION_LINE'), + makeIch(def, 'CROSS_DOWN', 'CONVERSION_LINE', 'BASE_LINE'), + makeIch(def, 'CLOUD_BREAK_DOWN', 'CLOSE_PRICE', 'NONE'), + ], pairMeta('EW5', 'sell')), + }, + EW_A: { + sell: def => wrapOr([ + makeIch(def, 'CROSS_DOWN', 'CLOSE_PRICE', 'BASE_LINE'), + makeIch(def, 'CROSS_DOWN', 'CONVERSION_LINE', 'BASE_LINE'), + ], pairMeta('EW_A', 'sell')), + }, + EW_B: { + sell: def => wrapAnd([ + makeIch(def, 'LT', 'CLOSE_PRICE', 'BASE_LINE'), + makeIch(def, 'BELOW_CLOUD', 'CLOSE_PRICE', 'NONE'), + makeIch(def, 'LT', 'CONVERSION_LINE', 'BASE_LINE'), + ], pairMeta('EW_B', 'sell')), + }, + EW_C: { + sell: def => wrapAnd([ + makeIch(def, 'CLOUD_BREAK_DOWN', 'CLOSE_PRICE', 'NONE'), + makeIch(def, 'BELOW_CLOUD', 'CLOSE_PRICE', 'NONE'), + makeIch(def, 'LT', 'CONVERSION_LINE', 'BASE_LINE'), + makeIch(def, 'LAGGING_LT_PRICE', 'LAGGING_SPAN', 'CLOSE_PRICE'), + ], pairMeta('EW_C', 'sell')), + }, +}; + +export function ichimokuSituationMetaFromValue(value: string): { situationId: IchimokuSituationId; mode: 'buy' | 'sell' } | null { + return VALUE_TO_META[value] ?? null; +} + +export function buildIchimokuSituationTree(value: string, def: IndicatorPeriodDef): LogicNode | null { + const meta = ichimokuSituationMetaFromValue(value); + if (!meta) return null; + const builder = BUILDERS[meta.situationId][meta.mode]; + return builder ? builder(def) : null; +} + +export function ichimokuSituationDisplayName(situationId: IchimokuSituationId, mode: 'buy' | 'sell'): string { + const item = ICHIMOKU_SITUATION_PALETTE_ITEMS.find( + i => i.situationId === situationId && i.mode === mode, + ); + return item?.label ?? `${situationId} ${mode === 'buy' ? '매수' : '매도'}`; +} + +export function ichimokuSituationPaletteDesc(value: string): string { + return ICHIMOKU_SITUATION_PALETTE_ITEMS.find(i => i.value === value)?.desc ?? ''; +} + +const COND_LABEL: Record = { + CROSS_UP: '상향돌파', CROSS_DOWN: '하향돌파', + GT: '>', LT: '<', + ABOVE_CLOUD: '구름 위', BELOW_CLOUD: '구름 아래', + CLOUD_BREAK_UP: '구름 상향돌파', CLOUD_BREAK_DOWN: '구름 하향이탈', + SPAN1_GT_SPAN2: '양운', SPAN1_LT_SPAN2: '음운', + LAGGING_GT_PRICE: '후행>26봉전 종가', LAGGING_LT_PRICE: '후행<26봉전 종가', +}; + +function fmtNode(n: LogicNode): string { + if (n.type === 'CONDITION' && n.condition) { + const c = n.condition; + const op = COND_LABEL[c.conditionType] ?? c.conditionType; + return `${c.leftField} ${op} ${c.rightField ?? ''}`.trim(); + } + if (n.type === 'AND' || n.type === 'OR') { + return (n.children ?? []).map(fmtNode).join(` ${n.type} `); + } + return ''; +} + +export function ichimokuSituationSummaryText( + situationId: IchimokuSituationId, + mode: 'buy' | 'sell', + def: IndicatorPeriodDef = { + rsiPeriod: 14, cciPeriod: 20, adxPeriod: 14, williamsR: 14, + trixPeriod: 12, vrPeriod: 26, psyPeriod: 12, newPsy: 12, investPsy: 12, + }, +): string { + const tree = BUILDERS[situationId][mode]?.(def); + return tree ? fmtNode(tree) : ''; +} + +export function ichimokuSituationCategoryLabel(cat: IchimokuSituationCategory): string { + switch (cat) { + case 'basic': return '기본'; + case 'alignment': return '호전·역전'; + case 'elliott': return '엘리어트'; + } +} diff --git a/frontend/src/utils/strategyEditorShared.tsx b/frontend/src/utils/strategyEditorShared.tsx index 00ebe74..09b636a 100644 --- a/frontend/src/utils/strategyEditorShared.tsx +++ b/frontend/src/utils/strategyEditorShared.tsx @@ -63,6 +63,14 @@ import { stableStrategyFilterLevelLabel, type StableStrategyId, } from '../utils/stableStrategyPairs'; +import { + buildIchimokuSituationTree, + isIchimokuSituationPairRoot, + isIchimokuSituationPaletteValue, + ichimokuSituationDisplayName, + ichimokuSituationSummaryText, + type IchimokuSituationId, +} from '../utils/ichimokuSituationStrategy'; import { buildPriceExtremeBreakoutTree, isPriceExtremeBreakoutPairPaletteValue, @@ -1015,6 +1023,10 @@ export const nodeToText = (node: LogicNode, DEF: DefType = DEF_DEFAULTS): string const cfg = inferIchimokuBbConfig(node); return `${ichimokuBbDisplayName(cfg.mode, cfg.chikouDisplacement)}\n${ichimokuBbSummaryText(cfg)}`; } + if (isIchimokuSituationPairRoot(node) && node.ichimokuSituationPair) { + const { situationId, mode } = node.ichimokuSituationPair; + return `${ichimokuSituationDisplayName(situationId as IchimokuSituationId, mode)}\n${ichimokuSituationSummaryText(situationId as IchimokuSituationId, mode, DEF)}`; + } if (isPriceExtremeBreakoutPairRoot(node) && node.priceExtremePair) { const { mode, shortPeriod, longPeriod } = node.priceExtremePair; const level = inferPriceExtremeFilterLevel(node); @@ -1038,6 +1050,10 @@ export const nodeToText = (node: LogicNode, DEF: DefType = DEF_DEFAULTS): string const cfg = inferIchimokuBbConfig(node); return `${ichimokuBbDisplayName(cfg.mode, cfg.chikouDisplacement)}\n${ichimokuBbSummaryText(cfg)}`; } + if (isIchimokuSituationPairRoot(node) && node.ichimokuSituationPair) { + const { situationId, mode } = node.ichimokuSituationPair; + return `${ichimokuSituationDisplayName(situationId as IchimokuSituationId, mode)}\n${ichimokuSituationSummaryText(situationId as IchimokuSituationId, mode, DEF)}`; + } if (isStochOverboughtPairRoot(node)) { const sec = node.stochPair!.secondaryIndicatorType; return `${stochPairDisplayName(sec)}\n${stochPairSummaryText(sec)}`; @@ -1565,6 +1581,8 @@ export type MakeNodeOptions = { ichimokuBb?: boolean; /** 추천 안정형 전략 복합 */ stableStrategy?: boolean; + /** 일목균형표 상황별·엘리어트 복합 */ + ichimokuSituation?: boolean; }; /** 팔레트 드래그 payload → makeNode 옵션 */ @@ -1575,6 +1593,7 @@ export function makeNodeOptionsFromPalette(data: { inflection33?: boolean; ichimokuBb?: boolean; stableStrategy?: boolean; + ichimokuSituation?: boolean; secondaryIndicator?: string; period?: number; shortPeriod?: number; @@ -1601,6 +1620,9 @@ export function makeNodeOptionsFromPalette(data: { if (data.stableStrategy || (data.value && isStableStrategyPaletteValue(data.value))) { return { stableStrategy: true }; } + if (data.ichimokuSituation || (data.value && isIchimokuSituationPaletteValue(data.value))) { + return { ichimokuSituation: true }; + } if (data.composite) { return { composite: true, @@ -1638,6 +1660,10 @@ export const makeNode = ( const tree = buildStableStrategyTree(value, DEF); if (tree) return tree; } + if (options?.ichimokuSituation || isIchimokuSituationPaletteValue(value)) { + const tree = buildIchimokuSituationTree(value, DEF); + if (tree) return tree; + } if (options?.composite) { let condition = makeCompositeCondition(value, signalType, DEF); condition = { diff --git a/frontend/src/utils/strategyEditorTemplatePaletteRows.ts b/frontend/src/utils/strategyEditorTemplatePaletteRows.ts index e2c7a2d..3de8728 100644 --- a/frontend/src/utils/strategyEditorTemplatePaletteRows.ts +++ b/frontend/src/utils/strategyEditorTemplatePaletteRows.ts @@ -12,6 +12,7 @@ import { isNewLow920SellPaletteValue, } from './priceExtremeBreakoutPair'; import { STABLE_STRATEGY_PALETTE_ITEMS } from './stableStrategyPairs'; +import { ichimokuSituationMetaFromValue } from './ichimokuSituationStrategy'; export type TemplatePaletteSource = | 'user' @@ -50,6 +51,8 @@ export function inferCompositePaletteSignal(item: PaletteItem): 'buy' | 'sell' { } const stable = STABLE_STRATEGY_PALETTE_ITEMS.find(s => s.value === item.value); if (stable) return stable.mode; + const ichimokuSit = ichimokuSituationMetaFromValue(item.value); + if (ichimokuSit) return ichimokuSit.mode; if (item.value.endsWith('_BUY')) return 'buy'; if (item.value.endsWith('_SELL')) return 'sell'; return 'buy'; diff --git a/frontend/src/utils/strategyEvaluationTemplateApply.ts b/frontend/src/utils/strategyEvaluationTemplateApply.ts index 4074f28..5bcc9bf 100644 --- a/frontend/src/utils/strategyEvaluationTemplateApply.ts +++ b/frontend/src/utils/strategyEvaluationTemplateApply.ts @@ -26,6 +26,10 @@ import { buildStableStrategyTree, isStableStrategyPaletteValue, } from './stableStrategyPairs'; +import { + buildIchimokuSituationTree, + isIchimokuSituationPaletteValue, +} from './ichimokuSituationStrategy'; import { buildSidewaysFilterNode, loadSidewaysPaletteItems, @@ -71,18 +75,21 @@ function buildLogicNodeFromPaletteItem( const inflection33 = isInflection33PaletteValue(item.value); const ichimokuBb = isIchimokuBbPaletteValue(item.value); const stableStrategy = isStableStrategyPaletteValue(item.value); + const ichimokuSituation = isIchimokuSituationPaletteValue(item.value); const composite = item.kind === 'composite' && !stochPair && !priceExtremeBreakout && !inflection33 && !ichimokuBb - && !stableStrategy; + && !stableStrategy + && !ichimokuSituation; if (stochPair) return buildStochOverboughtPairTree(item.secondaryIndicator ?? 'CCI', def); if (priceExtremeBreakout) return buildPriceExtremeBreakoutTree(item.value, def); if (inflection33) return buildInflection33Tree(item.value, def); if (ichimokuBb) return buildIchimokuBbTree(item.value, def); if (stableStrategy) return buildStableStrategyTree(item.value, def); + if (ichimokuSituation) return buildIchimokuSituationTree(item.value, def); return makeNode('indicator', item.value, signalTab, def, composite ? { composite: true } : undefined); } diff --git a/frontend/src/utils/strategyPaletteStorage.ts b/frontend/src/utils/strategyPaletteStorage.ts index 0547c12..004c3b3 100644 --- a/frontend/src/utils/strategyPaletteStorage.ts +++ b/frontend/src/utils/strategyPaletteStorage.ts @@ -18,6 +18,9 @@ import { import { STABLE_STRATEGY_PALETTE_ITEMS, } from './stableStrategyPairs'; +import { + ICHIMOKU_SITUATION_PALETTE_ITEMS, +} from './ichimokuSituationStrategy'; import { NEW_HIGH_9_20_BUY_VALUE, NEW_LOW_9_20_SELL_VALUE, @@ -125,6 +128,12 @@ export const DEFAULT_COMPOSITE_ITEMS: Omit[] = [ builtIn: true, period: 26, }, + ...ICHIMOKU_SITUATION_PALETTE_ITEMS.map(i => ({ + value: i.value, + label: i.label, + desc: `[${i.category === 'basic' ? '기본' : i.category === 'alignment' ? '호전·역전' : '엘리어트'}] ${i.desc}`, + builtIn: true, + })), ...STABLE_STRATEGY_PALETTE_ITEMS.map(i => ({ value: i.value, label: i.label, diff --git a/frontend/src/utils/strategyTypes.ts b/frontend/src/utils/strategyTypes.ts index b6baec6..70e7016 100644 --- a/frontend/src/utils/strategyTypes.ts +++ b/frontend/src/utils/strategyTypes.ts @@ -80,6 +80,11 @@ export interface LogicNode { bbBand: 'UPPER_BAND' | 'MIDDLE_BAND' | 'LOWER_BAND'; conditionType: 'CROSS_UP' | 'CROSS_DOWN' | 'GT' | 'LT'; }; + /** 일목균형표 상황별·엘리어트 파동 복합 — @see 일목균형표 전략.md */ + ichimokuSituationPair?: { + situationId: string; + mode: 'buy' | 'sell'; + }; } export interface StrategyDSLDto { diff --git a/visible-ars/package-lock.json b/visible-ars/package-lock.json new file mode 100644 index 0000000..fb1b87f --- /dev/null +++ b/visible-ars/package-lock.json @@ -0,0 +1,2680 @@ +{ + "name": "visible-ars", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "visible-ars", + "version": "1.0.0", + "dependencies": { + "lucide-react": "^0.468.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.28.0" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.3.1", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.49", + "tailwindcss": "^3.4.15", + "vite": "^5.4.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@remix-run/router": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.3.tgz", + "integrity": "sha512-4An71tdz9X8+3sI4Qqqd2LWd9vS39J7sqd9EU4Scw7TJE/qB10Flv/UuqbPVgfQV9XoK8Np6jNquZitnZq5i+Q==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.5.1", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.1.tgz", + "integrity": "sha512-jwM2pcTuCWUoN70FEvf5XrXyDbUgRURK4FnU8v0jWZZYU/KkVvN9T33mu1sVLFY9JW3kTWzKheEpn6xYLRc/VA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.4", + "caniuse-lite": "^1.0.30001799", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.38", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", + "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", + "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.38", + "caniuse-lite": "^1.0.30001799", + "electron-to-chromium": "^1.5.376", + "node-releases": "^2.0.48", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.378", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.378.tgz", + "integrity": "sha512-VinvOAuuPmdD1guEgGv5f2Qp7/vlfqOrUOMYNnOD4wj3pit8kRsQHzfIf6teyUGWo15Tg5+bOJaRunvyltpVWQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.468.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.468.0.tgz", + "integrity": "sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.49", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.49.tgz", + "integrity": "sha512-f06bl1D+8ZDkn2oOQQKAh5/otFWqVnM1Q5oerA8Pex7UfT66Tx4IPHIqVVFKqFT3FUtaDstdgkM7yT7JWhqxfw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", + "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "6.30.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.4.tgz", + "integrity": "sha512-SVUsDe+DybHM/WmYKIVYhZh1o5Dcuf16yM6WjG02Q9XVFMZIJyHYhwrr6bFBXZkVP6z69kNkMyBCujt8FaFLJA==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.30.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.4.tgz", + "integrity": "sha512-q4HvNl+mmDdkS0g+MqiBZNteQJCuimWoOyHMy4T/RQLAn9Z29+E91QXRaxOujeMl2HTzRSS0KFPd7lxX3PjV0Q==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.3", + "react-router": "6.30.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/visible-ars/tailwind.config.js b/visible-ars/tailwind.config.js new file mode 100644 index 0000000..67ba788 --- /dev/null +++ b/visible-ars/tailwind.config.js @@ -0,0 +1,56 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./index.html', './src/**/*.{js,jsx}'], + darkMode: 'class', + theme: { + extend: { + colors: { + trust: { + DEFAULT: '#0047AB', + 50: '#E8F0FA', + 100: '#C5D9F2', + 600: '#0047AB', + 700: '#003A8C', + 800: '#002D6D', + }, + safety: { + DEFAULT: '#28A745', + 50: '#E8F5EC', + 600: '#28A745', + 700: '#1E7E34', + }, + emergency: { + red: '#DC3545', + orange: '#FD7E14', + }, + }, + fontFamily: { + sans: ['Pretendard', '-apple-system', 'BlinkMacSystemFont', 'system-ui', 'sans-serif'], + }, + boxShadow: { + card: '0 2px 12px rgba(0, 71, 171, 0.08)', + 'card-dark': '0 2px 16px rgba(0, 0, 0, 0.35)', + }, + animation: { + 'fade-in': 'fadeIn 0.35s ease-out', + 'slide-up': 'slideUp 0.35s ease-out', + wave: 'wave 1.2s ease-in-out infinite', + }, + keyframes: { + fadeIn: { + '0%': { opacity: '0' }, + '100%': { opacity: '1' }, + }, + slideUp: { + '0%': { opacity: '0', transform: 'translateY(12px)' }, + '100%': { opacity: '1', transform: 'translateY(0)' }, + }, + wave: { + '0%, 100%': { transform: 'scaleY(0.4)' }, + '50%': { transform: 'scaleY(1)' }, + }, + }, + }, + }, + plugins: [], +}; diff --git a/일목균형표 전략.md b/일목균형표 전략.md new file mode 100644 index 0000000..45f9695 --- /dev/null +++ b/일목균형표 전략.md @@ -0,0 +1,397 @@ +# 일목균형표(Ichimoku Kinko Hyo) 전략 — 구성 요소·매매 로직·엘리어트 파동 연계 + +goldenChart **투자전략 DSL**의 `ICHIMOKU` 지표 조건과 연동하여, 일목균형표의 시간·가격 균형 관계와 엘리어트 파동(Elliott Wave) 단계별 전략 조건을 정리한 문서입니다. + +> **관련 문서:** [매매전략조건.md](./매매전략조건.md) · [전략편집기 로직 및 동작흐름.md](./전략편집기%20로직%20및%20동작흐름.md) +> **내장 템플릿:** `ICHIMOKU_TREND` · `ICHIMOKU_SANYAKU`(삼역호전) · `ICHIMOKU_PERFECT`(5원소) + +--- + +## 1. 일목균형표란 + +일목균형표는 **과거·현재·미래**의 가격 균형을 한 차트(일목)에 담은 추세·지지·저항 통합 지표입니다. +단순 이동평균 교차가 아니라, **선행(구름)·후행(26봉 지연)** 개념으로 시장의 “시간적 균형”을 읽습니다. + +### 1.1 핵심 구성 요소 + +| 구성 요소 | DSL 필드 | 계산 (표준 9·26·52) | 시장에서의 역할 | +|-----------|----------|---------------------|-----------------| +| **전환선** (Conversion Line) | `CONVERSION_LINE` | (9봉 최고+최저) ÷ 2 | 단기 균형점. 주가의 **단기 방향·속도** | +| **기준선** (Base Line) | `BASE_LINE` | (26봉 최고+최저) ÷ 2 | 중기 균형점. **추세 그 자체**, 강한 지지·저항 | +| **선행스팬 1** (Leading Span 1) | `LEADING_SPAN1` | (전환선+기준선) ÷ 2, **26봉 선행** | 단·중기 평균을 미래로 투영 → **구름 상·하단** | +| **선행스팬 2** (Leading Span 2) | `LEADING_SPAN2` | (52봉 최고+최저) ÷ 2, **26봉 선행** | 장기 균형점 → **구름 두께**·매물대 강도 | +| **구름대** (Kumo / Cloud) | `LEADING_SPAN1` ↔ `LEADING_SPAN2` | 선행1·2 사이 영역 | 지지(양운) / 저항(음운) **매물·심리 경계** | +| **후행스팬** (Lagging Span) | `LAGGING_SPAN` | 현재 종가를 **26봉 후행** 표시 | 현재 vs 26봉 전 종가 비교 → **추세 확정** | + +### 1.2 구성 요소 간 관계 (개념도) + +```text + [미래] ← 선행스팬1·2 (26봉 앞) + ╱╲ 구름대 (Kumo) + ╱ ╲ + 전환선 ────●────●────●──── (9봉, 가장 민감) + 기준선 ────────●────●──── (26봉, 추세의 중심) + 종가 ──────────●──────── (현재) + 후행 ────────────────●── (종가를 26봉 뒤에 표시) + [과거] +``` + +| 관계 | 의미 | 해석 | +|------|------|------| +| 전환선 ↔ 기준선 | 단기 vs 중기 균형 | 교차 = **추세 전환 1차 신호** | +| 선행1 vs 선행2 | 구름 색·두께 | 선행1>선행2 → **양운**(상승 구름), 반대 → **음운** | +| 종가 vs 구름 | 현재가 위치 | 구름 위 = 강세, 아래 = 약세, 내부 = **전환·횡보** | +| 후행 vs 26봉 전 종가 | 시간 지연 확인 | 후행이 과거 종가 위 = **상승 추세 확정** | + +### 1.3 호전(정배열) vs 역전(역배열) + +#### 🟩 호전 — 완벽한 상승 추세 + +```text +종가 > 전환선 > 기준선 > 구름(양운) +후행스팬 > 26봉 전 종가 +(선택) 후행스팬 > 26봉 전 구름 +``` + +| 확인 항목 | DSL 조건 예시 | +|-----------|---------------| +| 괘(가격선) | `CONVERSION_LINE GT BASE_LINE` | +| 주가·구름 | `CLOSE_PRICE ABOVE_CLOUD` | +| 구름 성격 | `SPAN1_GT_SPAN2` (양운) | +| 후행 확정 | `LAGGING_GT_PRICE` | + +#### 🟥 역전 — 완벽한 하락 추세 + +```text +종가 < 전환선 < 기준선 < 구름(음운) +후행스팬 < 26봉 전 종가 +``` + +| 확인 항목 | DSL 조건 예시 | +|-----------|---------------| +| 괘 | `CONVERSION_LINE LT BASE_LINE` | +| 주가·구름 | `CLOSE_PRICE BELOW_CLOUD` | +| 구름 성격 | `SPAN1_LT_SPAN2` (음운) | +| 후행 확정 | `LAGGING_LT_PRICE` | + +--- + +## 2. 상황별 기본 매수·매도 판단 로직 + +### 2.1 매수(Long) 타이밍 + +| # | 상황 | 판단 근거 | DSL 조건 (예) | 강도 | +|---|------|-----------|---------------|------| +| L1 | **골든크로스(호전)** | 전환선이 기준선 상향 돌파 | `CONVERSION_LINE CROSS_UP BASE_LINE` | ★★★ | +| L2 | **기준선 돌파** | 중기 추세 전환 | `CLOSE_PRICE CROSS_UP BASE_LINE` | ★★★ | +| L3 | **구름 돌파** | 매물대·심리 저항 돌파 | `CLOUD_BREAK_UP` | ★★★★ | +| L4 | **후행 호전** | 26봉 전 대비 추세 확정 | `LAGGING_GT_PRICE` (또는 `CROSS_UP`) | ★★★★ | +| L5 | **구름 지지** | 양운 상단·기준선에서 반등 | `CLOSE_PRICE GT LEADING_SPAN1` + `GT BASE_LINE` | ★★ | +| L6 | **삼역호전** | ①괘 ②구름 ③후행 동시 | 아래 §3.3 참조 | ★★★★★ | + +**매수 시 주의** + +- 구름 **내부**(`IN_CLOUD`)에서는 신호 빈도↑·신뢰도↓ → 필터(거래량·ADX) 권장. +- `CROSS_*` 조건은 **해당 봉 1회**만 true → 연속 보유는 `GT`/`ABOVE_CLOUD` 등 **상태 조건** 병행. + +### 2.2 매도(Short / 청산) 타이밍 + +| # | 상황 | 판단 근거 | DSL 조건 (예) | 강도 | +|---|------|-----------|---------------|------| +| S1 | **데드크로스(역전)** | 전환선 기준선 하향 이탈 | `CONVERSION_LINE CROSS_DOWN BASE_LINE` | ★★★ | +| S2 | **기준선 이탈** | 중기 추세 붕괴 | `CLOSE_PRICE CROSS_DOWN BASE_LINE` | ★★★ | +| S3 | **구름 이탈** | 지지 붕괴 | `CLOUD_BREAK_DOWN` | ★★★★ | +| S4 | **후행 역전** | 하락 추세 확정 | `LAGGING_LT_PRICE` | ★★★★ | +| S5 | **구름 저항** | 음운 하단·기준선에서 반락 | `CLOSE_PRICE LT LEADING_SPAN1` + `LT BASE_LINE` | ★★ | +| S6 | **삼역역전** | ①데드 ②구름하 ③후행하 | §3.3 역방향 | ★★★★★ | + +**매도(청산) 설계 팁** + +- 추세 추종: `OR(데드크로스, 종가<전환선, 구름하향돌파)` — **연속 매도 방지**. +- 익절: 5파·과열 구간에서는 전환선 이탈만으로도 1차 청산 신호로 사용. + +### 2.3 구름·선행스팬 해석 요약 + +| 구름 상태 | 선행1 vs 선행2 | 종가 위치 | 일반적 해석 | +|-----------|----------------|-----------|-------------| +| **양운** | 선행1 > 선행2 | 종가 > 구름 | 상승 추세, 구름 = **지지** | +| **음운** | 선행1 < 선행2 | 종가 < 구름 | 하락 추세, 구름 = **저항** | +| **얇은 구름** | 두 선행 간격 좁음 | 돌파 직후 | 변곡·추세 전환 **임박** | +| **두꺼운 구름** | 두 선행 간격 넓음 | 구름 안·근처 | **강한 매물대**, 돌파 난이도↑ | + +--- + +## 3. 삼역호전 / 삼역역전 — 핵심 복합 신호 + +### 3.1 삼역호전 (三役好轉) — 강력 매수 + +| 역(役) | 일목 요소 | 조건 | +|--------|-----------|------| +| **괘** | 전환·기준 | 전환선 > 기준선 (또는 골든크로스) | +| **주가** | 종가·구름 | 종가 > 구름 (`ABOVE_CLOUD` / `CLOUD_BREAK_UP`) | +| **후행** | 후행·과거 종가 | 후행 > 26봉 전 종가 (`LAGGING_GT_PRICE`) | + +**goldenChart 템플릿:** `ICHIMOKU_SANYAKU` — 구름 돌파(현재 봉) + 단계별 필터(N봉 EXISTS_IN). + +### 3.2 삼역역전 — 강력 매도·대피 + +| 역 | 조건 | +|----|------| +| 괘 | 전환선 < 기준선 (데드크로스) | +| 주가 | 종가 < 구름 (`BELOW_CLOUD` / `CLOUD_BREAK_DOWN`) | +| 후행 | 후행 < 26봉 전 종가 (`LAGGING_LT_PRICE`) | + +### 3.3 5원소 입체 매매 (Perfect Ichimoku) + +괘 · 주가 · 구름(양/음운) · 후행 **4중 AND** — ta4j `PerfectIchimokuStrategy` 동형. + +**goldenChart 템플릿:** `ICHIMOKU_PERFECT` (필터 강도에 따라 2~4조건). + +--- + +## 4. 엘리어트 파동 × 일목균형표 — 단계별 전략 조건 + +엘리어트 파동의 **추세 전개**와 일목의 **선행·후행 시간 구조**를 결합하면, 파동 단계별 진입·청산 근거를 명확히 할 수 있습니다. + +> **전제:** 아래 “파동”은 **추정**이며, 실전에서는 상위·하위 시간대 일목을 함께 봅니다. +> 조건은 goldenChart DSL로 표현 가능한 형태로 기술합니다. + +--- + +### 4.1 1파 — 상승 시동 (추세 전환 시작) + +| 항목 | 내용 | +|------|------| +| **파동 특징** | 장기 하락 종료 후 첫 반등. 바닥 예측 난이도 **최고** | +| **일목 상태** | 하락하던 전환·기준선을 **순차 돌파** 시작. 위에는 **두터운 음운**이 여전히 존재 | +| **관계** | 종가 ≈ 전환선 근처, 기준선 **미돌파 또는 돌파 직후**, 구름 **아래·내부** | + +**전략 조건** + +| 구분 | 조건 | DSL 예시 | +|------|------|----------| +| 공격적 매수 | 기준선 상향 돌파 | `CLOSE_PRICE CROSS_UP BASE_LINE` | +| 보조 확인 | 전환 > 기준 | `CONVERSION_LINE GT BASE_LINE` | +| 필터(권장) | 아직 구름 아래면 **소액·분할** | `NOT ABOVE_CLOUD` → 포지션 축소 | +| 매도/관망 | 음운 하단 저항 | `CLOSE_PRICE LT LEADING_SPAN2` 유지 시 추가 매수 자제 | + +**판단:** 삼역호전 **미충족** → `ICHIMOKU_TREND`(골든크로스) 수준만 허용, `SANYAKU`/`PERFECT`는 **대기**. + +--- + +### 4.2 2파 — 첫 번째 조정 (눌림목) + +| 항목 | 내용 | +|------|------| +| **파동 특징** | 1파 되돌림(종종 50~61.8%). **마지막 저가 테스트** | +| **일목 상태** | 주가 재하락하나 **선행2(구름 하단)·과거 바닥** 미이탈. 전환·기준 **수평 방어** | +| **관계** | 종가 > 기준선 또는 구름 하단(선행2) **지지** | + +**전략 조건** + +| 구분 | 조건 | DSL 예시 | +|------|------|----------| +| **1차 적극 매수** | 기준선·구름 하단 지지 후 반등 | `CLOSE_PRICE GT BASE_LINE` AND `CLOSE_PRICE GT LEADING_SPAN2` | +| 확인 | 전환 > 기준 유지 | `CONVERSION_LINE GT BASE_LINE` | +| 손절 | 기준선·선행2 동시 이탈 | `CLOSE_PRICE CROSS_DOWN BASE_LINE` OR `CLOUD_BREAK_DOWN` | +| 금지 | 후행 아직 미호전 | `LAGGING_LT_PRICE` 지속 시 **풀매수 금지** | + +**판단:** **2파 끝 = 기준선/양운 상단 지지** → 3파 전 **핵심 분할 매수 구간**. + +--- + +### 4.3 3파 — 본격 상승 (핵심 수익 구간) + +| 항목 | 내용 | +|------|------| +| **파동 특징** | 거래량·길이 **최대**. 추세 추종 수익 **극대화** 구간 | +| **일목 상태** | **삼역호전 완성**. 얇은 구름 돌파 → 앞선 **두터운 양운** | +| **관계** | 종가 > 전환 > 기준 > 구름, 후행 > 26봉 전 종가·구름 | + +**전략 조건 (삼역호전 = 3파 확인)** + +```text +AND( + CONVERSION_LINE GT BASE_LINE, /* 괘 */ + CLOSE_PRICE ABOVE_CLOUD, /* 주가 — 또는 CLOUD_BREAK_UP */ + LAGGING_GT_PRICE, /* 후행 */ + SPAN1_GT_SPAN2 /* 양운 (선택) */ +) +``` + +| 구분 | 전략 | +|------|------| +| **매수** | 삼역호전 충족 시 **추가 매수·불타기** (`ICHIMOKU_SANYAKU` / `PERFECT`) | +| **보유** | 종가 > **전환선** 유지 → **매도 금지** (추세 타기) | +| **청산 경고** | 전환선 이탈 **전**까지 보유 극대화 | +| **손절** | `CLOUD_BREAK_DOWN` 또는 `CONVERSION_LINE CROSS_DOWN BASE_LINE` | + +**판단:** �lliott **3파 ≈ 일목 삼역호전** — 시스템상 **가장 신뢰도 높은 롱 구간**. + +--- + +### 4.4 4파 — 조정 (복잡한 횡보) + +| 항목 | 내용 | +|------|------| +| **파동 특징** | 삼각형·횡보. 변동성↑, 방향성 혼란 | +| **일목 상태** | 급등 후 **기준선 지지 테스트**. 일시 **구름 내부** 진입 가능 | +| **관계** | 종가 ≈ 기준선 · 선행1(구름 상단). 전환·기준 **수렴** | + +**전략 조건** + +| 구분 | 조건 | DSL 예시 | +|------|------|----------| +| 일부 익절 | 기준선 이탈 | `CLOSE_PRICE CROSS_DOWN BASE_LINE` | +| 재매수 | 구름 **상단(선행1)** 지지 | `CLOSE_PRICE GT LEADING_SPAN1` AND `IN_CLOUD` 또는 `ABOVE_CLOUD` 회복 | +| 관망 | 구름 내부 장기 체류 | `IN_CLOUD` + `HOLD_N_DAYS` → 방향 재확인 전 **신규 진입 자제** | +| 손절 | 구름 하단 이탈 | `CLOUD_BREAK_DOWN` | + +**판단:** **단기 매매** 구간. 추세 추종은 포지션 **축소**, 스윙만 선행1·기준선 지지에서 재진입. + +--- + +### 4.5 5파 — 마지막 상승 (과열·분산 매도) + +| 항목 | 내용 | +|------|------| +| **파동 특징** | 신고가 갱신 but **모멘텀 둔화**. 대중 **후행 참여** | +| **일목 상태** | 종가·전환·기준 **이격 과대**. 후행은 위에 있으나 **꺾임** 조짐. 구름 **얇아짐** | +| **관계** | `DIFF_GT(종가, 전환선)` 과열 · `SPAN1`/`SPAN2` 간격 축소 | + +**전략 조건** + +| 구분 | 조건 | 전략 | +|------|------|------| +| 분할 매도 | 신고가 + 전환선과 이격 확대 | `CLOSE_PRICE GT CONVERSION_LINE` + `DIFF_GT` (임계값) | +| 1차 청산 | **전환선 이탈** | `CLOSE_PRICE CROSS_DOWN CONVERSION_LINE` | +| 2차 청산 | 데드크로스 | `CONVERSION_LINE CROSS_DOWN BASE_LINE` | +| 전량 익절 | 구름 재진입·하향 | `CLOUD_BREAK_DOWN` 또는 `BELOW_CLOUD` | + +**판단:** **매수 금지** · 보유분 **점진적 분할 매도**. 3파와 달리 **전환선 = 생명선**. + +--- + +### 4.6 A-B-C 조정파 — 하락 전환 + +#### A파 (하락 개시) + +| 일목 | 조건 | +|------|------| +| 기준선 **강한 이탈** | `CLOSE_PRICE CROSS_DOWN BASE_LINE` | +| 데드크로스 | `CONVERSION_LINE CROSS_DOWN BASE_LINE` | +| 전략 | **신규 매수 중단**, 5파 잔량 **청산 가속** | + +#### B파 (기술적 반등) + +| 일목 | 조건 | +|------|------| +| 반등하나 **기준선·음운 하단** 저항 | `CLOSE_PRICE CROSS_UP BASE_LINE` 후 `LT BASE_LINE` 재이탈 | +| 구름 | `BELOW_CLOUD` 유지, `CLOUD_BREAK_UP` **실패** | +| 전략 | 기준선 터치 후 **전량 매도·대피** (가짜 반등) | + +**DSL 예시 (B파 저항 확인):** + +```text +AND( + CLOSE_PRICE LT BASE_LINE, + BELOW_CLOUD, + CONVERSION_LINE LT BASE_LINE +) +``` + +#### C파 (본 하락) + +| 일목 | 조건 | +|------|------| +| 구름 완전 이탈 | `CLOUD_BREAK_DOWN` + `BELOW_CLOUD` | +| 삼역역전 | 데드 + 구름 아래 + `LAGGING_LT_PRICE` | +| 전략 | **물타기 금지**, 현금·인버스. `ICHIMOKU_SANYAKU` 매도 OR 조건 활용 | + +--- + +## 5. 파동 × 일목 — 한눈에 보는 매매 매트릭스 + +| 파동 | 일목 핵심 상태 | 매수 | 매도/청산 | goldenChart 템플릿 참고 | +|------|----------------|------|-----------|-------------------------| +| **1파** | 기준선 돌파 시도, 음운 위 | 소액·분할 | 관망 | `ICHIMOKU_TREND` (relaxed) | +| **2파** | 기준선·선행2 지지 | **적극 1차 매수** | 지지 이탈 시 손절 | `TREND` + 구름 하단 `GT` | +| **3파** | **삼역호전** | **추가·불타기** | 전환선 이탈 전 보유 | `ICHIMOKU_SANYAKU` / `PERFECT` | +| **4파** | 기준선·구름 상단 횡보 | 지지 확인 시만 | 기준선 이탈 익절 | `IN_CLOUD` 필터 | +| **5파** | 이격 과열, 얇은 구름 | **금지** | 전환선·데드 **분할 매도** | `CROSS_DOWN` 전환선 | +| **A파** | 기준선 붕괴 | 금지 | 잔량 청산 | `TREND` sell | +| **B파** | 기준선·음운 저항 | 금지 | **전량 매도** | `BELOW_CLOUD` + `LT BASE` | +| **C파** | 삼역역전 | 금지 | 대피·숏 | `ICHIMOKU_SIT_EW_C_SELL` | + +> **복합지표 팔레트:** `ICHIMOKU_SIT_*` — 기본(L1~S6)·호전·역전·엘리어트(1~5·A~C) 파동별 매수/매도 조건 세트 (전략편집기 복합지표 탭) + +--- + +## 6. goldenChart 전략편집기 적용 가이드 + +### 6.1 내장 템플릿 매핑 + +| 템플릿 | 적합 파동 | 핵심 조건 | +|--------|-----------|-----------| +| `ICHIMOKU_TREND` | 1파·2파·A파 | 전환↔기준 골든/데드 + (선택) 구름 | +| `ICHIMOKU_SANYAKU` | **3파** | 구름 돌파 + 후행·전환 필터 | +| `ICHIMOKU_PERFECT` | 3파 (strict) | 4중 AND — 신호↓ 품질↑ | +| `ICHIMOKU_BB` | 4파·5파 | 후행 vs 볼린저 — 변동성·과열 | + +### 6.2 필터 강도 권장 (파동별) + +| 파동 | `relaxed` | `balanced` | `strict` | +|------|-----------|------------|----------| +| 1~2파 | ○ 진입 탐색 | △ | ✕ (과도) | +| **3파** | △ | **○** | ○ (확신 시) | +| 4~5파 | — (매수 X) | 청산 보조 | 익절 강화 | +| A~C파 | — | 매도 | **삼역역전** | + +### 6.3 조건 설계 시 유의사항 + +1. **`CROSS_*` vs `GT/LT`:** 돌파 **트리거**는 CROSS, **보유**는 GT/ABOVE_CLOUD. +2. **EXISTS_IN 윈도우:** 삼역호전 보조 필터에만 사용 — 트리거에 쓰면 시그널 과다. +3. **멀티 타임프레임:** 3파 확인 = 상위 TF `ABOVE_CLOUD` + 하위 TF `CROSS_UP` 조합 권장. +4. **엘리어트 병행:** 파동 카운트는 주관적 → 일목 **상태 조건**으로 객관화. + +--- + +## 7. 요약 — 판단 흐름도 + +```text +[하락/바닥] 1파: 기준선 돌파? ──No──→ 관망 + │ + Yes (소액) + ↓ + 2파: 기준선·선행2 지지? ──No──→ 손절 + │ + Yes (1차 매수) + ↓ + 3파: 삼역호전? ──No──→ 대기/추가 관망 + │ + Yes (적극 매수·보유) + ↓ + 4파: 기준선·구름상단 지지? → 재매수 or 일부익절 + ↓ + 5파: 전환선 이탈? → 분할 매도 + ↓ + A-B-C: 기준선 저항·삼역역전? → 전량 청산·대피 +``` + +--- + +## 8. 참고 — 표준 기간 (9 · 26 · 52) + +| 요소 | 기간 | 시간축 의미 | +|------|------|-------------| +| 전환선 | 9 | 단기 (약 1.5주, 일봉 기준) | +| 기준선 | 26 | 중기 (약 1달) | +| 선행스팬 | 26 선행 | **1달 앞** 매물·심리 | +| 선행2 | 52 | 장기 (약 2.5달) | +| 후행 | 26 후행 | **1달 전**과 현재 비교 | + +분봉(3m·15m) 사용 시 동일 비율을 유지하되, `ICHIMOKU_SANYAKU` 템플릿의 EXISTS_IN 윈도우(N봉)를 **타임프레임에 맞게** 조절합니다. + +--- + +*문서 버전: 2026-03 · goldenChart 전략 DSL `ICHIMOKU` 조건셋 기준*